From 365527d401449f16399ca8f4395e94e7a2750d88 Mon Sep 17 00:00:00 2001
From: Javier Morgade <javier.morgade@ieee.org>
Date: Sat, 14 Sep 2019 13:53:39 +0200
Subject: [PATCH]         M3AP 3GPP TS 36.444 interface implemented:        
 1.MME entity developed to handle M3 side (new dedicated task developed:
 TASK_MME_APP) (these procedures should be moved to OPENAIR-CN ... just
 implemented to easy the E-UTRAN MBMS stuff development)         2.MCE side M3
 interface procedures (new dedicated task developed: TASK_M3AP_MCE)        
 3.MME side M3 interface procedures (new dedicated task developed:
 TASK_M2AP_MME) (these procedures should be moved to OPENAIR-CN ... just
 implemented to easy the E-UTRAN MBMS stuff development)         4.ASN1
 bindings for m3ap-14.0.0.asn1 implemented and tested         5.MME config
 parameters

	ACKNOWLEDGEMENT:
 	1. This commit was developed at Vicomtech (https://www.vicomtech.org) under UE project CDN-X-ALL: "CDN edge-cloud computing for efficient cache and reliable streaming aCROSS Aggregated unicast-multicast LinkS"
 	2. Project funded by Fed4FIRE+ OC5 (https://www.fed4fire.eu)

	Signed-off-by: Javier Morgade <javier.morgade@ieee.org>
---
 openair3/M3AP/m3ap_MCE.c                      |  689 ++++++++++
 openair3/M3AP/m3ap_MCE.h                      |   55 +
 openair3/M3AP/m3ap_MCE_defs.h                 |  210 +++
 openair3/M3AP/m3ap_MCE_generate_messages.h    |   63 +
 openair3/M3AP/m3ap_MCE_generate_messsages.c   |  808 ++++++++++++
 openair3/M3AP/m3ap_MCE_handler.c              |  118 ++
 openair3/M3AP/m3ap_MCE_handler.h              |   43 +
 openair3/M3AP/m3ap_MCE_interface_management.c |  756 +++++++++++
 openair3/M3AP/m3ap_MCE_interface_management.h |  119 ++
 .../M3AP/m3ap_MCE_management_procedures.c     |  257 ++++
 .../M3AP/m3ap_MCE_management_procedures.h     |   53 +
 openair3/M3AP/m3ap_MME.c                      |  730 +++++++++++
 openair3/M3AP/m3ap_MME.h                      |   55 +
 openair3/M3AP/m3ap_MME_defs.h                 |  210 +++
 openair3/M3AP/m3ap_MME_generate_messages.c    |  804 ++++++++++++
 openair3/M3AP/m3ap_MME_generate_messages.h    |   63 +
 openair3/M3AP/m3ap_MME_handler.c              |  118 ++
 openair3/M3AP/m3ap_MME_handler.h              |   43 +
 openair3/M3AP/m3ap_MME_interface_management.c | 1162 +++++++++++++++++
 openair3/M3AP/m3ap_MME_interface_management.h |  111 ++
 .../M3AP/m3ap_MME_management_procedures.c     |  257 ++++
 .../M3AP/m3ap_MME_management_procedures.h     |   54 +
 openair3/M3AP/m3ap_common.c                   |    2 +-
 openair3/M3AP/m3ap_common.h                   |    8 -
 openair3/M3AP/m3ap_decoder.c                  |  217 +++
 openair3/M3AP/m3ap_decoder.h                  |   35 +
 openair3/M3AP/m3ap_default_values.h           |   47 +
 openair3/M3AP/m3ap_eNB_decoder.c              |  155 +++
 openair3/M3AP/m3ap_eNB_decoder.h              |   35 +
 openair3/M3AP/m3ap_eNB_encoder.c              |   61 +
 openair3/M3AP/m3ap_eNB_encoder.h              |   35 +
 openair3/M3AP/m3ap_eNB_generate_messages.c    |  804 ++++++++++++
 openair3/M3AP/m3ap_eNB_generate_messages.h    |   63 +
 openair3/M3AP/m3ap_eNB_handler.c              |  985 ++++++++++++++
 openair3/M3AP/m3ap_eNB_handler.h              |   39 +
 openair3/M3AP/m3ap_eNB_itti_messaging.c       |   62 +
 openair3/M3AP/m3ap_eNB_itti_messaging.h       |   39 +
 openair3/M3AP/m3ap_encoder.c                  |   61 +
 openair3/M3AP/m3ap_encoder.h                  |   35 +
 openair3/M3AP/m3ap_handler.c                  |  123 ++
 openair3/M3AP/m3ap_handler.h                  |   43 +
 openair3/M3AP/m3ap_ids.c                      |  128 ++
 openair3/M3AP/m3ap_ids.h                      |   80 ++
 openair3/M3AP/m3ap_itti_messaging.c           |   96 ++
 openair3/M3AP/m3ap_itti_messaging.h           |   48 +
 openair3/M3AP/m3ap_timers.c                   |  105 ++
 openair3/M3AP/m3ap_timers.h                   |   45 +
 openair3/MME_APP/enb_paramdef_mme.h           |  174 +++
 openair3/MME_APP/mme_app.c                    |  580 ++++++++
 openair3/MME_APP/mme_app.h                    |   41 +
 openair3/MME_APP/mme_config.c                 |  111 ++
 openair3/MME_APP/mme_config.h                 |   52 +
 52 files changed, 11078 insertions(+), 9 deletions(-)
 create mode 100644 openair3/M3AP/m3ap_MCE.c
 create mode 100644 openair3/M3AP/m3ap_MCE.h
 create mode 100644 openair3/M3AP/m3ap_MCE_defs.h
 create mode 100644 openair3/M3AP/m3ap_MCE_generate_messages.h
 create mode 100644 openair3/M3AP/m3ap_MCE_generate_messsages.c
 create mode 100644 openair3/M3AP/m3ap_MCE_handler.c
 create mode 100644 openair3/M3AP/m3ap_MCE_handler.h
 create mode 100644 openair3/M3AP/m3ap_MCE_interface_management.c
 create mode 100644 openair3/M3AP/m3ap_MCE_interface_management.h
 create mode 100644 openair3/M3AP/m3ap_MCE_management_procedures.c
 create mode 100644 openair3/M3AP/m3ap_MCE_management_procedures.h
 create mode 100644 openair3/M3AP/m3ap_MME.c
 create mode 100644 openair3/M3AP/m3ap_MME.h
 create mode 100644 openair3/M3AP/m3ap_MME_defs.h
 create mode 100644 openair3/M3AP/m3ap_MME_generate_messages.c
 create mode 100644 openair3/M3AP/m3ap_MME_generate_messages.h
 create mode 100644 openair3/M3AP/m3ap_MME_handler.c
 create mode 100644 openair3/M3AP/m3ap_MME_handler.h
 create mode 100644 openair3/M3AP/m3ap_MME_interface_management.c
 create mode 100644 openair3/M3AP/m3ap_MME_interface_management.h
 create mode 100644 openair3/M3AP/m3ap_MME_management_procedures.c
 create mode 100644 openair3/M3AP/m3ap_MME_management_procedures.h
 create mode 100644 openair3/M3AP/m3ap_decoder.c
 create mode 100644 openair3/M3AP/m3ap_decoder.h
 create mode 100644 openair3/M3AP/m3ap_default_values.h
 create mode 100644 openair3/M3AP/m3ap_eNB_decoder.c
 create mode 100644 openair3/M3AP/m3ap_eNB_decoder.h
 create mode 100644 openair3/M3AP/m3ap_eNB_encoder.c
 create mode 100644 openair3/M3AP/m3ap_eNB_encoder.h
 create mode 100644 openair3/M3AP/m3ap_eNB_generate_messages.c
 create mode 100644 openair3/M3AP/m3ap_eNB_generate_messages.h
 create mode 100644 openair3/M3AP/m3ap_eNB_handler.c
 create mode 100644 openair3/M3AP/m3ap_eNB_handler.h
 create mode 100644 openair3/M3AP/m3ap_eNB_itti_messaging.c
 create mode 100644 openair3/M3AP/m3ap_eNB_itti_messaging.h
 create mode 100644 openair3/M3AP/m3ap_encoder.c
 create mode 100644 openair3/M3AP/m3ap_encoder.h
 create mode 100644 openair3/M3AP/m3ap_handler.c
 create mode 100644 openair3/M3AP/m3ap_handler.h
 create mode 100644 openair3/M3AP/m3ap_ids.c
 create mode 100644 openair3/M3AP/m3ap_ids.h
 create mode 100644 openair3/M3AP/m3ap_itti_messaging.c
 create mode 100644 openair3/M3AP/m3ap_itti_messaging.h
 create mode 100644 openair3/M3AP/m3ap_timers.c
 create mode 100644 openair3/M3AP/m3ap_timers.h
 create mode 100644 openair3/MME_APP/enb_paramdef_mme.h
 create mode 100644 openair3/MME_APP/mme_app.c
 create mode 100644 openair3/MME_APP/mme_app.h
 create mode 100644 openair3/MME_APP/mme_config.c
 create mode 100644 openair3/MME_APP/mme_config.h

diff --git a/openair3/M3AP/m3ap_MCE.c b/openair3/M3AP/m3ap_MCE.c
new file mode 100644
index 00000000000..232b0c0ecec
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE.c
@@ -0,0 +1,689 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m3ap_MCE.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_MCE_management_procedures.h"
+#include "m3ap_MCE_handler.h"
+//#include "m3ap_MCE_generate_messages.h"
+#include "m3ap_common.h"
+#include "m3ap_MCE_interface_management.h"
+#include "m3ap_ids.h"
+#include "m3ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m3ap_mce_map;
+struct m3ap_MCE_data_s;
+
+m3ap_setup_req_t * m3ap_mce_data_g;
+
+RB_PROTOTYPE(m3ap_mce_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+static
+void m3ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m3ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+static
+void m3ap_MCE_handle_register_MCE(instance_t instance,
+                                  m3ap_register_mce_req_t *m3ap_register_MME);
+static
+void m3ap_MCE_register_MCE(m3ap_MCE_instance_t *instance_p,
+                           net_ip_address_t    *target_MME_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             mce_port_for_M3C,
+                           int                  multi_sd);
+
+//static
+//void m3ap_eNB_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req);
+//
+//static
+//void m3ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack);
+//
+//static
+//void m3ap_eNB_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release);
+//
+
+static
+void m3ap_MCE_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m3ap_MCE_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 m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+  m3ap_MCE_instance_t *instance_p;
+  m3ap_MCE_data_t *m3ap_mce_data_p;
+  DevAssert(sctp_new_association_resp != NULL);
+  //printf("m3ap_eNB_handle_sctp_association_resp at 1\n");
+  //dump_trees();
+  instance_p = m3ap_MCE_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  /* if the assoc_id is already known, it is certainly because an IND was received
+   * before. In this case, just update streams and return
+   */
+  if (sctp_new_association_resp->assoc_id != -1) {
+    m3ap_mce_data_p = m3ap_get_MCE(instance_p, sctp_new_association_resp->assoc_id,
+                                   sctp_new_association_resp->ulp_cnx_id);
+
+    if (m3ap_mce_data_p != NULL) {
+      /* some sanity check - to be refined at some point */
+      if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+        M3AP_ERROR("m3ap_mce_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+        abort();
+      }
+
+      m3ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+      m3ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+      return;
+    }
+  }
+
+  m3ap_mce_data_p = m3ap_get_MCE(instance_p, -1,
+                                 sctp_new_association_resp->ulp_cnx_id);
+  DevAssert(m3ap_mce_data_p != NULL);
+  //printf("m3ap_MCE_handle_sctp_association_resp at 2\n");
+  //dump_trees_m3();
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+    //m3ap_handle_m3_setup_message(instance_p, m3ap_enb_data_p,
+                                 //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return;
+  }
+
+  //printf("m3ap_MCE_handle_sctp_association_resp at 3\n");
+  //dump_trees_m3();
+  /* Update parameters */
+  m3ap_mce_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+  m3ap_mce_data_p->in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mce_data_p->out_streams = sctp_new_association_resp->out_streams;
+  //printf("m3ap_MCE_handle_sctp_association_resp at 4\n");
+  //dump_trees_m3();
+
+  m3ap_mce_data_g->assoc_id    = sctp_new_association_resp->assoc_id;
+  m3ap_mce_data_g->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mce_data_g->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+  /* Prepare new m3 Setup Request */
+  //m3ap_eNB_generate_m3_setup_request(instance_p, m3ap_enb_data_p);
+  MCE_send_M3_SETUP_REQUEST(instance_p, m3ap_mce_data_p);
+}
+
+static
+void m3ap_MCE_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  m3ap_MCE_instance_t *instance_p;
+  m3ap_MCE_data_t *m3ap_mce_data_p;
+  //printf("m3ap_MCE_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  //dump_trees_m3();
+  DevAssert(sctp_new_association_ind != NULL);
+  instance_p = m3ap_MCE_get_instance(instance);
+  DevAssert(instance_p != NULL);
+  m3ap_mce_data_p = m3ap_get_MCE(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  if (m3ap_mce_data_p != NULL) abort();
+
+  //  DevAssert(m3ap_mce_data_p != NULL);
+  if (m3ap_mce_data_p == NULL) {
+    /* Create new MCE descriptor */
+    m3ap_mce_data_p = calloc(1, sizeof(*m3ap_mce_data_p));
+    DevAssert(m3ap_mce_data_p != NULL);
+    m3ap_mce_data_p->cnx_id                = m3ap_MCE_fetch_add_global_cnx_id();
+    m3ap_mce_data_p->m3ap_MCE_instance = instance_p;
+    /* Insert the new descriptor in list of known eNB
+     * but not yet associated.
+     */
+    RB_INSERT(m3ap_mce_map, &instance_p->m3ap_mce_head, m3ap_mce_data_p);
+    m3ap_mce_data_p->state = M3AP_MCE_STATE_CONNECTED;
+    instance_p->m3_target_mme_nb++;
+
+    if (instance_p->m3_target_mme_pending_nb > 0) {
+      instance_p->m3_target_mme_pending_nb--;
+    }
+  } else {
+    M3AP_WARN("m3ap_mce_data_p already exists\n");
+  }
+
+  //printf("m3ap_MCE_handle_sctp_association_ind at 2\n");
+  //dump_trees_m3();
+  /* Update parameters */
+  m3ap_mce_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  m3ap_mce_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  m3ap_mce_data_p->out_streams = sctp_new_association_ind->out_streams;
+  //printf("m3ap_MCE_handle_sctp_association_ind at 3\n");
+  //dump_trees_m3();
+}
+
+int m3ap_MCE_init_sctp (m3ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mce_port_for_M3C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M3AP_MCE, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = mce_port_for_M3C;
+  sctp_init->ppid = M3AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m3ap_MCE_register_MCE(m3ap_MCE_instance_t *instance_p,
+                                  net_ip_address_t    *target_MCE_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t         mce_port_for_M3C,
+                                  int                  multi_sd) {
+  MessageDef                       *message                   = NULL;
+  sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+  m3ap_MCE_data_t                  *m3ap_mce_data             = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(target_MCE_ip_address != NULL);
+  message = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+  sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+  sctp_new_association_req->port = mce_port_for_M3C;
+  sctp_new_association_req->ppid = M3AP_SCTP_PPID;
+  sctp_new_association_req->in_streams  = in_streams;
+  sctp_new_association_req->out_streams = out_streams;
+  sctp_new_association_req->multi_sd = multi_sd;
+  memcpy(&sctp_new_association_req->remote_address,
+         target_MCE_ip_address,
+         sizeof(*target_MCE_ip_address));
+  memcpy(&sctp_new_association_req->local_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+  /* Create new MCE descriptor */
+  m3ap_mce_data = calloc(1, sizeof(*m3ap_mce_data));
+  DevAssert(m3ap_mce_data != NULL);
+  m3ap_mce_data->cnx_id                = m3ap_MCE_fetch_add_global_cnx_id();
+  sctp_new_association_req->ulp_cnx_id = m3ap_mce_data->cnx_id;
+  m3ap_mce_data->assoc_id          = -1;
+  m3ap_mce_data->m3ap_MCE_instance = instance_p;
+  /* Insert the new descriptor in list of known eNB
+   * but not yet associated.
+   */
+
+  m3ap_mce_data_g = (m3ap_setup_req_t*)calloc(1,sizeof(m3ap_setup_req_t));
+
+
+
+  RB_INSERT(m3ap_mce_map, &instance_p->m3ap_mce_head, m3ap_mce_data);
+  m3ap_mce_data->state = M3AP_MCE_STATE_WAITING;
+  instance_p->m3_target_mme_nb ++;
+  instance_p->m3_target_mme_pending_nb ++;
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+static
+void m3ap_MCE_handle_register_MCE(instance_t instance,
+                                  m3ap_register_mce_req_t *m3ap_register_MCE) {
+  m3ap_MCE_instance_t *new_instance;
+  DevAssert(m3ap_register_MCE != NULL);
+  /* Look if the provided instance already exists */
+  new_instance = m3ap_MCE_get_instance(instance);
+
+  if (new_instance != NULL) {
+    /* Checks if it is a retry on the same MCE */
+    DevCheck(new_instance->MCE_id == m3ap_register_MCE->MCE_id, new_instance->MCE_id, m3ap_register_MCE->MCE_id, 0);
+    DevCheck(new_instance->cell_type == m3ap_register_MCE->cell_type, new_instance->cell_type, m3ap_register_MCE->cell_type, 0);
+    DevCheck(new_instance->tac == m3ap_register_MCE->tac, new_instance->tac, m3ap_register_MCE->tac, 0);
+    DevCheck(new_instance->mcc == m3ap_register_MCE->mcc, new_instance->mcc, m3ap_register_MCE->mcc, 0);
+    DevCheck(new_instance->mnc == m3ap_register_MCE->mnc, new_instance->mnc, m3ap_register_MCE->mnc, 0);
+    M3AP_WARN("MCE[%d] already registered\n", instance);
+  } else {
+    new_instance = calloc(1, sizeof(m3ap_MCE_instance_t));
+    DevAssert(new_instance != NULL);
+    RB_INIT(&new_instance->m3ap_mce_head);
+    /* Copy usefull parameters */
+    new_instance->instance         = instance;
+    new_instance->MCE_name         = m3ap_register_MCE->MCE_name;
+    new_instance->MCE_id           = m3ap_register_MCE->MCE_id;
+    new_instance->cell_type        = m3ap_register_MCE->cell_type;
+    new_instance->tac              = m3ap_register_MCE->tac;
+    new_instance->mcc              = m3ap_register_MCE->mcc;
+    new_instance->mnc              = m3ap_register_MCE->mnc;
+    new_instance->mnc_digit_length = m3ap_register_MCE->mnc_digit_length;
+    new_instance->num_cc           = m3ap_register_MCE->num_cc;
+
+    m3ap_id_manager_init(&new_instance->id_manager);
+    m3ap_timers_init(&new_instance->timers,
+                     m3ap_register_MCE->t_reloc_prep,
+                     m3ap_register_MCE->tm3_reloc_overall);
+
+    for (int i = 0; i< m3ap_register_MCE->num_cc; i++) {
+      new_instance->eutra_band[i]              = m3ap_register_MCE->eutra_band[i];
+      new_instance->downlink_frequency[i]      = m3ap_register_MCE->downlink_frequency[i];
+      new_instance->uplink_frequency_offset[i] = m3ap_register_MCE->uplink_frequency_offset[i];
+      new_instance->Nid_cell[i]                = m3ap_register_MCE->Nid_cell[i];
+      new_instance->N_RB_DL[i]                 = m3ap_register_MCE->N_RB_DL[i];
+      new_instance->frame_type[i]              = m3ap_register_MCE->frame_type[i];
+      new_instance->fdd_earfcn_DL[i]           = m3ap_register_MCE->fdd_earfcn_DL[i];
+      new_instance->fdd_earfcn_UL[i]           = m3ap_register_MCE->fdd_earfcn_UL[i];
+    }
+
+    DevCheck(m3ap_register_MCE->nb_m3 <= M3AP_MAX_NB_MCE_IP_ADDRESS,
+             M3AP_MAX_NB_MCE_IP_ADDRESS, m3ap_register_MCE->nb_m3, 0);
+    memcpy(new_instance->target_mme_m3_ip_address,
+           m3ap_register_MCE->target_mme_m3_ip_address,
+           m3ap_register_MCE->nb_m3 * sizeof(net_ip_address_t));
+    new_instance->nb_m3             = m3ap_register_MCE->nb_m3;
+    new_instance->mme_m3_ip_address = m3ap_register_MCE->mme_m3_ip_address;
+    new_instance->sctp_in_streams   = m3ap_register_MCE->sctp_in_streams;
+    new_instance->sctp_out_streams  = m3ap_register_MCE->sctp_out_streams;
+    new_instance->mce_port_for_M3C  = m3ap_register_MCE->mme_port_for_M3C;
+    /* Add the new instance to the list of MCE (meaningfull in virtual mode) */
+    m3ap_MCE_insert_new_instance(new_instance);
+    M3AP_INFO("Registered new MCE[%d] and %s MCE id %u\n",
+              instance,
+              m3ap_register_MCE->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+              m3ap_register_MCE->MCE_id);
+
+    
+    printf("ipv4_address %s\n",m3ap_register_MCE->mme_m3_ip_address.ipv4_address);
+    /* initiate the SCTP listener */
+    if (m3ap_MCE_init_sctp(new_instance,&m3ap_register_MCE->mme_m3_ip_address,m3ap_register_MCE->mme_port_for_M3C) <  0 ) {
+      M3AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+      return;
+    }
+
+    M3AP_INFO("MCE[%d] MCE id %u acting as a listner (server)\n",
+              instance, m3ap_register_MCE->MCE_id);
+  }
+}
+
+static
+void m3ap_MCE_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m3ap_MCE_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m3ap_MCE_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M3AP_ERROR("Error: be sure to properly configure M3 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of MCE ip address */
+
+  for (index = 0; index < instance->nb_m3; index++) {
+    M3AP_INFO("MCE[%d] MCE id %u acting as an initiator (client)\n",
+              instance_id, instance->MCE_id);
+    m3ap_MCE_register_MCE(instance,
+                          &instance->target_mme_m3_ip_address[index],
+                          &instance->mme_m3_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->mce_port_for_M3C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m3ap_eNB_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req)
+//{
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  m3ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m3ap_handover_req->target_physCellId;
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_is_eNB_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m3ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m3ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not allocate a new M3AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m3ap_set_ids(id_manager, ue_id, m3ap_handover_req->rnti, ue_id, -1);
+//  m3ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m3ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m3ap_timer_get_tti(&instance_p->timers));
+//  m3ap_id_set_target(id_manager, ue_id, target);
+//
+//  m3ap_eNB_generate_m3_handover_request(instance_p, target, m3ap_handover_req, ue_id);
+//}
+
+//static
+//void m3ap_eNB_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_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 M3AP to identify eNodeBs
+//   * RRC knows about mod_id and M3AP knows about eNB_id (eNB_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  int source_assoc_id = m3ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m3ap_handover_req_ack->m3_id_target;
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, m3ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m3ap_eNB_generate_m3_handover_request_ack(instance_p, target, m3ap_handover_req_ack);
+//}
+//
+//static
+//void m3ap_eNB_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release)
+//{
+//  m3ap_eNB_instance_t *instance_p;
+//  m3ap_eNB_data_t     *target;
+//  int source_assoc_id = m3ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_eNB(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m3ap_eNB_generate_m3_ue_context_release(instance_p, target, m3ap_ue_context_release);
+//
+//  /* free the M3AP UE ID */
+//  ue_id = m3ap_find_id_from_rnti(&instance_p->id_manager, m3ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not find UE %x\n", m3ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+uint8_t m3ap_m3setup[] = {
+  0x00, 0x07, 0x00, 0x23, 0x00, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x07, 0x40, 0x55, 0xf5, 0x01, 0x00,
+  0x25, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x03, 0x80,
+  0x4d, 0x33, 0x2d, 0x65, 0x4e, 0x42, 0x33, 0x37,
+  0x00, 0x14, 0x00, 0x03, 0x01, 0x00, 0x01
+};
+
+uint8_t m3ap_start[] = {
+  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+};
+
+
+void *m3ap_MCE_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M3AP_DEBUG("Starting M3AP MCE layer\n");
+  m3ap_MCE_prepare_internal_data();
+  itti_mark_task_ready(TASK_M3AP_MCE);
+
+  while (1) {
+    itti_receive_msg(TASK_M3AP_MCE, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+//	LOG_W(M3AP,"MCE Received Test Message ... TODO\n");
+//	//MessageDef * message_p = itti_alloc_new_message(TASK_M3AP, MESSAGE_TEST);
+//	//itti_send_msg_to_task(TASK_M2AP_ENB, 1/*ctxt_pP->module_id*/, message_p);
+// 
+//        asn_dec_rval_t dec_ret;
+//
+//	
+//	uint8_t  *buffer;
+//  	uint32_t  len;
+//	M3AP_M3AP_PDU_t          pdu;
+//	memset(&pdu, 0, sizeof(pdu));
+//
+//	buffer = &m3ap_m3setup[0];
+//	//buffer = &m3ap_start[0];
+//  	len=8*4+7;
+//  	//len=8*9+7;
+//
+//	//if (m3ap_decode_pdu(&pdu, buffer, len) < 0) {
+//    	//	LOG_E(M3AP, "Failed to decode PDU\n");
+//    //re//turn -1;
+//  	//}
+//	M3AP_M3AP_PDU_t *pdu2 = &pdu;
+//	dec_ret = aper_decode(NULL,
+//                        &asn_DEF_M3AP_M3AP_PDU,
+//                        (void **)&pdu2,
+//                        buffer,
+//                        len,
+//                        0,
+//                        0);
+//
+//	LOG_W(M3AP,"Trying to print %d\n",(dec_ret.code == RC_OK));
+//	xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, &pdu);
+//	LOG_W(M3AP,"Trying to print out \n");
+
+        break;
+      case TERMINATE_MESSAGE:
+        M3AP_WARN(" *** Exiting M3AP thread\n");
+        itti_exit_task();
+        break;
+
+      case M3AP_SUBFRAME_PROCESS:
+        m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+        break;
+
+      case M3AP_REGISTER_MCE_REQ:
+	        LOG_I(M3AP,"MCE Received M3AP_REGISTER_MCE_REQ Message\n");
+
+        m3ap_MCE_handle_register_MCE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_REGISTER_MCE_REQ(received_msg));
+        break;
+
+      case M3AP_MBMS_SESSION_START_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_START_RESP Message\n");
+	MCE_send_MBMS_SESSION_START_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+		
+      case M3AP_MBMS_SESSION_STOP_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_STOP_RESP Message\n");
+	MCE_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     &M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+
+      case M3AP_MBMS_SESSION_UPDATE_RESP:
+	        LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_UPDATE_RESP Message\n");
+	//MCE_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                     //&M3AP_MBMS_SESSION_START_RESP(received_msg));
+
+	break;
+
+	
+//      case M3AP_HANDOVER_REQ:
+//        m3ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_HANDOVER_REQ(received_msg));
+//        break;
+//
+//      case M3AP_HANDOVER_REQ_ACK:
+//        m3ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                         &M3AP_HANDOVER_REQ_ACK(received_msg));
+//        break;
+//
+//      case M3AP_UE_CONTEXT_RELEASE:
+//        m3ap_eNB_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                                &M3AP_UE_CONTEXT_RELEASE(received_msg));
+//        break;
+//
+      case SCTP_INIT_MSG_MULTI_CNF:
+	        LOG_D(M3AP,"MCE Received SCTP_INIT_MSG_MULTI_CNF Message\n");
+
+        m3ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                                &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+	        LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+
+        m3ap_MCE_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+	        LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION Message\n");
+
+        m3ap_MCE_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+	        LOG_D(M3AP,"MCE Received SCTP_DATA_IND Message\n");
+
+        m3ap_MCE_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M3AP_ERROR("Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m3ap_MCE_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m3 = NULL;
+  paramdef_t p[] = {
+   { "enable_mce_m3", "yes/no", 0, strptr:&enable_m3, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first MCE */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "MCEs.[0]");
+  if (enable_m3 != NULL && strcmp(enable_m3, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M3AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair3/M3AP/m3ap_MCE.h b/openair3/M3AP/m3ap_MCE.h
new file mode 100644
index 00000000000..3a617776e3d
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB.h
+ * \brief m3ap 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>
+
+/** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M3AP_MCE_H_
+#define M3AP_MCE_H_
+
+#include "m3ap_MCE_defs.h"
+
+
+int m3ap_MCE_init_sctp (m3ap_MCE_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mce_port_for_M3C);
+
+void *m3ap_MCE_task(void *arg);
+
+int is_m3ap_MCE_enabled(void);
+
+#endif /* M3AP_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair3/M3AP/m3ap_MCE_defs.h b/openair3/M3AP/m3ap_MCE_defs.h
new file mode 100644
index 00000000000..18ad70a408b
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_defs.h
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_defs.h
+ * \brief m3ap struct definitions for MCE
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m3ap_ids.h" //looks X2AP specific for HO
+#include "m3ap_timers.h"
+
+#ifndef M3AP_MCE_DEFS_H_
+#define M3AP_MCE_DEFS_H_
+
+#define M3AP_MCE_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M3AP_MCE_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target MCE accepts or
+   * M3 Setup failure if rejects the MCE.
+   */
+  M3AP_MCE_STATE_WAITING     = 0x1,
+
+  /* The MCE is successfully connected to another MCE. */
+  M3AP_MCE_STATE_CONNECTED   = 0x2,
+
+  /* M3AP is ready, and the MCE is successfully connected to another MCE. */
+  M3AP_MCE_STATE_READY             = 0x3,
+
+  M3AP_MCE_STATE_OVERLOAD          = 0x4,
+
+  M3AP_MCE_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M3AP_MCE_STATE_MAX,
+} m3ap_MCE_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t mce_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular MCE */
+/*struct mce_code_s {
+  uint8_t mce_code;
+  STAILQ_ENTRY(mce_code_s) next;
+};*/
+
+struct m3ap_MCE_instance_s;
+
+/* This structure describes association of a MCE to another MCE */
+typedef struct m3ap_MCE_data_s {
+  /* MCE descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m3ap_MCE_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *MCE_name;
+
+  /*  target MCE ID */
+  uint32_t MCE_id;
+
+  /* Current MCE load information (if any). */
+  //m3ap_load_state_t overload_state;
+
+  /* Current MCE->MCE M3AP association state */
+  m3ap_MCE_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M3AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m3ap_MCE_instance_s *m3ap_MCE_instance;
+} m3ap_MCE_data_t;
+
+typedef struct m3ap_MCE_instance_s {
+  /* used in simulation to store multiple MCE instances*/
+  STAILQ_ENTRY(m3ap_MCE_instance_s) m3ap_MCE_entries;
+
+  /* Number of target MCEs requested by MCE (tree size) */
+  uint32_t m3_target_mme_nb;
+  /* Number of target MCEs for which association is pending */
+  uint32_t m3_target_mme_pending_nb;
+  /* Number of target MCE successfully associated to MCE */
+  uint32_t m3_target_mme_associated_nb;
+  /* Tree of M3AP MCE associations ordered by association ID */
+  RB_HEAD(m3ap_mce_map, m3ap_MCE_data_s) m3ap_mce_head;
+
+  /* Tree of UE ordered by MCE_ue_m3ap_id's */
+  //  RB_HEAD(m3ap_ue_map, m3ap_MCE_ue_context_s) m3ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of MCE */
+  char *MCE_name;
+
+  /* Unique MCE_id to identify the MCE within EPC.
+   * In our case the MCE is a macro MCE so the id will be 20 bits long.
+   * For Home MCE id, this field should be 28 bits long.
+   */
+  uint32_t MCE_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  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_mme_m3_ip_address[M3AP_MAX_NB_MCE_IP_ADDRESS];
+  uint8_t          nb_m3;
+  net_ip_address_t mme_m3_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         mce_port_for_M3C;
+  int              multi_sd;
+
+  m3ap_id_manager  id_manager;
+  m3ap_timers_t    timers;
+} m3ap_MCE_instance_t;
+
+typedef struct {
+  /* List of served MCEs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m3ap_MCE_instances_head_s, m3ap_MCE_instance_s) m3ap_MCE_instances_head;
+  /* Nb of registered MCEs */
+  uint8_t nb_registered_MCEs;
+
+  /* Generate a unique connexion id used between M3AP and SCTP */
+  uint16_t global_cnx_id;
+} m3ap_MCE_internal_data_t;
+
+int m3ap_MCE_compare_assoc_id(struct m3ap_MCE_data_s *p1, struct m3ap_MCE_data_s *p2);
+
+/* Generate the tree management functions */
+struct m3ap_MCE_map;
+struct m3ap_MCE_data_s;
+RB_PROTOTYPE(m3ap_MCE_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+
+#endif /* M3AP_MCE_DEFS_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_generate_messages.h b/openair3/M3AP/m3ap_MCE_generate_messages.h
new file mode 100644
index 00000000000..0884e8216e0
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.h
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_ENB_GENERATE_MESSAGES_H_
+#define M2AP_ENB_GENERATE_MESSAGES_H_
+
+#include "m2ap_eNB_defs.h"
+#include "m2ap_common.h"
+
+int m2ap_eNB_generate_m2_setup_request(m2ap_eNB_instance_t *instance_p,
+				       m2ap_eNB_data_t *m2ap_eNB_data_p);
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p);
+
+/*int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);*/
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_ENB_GENERATE_MESSAGES_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_generate_messsages.c b/openair3/M3AP/m3ap_MCE_generate_messsages.c
new file mode 100644
index 00000000000..8d8c7f38534
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_generate_messsages.c
@@ -0,0 +1,808 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_eNB_generate_messages.c
+ * \brief m2ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_eNB.h"
+#include "m2ap_eNB_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m2ap_eNB_generate_m2_setup_request(
+  m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+{
+  module_id_t enb_mod_idP=0;
+  module_id_t du_mod_idP=0;
+
+  M2AP_M2AP_PDU_t          pdu;
+  M2AP_M2SetupRequest_t    *out;
+  M2AP_M2SetupRequest_Ies_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       i = 0;
+  int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality   = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  /* c1. GlobalENB_ID (integer value) */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_GlobalENB_ID;
+  //ie->value.choice.GlobalENB_ID.eNB_ID = 1;//M2AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  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 = M2AP_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);
+  M2AP_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 */
+  ///* c2. GNB_eNB_ID (integrer value) */
+  //ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id                        = M2AP_ProtocolIE_ID_id_gNB_eNB_ID;
+  //ie->criticality               = M2AP_Criticality_reject;
+  //ie->value.present             = M2AP_M2SetupRequestIEs__value_PR_GNB_eNB_ID;
+  //asn_int642INTEGER(&ie->value.choice.GNB_eNB_ID, f1ap_du_data->gNB_eNB_id);
+  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  /* c3. ENBname */
+  if (m2ap_eNB_data_p->eNB_name != NULL) {
+    ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+    ie->id                        = M2AP_ProtocolIE_ID_id_ENBname;
+    ie->criticality               = M2AP_Criticality_ignore;
+    ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENBname;
+    //OCTET_STRING_fromBuf(&ie->value.choice.ENB_Name, m2ap_eNB_data_p->eNB_name,
+                         //strlen(m2ap_eNB_data_p->eNB_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  /* c4. serverd cells list */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  ie->id                        = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_List;
+  ie->criticality               = M2AP_Criticality_reject;
+  ie->value.present             = M2AP_M2SetupRequest_Ies__value_PR_ENB_MBMS_Configuration_data_List;
+
+  int num_mbms_available = 1;//m2ap_du_data->num_mbms_available;
+  LOG_D(M2AP, "num_mbms_available = %d \n", num_mbms_available);
+
+ for (i=0;
+       i<num_mbms_available;
+       i++) {
+        /* mandatory */
+        /* 4.1 serverd cells item */
+
+        M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+        mbms_configuration_data_list_item_ies = (M2AP_ENB_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M2AP_ENB_MBMS_Configuration_data_ItemIEs_t));
+        mbms_configuration_data_list_item_ies->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_Configuration_data_Item;
+        mbms_configuration_data_list_item_ies->criticality = M2AP_Criticality_reject;
+        mbms_configuration_data_list_item_ies->value.present = M2AP_ENB_MBMS_Configuration_data_ItemIEs__value_PR_ENB_MBMS_Configuration_data_Item;
+
+	M2AP_ENB_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+	mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.ENB_MBMS_Configuration_data_Item;
+	{
+		MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+        	MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+		M2AP_MBMS_Service_Area_t * mbms_service_area;
+		mbms_service_area = (M2AP_MBMS_Service_Area_t*)calloc(1,sizeof(M2AP_MBMS_Service_Area_t));
+		ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+
+
+	}
+
+
+        //M2AP_ENB_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M2AP_ENB_MBMS_Configuration_data_Item_t));
+	
+	//M2AP_ECGI_t      eCGI;
+		//M2AP_PLMN_Identity_t     pLMN_Identity;
+		//M2AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+	//M2AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+	//M2AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+
+
+	ASN_SEQUENCE_ADD(&ie->value.choice.ENB_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+
+ }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  LOG_W(M2AP,"m2ap_eNB_data_p->assoc_id %d\n",m2ap_eNB_data_p->assoc_id);
+  /* encode */
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M2AP, "Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+ 
+  LOG_W(M2AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M2AP_eNB,
+ // MSC_M2AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M2_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m2ap_eNB_data_p->ENBname);
+
+  m2ap_eNB_itti_send_sctp_data_req(instance_p, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return 0;
+
+
+}
+
+//int m2ap_MCE_generate_m2_setup_response(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupResponse_t              *out;
+//  M2AP_M2SetupResponse_Ies_t          *ie;
+//  //M2AP_PLMN_Identity_t                *plmn;
+//  //ServedCells__Member                 *servedCellMember;
+//  //M2AP_GU_Group_ID_t                  *gu;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+//  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GlobalENB_ID;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_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 = M2AP_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);
+//  //M2AP_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 = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_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 = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_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 = M2AP_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 = M2AP_Transmission_Bandwidth_bw6;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+//  //            break;
+//  //          case 15:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+//  //            break;
+//  //          case 25:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+//  //            break;
+//  //          case 50:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+//  //            break;
+//  //          case 75:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+//  //            break;
+//  //          case 100:
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+//  //            break;
+//  //          default:
+//  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+//  //            break;
+//  //        }
+//  //      }
+//  //      else {
+//  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+//  //      }
+//  //    }
+//  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+//  //  }
+//  //}
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+//  //ie->criticality = M2AP_Criticality_reject;
+//  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+//  //{
+//  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_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 (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup response\n");
+//    return -1;
+//  }
+//
+//  m2ap_eNB_data_p->state = M2AP_ENB_STATE_READY;
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+//int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+//                                       uint32_t assoc_id,
+//                                       M2AP_Cause_PR cause_type,
+//                                       long cause_value,
+//                                       long time_to_wait)
+//{
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_M2SetupFailure_t              *out;
+//  M2AP_M2SetupFailure_Ies_t          *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  /* Prepare the M2AP message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+//  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+//
+//  /* mandatory */
+//  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+//
+//  //m2ap_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 = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+//  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+//  //ie->criticality = M2AP_Criticality_ignore;
+//  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+//
+//  //if (time_to_wait > -1) {
+//  //  ie->value.choice.TimeToWait = time_to_wait;
+//  //}
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode M2 setup failure\n");
+//    return -1;
+//  }
+//
+//  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB,
+//  //                    MSC_M2AP_TARGET_ENB, NULL, 0,
+//  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+//  //                    assoc_id, cause_type, cause_value);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+//
+//  return ret;
+//}
+
+int m2ap_eNB_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_eNB_generate_m2_handover_request (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_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(m2ap_eNB_data_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_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(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KENB_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_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<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_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 = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_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 = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_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,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_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*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_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 = M2AP_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 (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_request_ack (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_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 = m2ap_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 = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_ue_context_release (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_eNB_generate_m2_handover_cancel (m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_eNB_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_eNB_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_eNB_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_ENB, MSC_M2AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_eNB_data_p->assoc_id);
+//
+//  m2ap_eNB_itti_send_sctp_data_req(instance_p->instance, m2ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair3/M3AP/m3ap_MCE_handler.c b/openair3/M3AP/m3ap_MCE_handler.c
new file mode 100644
index 00000000000..e733af28db3
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_handler.c
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+//#include "m3ap_MCE_management_procedures.h"
+#include "m3ap_MCE_generate_messages.h"
+
+//#include "m3ap_MME_interface_management.h"
+#include "m3ap_MCE_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_MCE_message_decoded_callback m3ap_MCE_messages_callback[][3] = {
+  { MCE_handle_MBMS_SESSION_START_REQUEST, 0, 0 }, /* MBMSSessionStart  */
+  { MCE_handle_MBMS_SESSION_STOP_REQUEST, 0, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { MCE_handle_MBMS_SESSION_UPDATE_REQUEST, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, MCE_handle_M3_SETUP_RESPONSE, 0 } /* M3 Setup */
+};
+
+static char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_MCE_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[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_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_MCE_handler.h b/openair3/M3AP/m3ap_MCE_handler.h
new file mode 100644
index 00000000000..ce4997e80d7
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_HANDLERS_H_
+#define M2AP_MCE_HANDLERS_H_
+
+#include "m2ap_MCE_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_MCE_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_MCE_interface_management.c b/openair3/M3AP/m3ap_MCE_interface_management.c
new file mode 100644
index 00000000000..26948465263
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_interface_management.c
@@ -0,0 +1,756 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_interface_management.c
+ * \brief m3ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "intertask_interface.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE.h"
+//#include "m3ap_MCE_generate_messages.h"
+#include "m3ap_encoder.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MCE_interface_management.h"
+
+
+#include "m3ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+
+//#include "m3ap_common.h"
+//#include "m3ap_encoder.h"
+//#include "m3ap_decoder.h"
+//#include "m3ap_itti_messaging.h"
+//#include "m3ap_MCE_interface_management.h"
+//#include "assertions.h"
+
+extern m3ap_setup_req_t * m3ap_mce_data_g;
+
+
+int MCE_handle_MBMS_SESSION_START_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu){
+//  LOG_W(M3AP, "MCE_handle_MBMS_SESSION_START_REQUEST assoc_id %d\n",assoc_id);
+//
+    MessageDef                         *message_p;
+//  M3AP_SessionStartRequest_t              *container;
+//  M3AP_SessionStartRequest_Ies_t           *ie;
+//  int i = 0;
+//
+//  DevAssert(pdu != NULL);
+//
+//  container = &pdu->choice.initiatingMessage.value.choice.SessionStartRequest;
+
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_START_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+//  if(1){
+//	MCE_send_MBMS_SESSION_START_RESPONSE(instance,assoc_id);
+//  }else
+//	MCE_send_MBMS_SESSION_START_FAILURE(instance,assoc_id);
+  return 0;
+  
+}
+
+int MCE_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp){
+  //AssertFatal(1==0,"Not implemented yet\n");
+
+//	module_id_t mce_mod_idP;
+//  module_id_t enb_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionStartResponse_t    *out;
+  M3AP_MBMSSessionStartResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStart;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionStartResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionStart Response\n");
+    return -1;
+  }
+//
+//
+//  LOG_W(M3AP,"pdu.present %d\n",pdu.present);
+// // MSC_LOG_TX_MESSAGE(
+// // MSC_M3AP_MCE,
+// // MSC_M3AP_MCE,
+// // (const char *)buffer,
+// // len,
+// // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+// // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+// // m3ap_MCE_data_p->MCEname);
+//
+   m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+
+int MCE_send_MBMS_SESSION_START_FAILURE(instance_t instance, m3ap_session_start_failure_t * m3ap_session_start_failure){
+//  module_id_t enb_mod_idP;
+//  module_id_t mce_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+//  M3AP_M3AP_PDU_t           pdu;
+//  M3AP_SessionStartFailure_t    *out;
+//  M3AP_SessionStartFailure_Ies_t *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//
+//  /* Create */
+//  /* 0. Message Type */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+//  //pdu.choice.unsuccessfulOutcome = (M3AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M3AP_UnsuccessfulOutcome_t));
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M3AP_ProcedureCode_id_sessionStart;
+//  pdu.choice.unsuccessfulOutcome.criticality   = M3AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M3AP_UnsuccessfulOutcome__value_PR_SessionStartFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.SessionStartFailure;
+//
+//  /* mandatory */
+//  /* c1. Transaction ID (integer value)*/
+// // ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_M3SetupFailure_Ies_t));
+// // ie->id                        = M3AP_ProtocolIE_ID_id_GlobalMCE_ID;
+// // ie->criticality               = M3AP_Criticality_reject;
+// // ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_GlobalMCE_ID;
+// // ie->value.choice.GlobalMCE_ID = M3AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+// // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  /* c2. Cause */
+//  ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_SessionStartFailure_Ies_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality               = M3AP_Criticality_ignore;
+//  ie->value.present             = M3AP_SessionStartFailure_Ies__value_PR_Cause;
+//  ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M3AP_CauseRadioNetwork_unspecified;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//
+//     /* encode */
+//  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    LOG_E(M3AP, "Failed to encode M3 setup request\n");
+//    return -1;
+//  }
+//
+//  //mce_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+//  m3ap_MCE_itti_send_sctp_data_req(instance,assoc_id,buffer,len,0);
+//
+
+  return 0;
+}
+
+int MCE_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu){
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MCE_handle_MBMS_SESSION_STOP_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M3AP_MBMSSessionStopRequest_t              *container;
+  //M3AP_MBMSSessionStopRequest_IEs_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MBMSSessionStopRequest;
+
+  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  //if(1){
+	//MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id);
+  //}else
+	//MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id);
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_STOP_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+  return 0;
+  
+}
+int MCE_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp){
+//	module_id_t mce_mod_idP;
+//  module_id_t enb_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionStopResponse_t    *out;
+  M3AP_MBMSSessionStopResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStop;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionStopResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionStop Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M3AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M3AP_MCE,
+ // MSC_M3AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m3ap_MCE_data_p->MCEname);
+
+  m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+
+/*
+ * Session Update
+ */
+int MCE_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance,
+                                        uint32_t assoc_id,
+                                        uint32_t stream,
+                                        M3AP_M3AP_PDU_t *pdu)
+{
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MCE_handle_MBMS_SESSION_UPDATE_REQUEST assoc_id %d\n",assoc_id);
+
+  MessageDef                         *message_p;
+  //M3AP_MBMSSessionUpdateRequest_t              *container;
+  //M3AP_MBMSSessionUpdateRequest_IEs_t           *ie;
+  //int i = 0;
+
+  DevAssert(pdu != NULL);
+
+  //container = &pdu->choice.initiatingMessage.value.choice.MBMSSessionUpdateRequest;
+
+  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+  if (stream != 0) {
+    LOG_D(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+              assoc_id, stream);
+  }
+
+  //if(1){
+	//MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id);
+  //}else
+	//MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id);
+    message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_UPDATE_REQ);
+
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+
+    itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+
+
+
+
+	return 0;
+}
+
+int MCE_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m3ap_mbms_session_update_resp_t * m3ap_mbms_session_update_resp){
+  M3AP_M3AP_PDU_t           pdu;
+  M3AP_MBMSSessionUpdateResponse_t    *out;
+  M3AP_MBMSSessionUpdateResponse_IEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+
+  /* Create */
+  /* 0. Message Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_mBMSsessionUpdate;
+  pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.MBMSSessionUpdateResponse;
+  
+
+  /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+ /* mandatory */
+  /* c1. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateResponse_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateResponse_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 SessionUpdate Response\n");
+    return -1;
+  }
+
+
+  LOG_D(M3AP,"pdu.present %d\n",pdu.present);
+ // MSC_LOG_TX_MESSAGE(
+ // MSC_M3AP_MCE,
+ // MSC_M3AP_MCE,
+ // (const char *)buffer,
+ // len,
+ // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+ // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ // m3ap_MCE_data_p->MCEname);
+
+  m3ap_MCE_itti_send_sctp_data_req(instance, m3ap_mce_data_g->assoc_id, buffer, len, 0);
+  return 0;
+}
+int MCE_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m3ap_mbms_session_update_failure_t * m3ap_mbms_session_update_failure){
+	return 0;
+}
+
+/*
+    M3 Setup
+*/
+
+//uint8_t m3ap_m3setup_message[] = {0x00,0x07,0x00,0x23,0x00,0x00,0x03,0x00,0x12,0x00,0x07,0x40,0x55,0xf5,0x01,0x00,0x25,0x00,0x00,0x13,0x40,0x0a,0x03,0x80,0x4d,0x33,0x2d,0x65,0x4e,0x42,0x33,0x37,0x00,0x14,0x00,0x03,0x01,0x00,0x01};
+uint8_t m3ap_m3setup_message[] = {
+  0x00, 0x07, 0x00, 0x23, 0x00, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x07, 0x40, 0x55, 0xf5, 0x01, 0x00,
+  0x25, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x03, 0x80,
+  0x4d, 0x33, 0x2d, 0x65, 0x4e, 0x42, 0x33, 0x37,
+  0x00, 0x14, 0x00, 0x03, 0x01, 0x00, 0x01
+};
+
+
+//uint8_t m3ap_start_message[] = {
+//  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+//  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+//  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+//  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+//  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+//  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+//  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+//  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+//  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+//  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+//};
+//
+// SETUP REQUEST
+int MCE_send_M3_SETUP_REQUEST(m3ap_MCE_instance_t *instance_p, m3ap_MCE_data_t *m3ap_MCE_data_p) {
+//  module_id_t enb_mod_idP=0;
+//  module_id_t du_mod_idP=0;
+//
+  M3AP_M3AP_PDU_t          pdu;
+  M3AP_M3SetupRequest_t    *out;
+  M3AP_M3SetupRequestIEs_t *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  //int       i = 0;
+  //int       j = 0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_M3SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M3SetupRequest;
+
+  /* mandatory */
+  /* c1. GlobalMCE_ID (integer value) */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_Global_MCE_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_Global_MCE_ID;
+  //ie->value.choice.GlobalMCE_ID.MCE_ID = 1;//M3AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                  &ie->value.choice.Global_MCE_ID.pLMN_Identity);
+  //ie->value.choice.Global_MCE_ID.MCE_ID.present = M3AP_MCE_ID_PR_macro_MCE_ID;
+ OCTET_STRING_fromBuf(&ie->value.choice.Global_MCE_ID.mCE_ID,"02",2);
+
+ // MACRO_ENB_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                         &ie->value.choice.Global_MCE_ID.mCE_ID);
+  //M3AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+   //       ie->value.choice.Global_MCE_ID.mCE_ID.buf[0],
+    //      ie->value.choice.Global_MCE_ID.mCE_ID.buf[1],
+     //     ie->value.choice.Global_MCE_ID.mCE_ID.buf[2]);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  ///* mandatory */
+//  ///* c2. GNB_MCE_ID (integrer value) */
+//  //ie = (M3AP_M3SetupRequest_Ies_t *)calloc(1, sizeof(M3AP_M3SetupRequest_Ies_t));
+//  //ie->id                        = M3AP_ProtocolIE_ID_id_gNB_MCE_ID;
+//  //ie->criticality               = M3AP_Criticality_reject;
+//  //ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_GNB_MCE_ID;
+//  //asn_int642INTEGER(&ie->value.choice.GNB_MCE_ID, f1ap_du_data->gNB_MCE_id);
+//  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//     /* optional */
+  /* c3. MCEname */
+  //m3ap_MCE_data_p->MCE_name="kk";
+  if (m3ap_MCE_data_p->MCE_name != NULL) {
+    ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+    ie->id                        = M3AP_ProtocolIE_ID_id_MCEname;
+    ie->criticality               = M3AP_Criticality_ignore;
+    ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_MCEname;
+    OCTET_STRING_fromBuf(&ie->value.choice.MCEname, m3ap_MCE_data_p->MCE_name,
+                         strlen(m3ap_MCE_data_p->MCE_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */ //but removed from asn definition (optional) since it crashes when decoding ???????????
+//	M3SetupRequestIEs M3AP-PROTOCOL-IES ::= {
+//		{ ID id-Global-MCE-ID                   CRITICALITY reject      TYPE Global-MCE-ID                                      PRESENCE mandatory}|
+//		{ ID id-MCEname                                 CRITICALITY ignore      TYPE MCEname                                            PRESENCE optional}|
+//		{ ID id-MBMSServiceAreaList             CRITICALITY reject      TYPE MBMSServiceAreaListItem            PRESENCE mandatory}, --> optional ??????????
+//		...
+//	}
+
+
+  /* M3AP_MBMSServiceAreaListItem_t */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMSServiceAreaList;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_M3SetupRequestIEs__value_PR_MBMSServiceAreaListItem;
+
+  //M3AP_MBMSServiceAreaListItem_t * m3ap_mbmsservicearealistitem = (M3AP_MBMSServiceAreaListItem_t*)calloc(1,sizeof(M3AP_MBMSServiceAreaListItem_t)); 
+
+  M3AP_MBMSServiceArea1_t * m3ap_mbmsservicearea1 = (M3AP_MBMSServiceArea1_t*)calloc(1,sizeof(M3AP_MBMSServiceArea1_t));
+  
+  OCTET_STRING_fromBuf(m3ap_mbmsservicearea1,"02",2);
+
+  //ASN_SEQUENCE_ADD(&m3ap_mbmsservicearealistitem->list,m3ap_mbmsservicearea1);
+
+  //ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem,m3ap_mbmsservicearealistitem);
+  //ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem.list,m3ap_mbmsservicearealistitem);
+  ASN_SEQUENCE_ADD(&ie->value.choice.MBMSServiceAreaListItem.list,m3ap_mbmsservicearea1);
+  
+  //ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+//
+//  /* mandatory */
+//  /* c4. serverd cells list */
+//  ie = (M3AP_M3SetupRequest_Ies_t *)calloc(1, sizeof(M3AP_M3SetupRequest_Ies_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_List;
+//  ie->criticality               = M3AP_Criticality_reject;
+//  ie->value.present             = M3AP_M3SetupRequest_Ies__value_PR_MCE_MBMS_Configuration_data_List;
+//
+//  int num_mbms_available = 1;//m3ap_du_data->num_mbms_available;
+//  LOG_D(M3AP, "num_mbms_available = %d \n", num_mbms_available);
+//
+// for (i=0;
+//       i<num_mbms_available;
+//       i++) {
+//        /* mandatory */
+//        /* 4.1 serverd cells item */
+//
+//        M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *mbms_configuration_data_list_item_ies;
+//        mbms_configuration_data_list_item_ies = (M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *)calloc(1, sizeof(M3AP_MCE_MBMS_Configuration_data_ItemIEs_t));
+//        mbms_configuration_data_list_item_ies->id = M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_Item;
+//        mbms_configuration_data_list_item_ies->criticality = M3AP_Criticality_reject;
+//        mbms_configuration_data_list_item_ies->value.present = M3AP_MCE_MBMS_Configuration_data_ItemIEs__value_PR_MCE_MBMS_Configuration_data_Item;
+//
+//        M3AP_MCE_MBMS_Configuration_data_Item_t *mbms_configuration_data_item;
+//        mbms_configuration_data_item = &mbms_configuration_data_list_item_ies->value.choice.MCE_MBMS_Configuration_data_Item;
+//        {
+//		/* M3AP_ECGI_t eCGI */
+//                MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+//                  &mbms_configuration_data_item->eCGI.pLMN_Identity);
+//                MACRO_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+//                                   &mbms_configuration_data_item->eCGI.eUTRANcellIdentifier);
+//		/* M3AP_MBSFN_SynchronisationArea_ID_t mbsfnSynchronisationArea */ 
+//		mbms_configuration_data_item->mbsfnSynchronisationArea=10000; //? long
+//		/* M3AP_MBMS_Service_Area_ID_List_t mbmsServiceAreaList */
+//                M3AP_MBMS_Service_Area_t * mbms_service_area,*mbms_service_area2;
+//                mbms_service_area = (M3AP_MBMS_Service_Area_t*)calloc(1,sizeof(M3AP_MBMS_Service_Area_t));
+//                mbms_service_area2 = (M3AP_MBMS_Service_Area_t*)calloc(1,sizeof(M3AP_MBMS_Service_Area_t));
+//		//memset(mbms_service_area,0,sizeof(OCTET_STRING_t));
+//		OCTET_STRING_fromBuf(mbms_service_area,"01",2);
+//                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area);
+//		OCTET_STRING_fromBuf(mbms_service_area2,"02",2);
+//                ASN_SEQUENCE_ADD(&mbms_configuration_data_item->mbmsServiceAreaList.list,mbms_service_area2);
+//
+//
+//        }
+//
+//
+//        //M3AP_MCE_MBMS_Configuration_data_Item_t mbms_configuration_data_item;
+//        //memset((void *)&mbms_configuration_data_item, 0, sizeof(M3AP_MCE_MBMS_Configuration_data_Item_t));
+//
+//        //M3AP_ECGI_t      eCGI;
+//                //M3AP_PLMN_Identity_t     pLMN_Identity;
+//                //M3AP_EUTRANCellIdentifier_t      eUTRANcellIdentifier
+//        //M3AP_MBSFN_SynchronisationArea_ID_t      mbsfnSynchronisationArea;
+//        //M3AP_MBMS_Service_Area_ID_List_t         mbmsServiceAreaList;
+//
+//
+//        ASN_SEQUENCE_ADD(&ie->value.choice.MCE_MBMS_Configuration_data_List.list,mbms_configuration_data_list_item_ies);
+//
+// }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  
+// LOG_W(M3AP,"m3ap_MCE_data_p->assoc_id %d\n",m3ap_MCE_data_p->assoc_id);
+//  /* encode */
+
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, &pdu);
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3SetupRequest, &pdu.choice.initiatingMessage.value.choice.M3SetupRequest);
+//    xer_fprint(stdout, &asn_DEF_M3AP_M3SetupRequest, out);
+
+ if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+   LOG_E(M3AP, "Failed to encode M3 setup request\n");
+   return -1;
+ }
+
+ /* buffer = &m3ap_start_message[0];
+  len=8*9+7; 
+
+  buffer = &m3ap_m3setup_message[0];
+  len=8*4+7; */
+//
+//
+//  LOG_W(M3AP,"pdu.present %d\n",pdu.present);
+// // MSC_LOG_TX_MESSAGE(
+// // MSC_M3AP_MCE,
+// // MSC_M3AP_MCE,
+// // (const char *)buffer,
+// // len,
+// // MSC_AS_TIME_FMT" M3_SETUP_REQUEST initiatingMessage MCEname %s",
+// // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+// // m3ap_MCE_data_p->MCEname);
+//
+//
+////  buffer = &bytes[0];
+////  len = 40;
+////
+////  for(int i=0; i < len; i++ )
+////	printf("%02X",buffer[i]);
+////  printf("\n");
+////
+
+// M3AP_M3AP_PDU_t pdu2;
+//
+//  memset(&pdu2, 0, sizeof(pdu2));
+//
+//  for( i=0; i < len; i++)
+//        printf("%02X",buffer[i]);
+//  printf("\n");
+//
+//  if (m3ap_decode_pdu(&pdu2, buffer, len) < 0) {
+//    LOG_E(M3AP, "Failed to decode PDU\n");
+//    //return -1;
+//  }
+//
+
+  //printf("m3ap_MCE_data_p->assoc_id %d\n",m3ap_MCE_data_p->assoc_id);
+  m3ap_MCE_itti_send_sctp_data_req(instance_p->instance, m3ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return 0;
+}
+
+
+
+int MCE_handle_M3_SETUP_RESPONSE(instance_t instance,
+				uint32_t               assoc_id,
+				uint32_t               stream,
+				M3AP_M3AP_PDU_t       *pdu)
+{
+
+   LOG_D(M3AP, "MCE_handle_M3_SETUP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_m3Setup,
+	       "pdu->choice.successfulOutcome.procedureCode != M3AP_ProcedureCode_id_M3Setup\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome.criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_M3SetupResponse,
+	       "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_M3SetupResponse\n");
+
+   //M3AP_M3SetupResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.M3SetupResponse;
+
+
+   //M3AP_M3SetupResponseIEs_t *ie;
+   //int GlobalMCE_ID = -1;
+   //int num_cells_to_activate = 0;
+   //M3AP_Cells_to_be_Activated_List_Item_t *cell;
+
+   MessageDef *msg_p = itti_alloc_new_message (TASK_M3AP_MCE, M3AP_SETUP_RESP);
+
+  // LOG_D(M3AP, "M3AP: M3Setup-Resp: protocolIEs.list.count %d\n",
+  //       in->protocolIEs.list.count);
+  // for (int i=0;i < in->protocolIEs.list.count; i++) {
+  //   ie = in->protocolIEs.list.array[i];
+  // }
+   //AssertFatal(GlobalMCE_ID!=-1,"GlobalMCE_ID was not sent\n");
+   //AssertFatal(num_cells_to_activate>0,"No cells activated\n");
+   //M3AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate;
+
+   //for (int i=0;i<num_cells_to_activate;i++)  
+   //  AssertFatal(M3AP_SETUP_RESP (msg_p).num_SI[i] > 0, "System Information %d is missing",i);
+
+   //MSC_LOG_RX_MESSAGE(
+   // MSC_M3AP_MCE,
+   // MSC_M3AP_CU,
+   // 0,
+   // 0,
+   // MSC_AS_TIME_FMT" MCE_handle_M3_SETUP_RESPONSE successfulOutcome assoc_id %d",
+   // 0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+   // assoc_id);
+ 
+   //LOG_D(M3AP, "Sending M3AP_SETUP_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+   //      assoc_id,MCE_MOMCELE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p);
+
+   return 0;
+}
+
+// SETUP FAILURE
+int MCE_handle_M3_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu) {
+  LOG_E(M3AP, "MCE_handle_M3_SETUP_FAILURE\n");
+  return 0;
+}
+
+
+
+
+
diff --git a/openair3/M3AP/m3ap_MCE_interface_management.h b/openair3/M3AP/m3ap_MCE_interface_management.h
new file mode 100644
index 00000000000..76e13bb8d87
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_interface_management.h
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_interface_management.h
+ * \brief m3ap interface management for MCE
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_MCE_INTERFACE_MANAGEMENT_H_
+#define M3AP_MCE_INTERFACE_MANAGEMENT_H_
+
+/*
+ * Session Start 
+ */
+
+int MCE_handle_MBMS_SESSION_START_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+int MCE_send_MBMS_SESSION_START_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp);
+int MCE_send_MBMS_SESSION_START_FAILURE(instance_t instance, m3ap_session_start_failure_t * m3ap_session_start_failure);
+
+/*
+ * Session Stop
+ */
+
+int MCE_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Session Update
+ */
+int MCE_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, 
+					uint32_t assoc_id,
+                                	uint32_t stream,
+                                	M3AP_M3AP_PDU_t *pdu);
+
+int MCE_send_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, m3ap_mbms_session_update_resp_t * m3ap_mbms_session_update_resp);
+int MCE_send_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, m3ap_mbms_session_update_failure_t * m3ap_mbms_session_update_failure);
+
+
+
+
+
+
+
+int MCE_send_MBMS_SESSION_STOP_RESPONSE(instance_t instance, m3ap_session_start_resp_t * m3ap_session_start_resp);
+
+/*
+ * Reset
+ */
+int MCE_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M3AP_M3AP_PDU_t *pdu);
+int MCE_send_RESET_ACKKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge);
+int MCE_send_RESET(instance_t instance, M3AP_Reset_t *Reset);
+int MCE_handle_RESET_ACKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * M3AP Setup
+ */
+int MCE_send_M3_SETUP_REQUEST( m3ap_MCE_instance_t *instance_p, m3ap_MCE_data_t *m3ap_MCE_data_p);
+
+int MCE_handle_M3_SETUP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MCE_handle_M3_SETUP_FAILURE(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Error Indication
+ */
+int MCE_send_ERROR_INDICATION(instance_t instance, M3AP_M3AP_PDU_t *pdu_p);
+int MCE_handle_ERROR_INDICATION(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+
+
+
+#endif /* M3AP_MCE_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair3/M3AP/m3ap_MCE_management_procedures.c b/openair3/M3AP/m3ap_MCE_management_procedures.c
new file mode 100644
index 00000000000..106d211f107
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_management_procedures.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_MCE.h"
+
+
+#define M3AP_DEBUG_LIST
+#ifdef M3AP_DEBUG_LIST
+#  define M3AP_MCE_LIST_OUT(x, args...) M3AP_DEBUG("[MCE]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M3AP_MCE_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m3ap_MCE_internal_data_t m3ap_MCE_internal_data;
+
+RB_GENERATE(m3ap_mce_map, m3ap_MCE_data_s, entry, m3ap_MCE_compare_assoc_id);
+
+int m3ap_MCE_compare_assoc_id(
+  struct m3ap_MCE_data_s *p1, struct m3ap_MCE_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m3ap_MCE_fetch_add_global_cnx_id(void)
+{
+  return ++m3ap_MCE_internal_data.global_cnx_id;
+}
+
+void m3ap_MCE_prepare_internal_data(void)
+{
+  memset(&m3ap_MCE_internal_data, 0, sizeof(m3ap_MCE_internal_data));
+  STAILQ_INIT(&m3ap_MCE_internal_data.m3ap_MCE_instances_head);
+}
+
+void m3ap_MCE_insert_new_instance(m3ap_MCE_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                     new_instance_p, m3ap_MCE_entries);
+}
+
+void dump_tree_m3(m3ap_MCE_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("MCE id %d %s\n", t->MCE_id, t->MCE_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_tree_m3(t->entry.rbe_left);
+  dump_tree_m3(t->entry.rbe_right);
+}
+
+void dump_trees_m3(void)
+{
+m3ap_MCE_instance_t *zz;
+STAILQ_FOREACH(zz, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+               m3ap_MCE_entries) {
+printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_tree_m3(zz->m3ap_mce_head.rbh_root);
+printf("---------------------------------------------\n");
+}
+}
+
+struct m3ap_MCE_data_s *m3ap_get_MCE(m3ap_MCE_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m3ap_MCE_data_s  temp;
+  struct m3ap_MCE_data_s *found;
+
+printf("m3ap_get_MCE at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+dump_trees_m3();
+
+  memset(&temp, 0, sizeof(struct m3ap_MCE_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                   m3ap_MCE_entries) {
+      found = RB_FIND(m3ap_mce_map, &instance_p->m3ap_mce_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m3ap_mce_map, &instance_p->m3ap_mce_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m3ap_MCE_instance_t *m3ap_MCE_get_instance(instance_t instance)
+{
+  m3ap_MCE_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,
+                 m3ap_MCE_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m3ap_dump_MCE (m3ap_MCE_data_t  * MCE_ref);
+
+void
+m3ap_dump_MCE_list (void) {
+   m3ap_MCE_instance_t *inst = NULL;
+   struct m3ap_MCE_data_s *found = NULL;
+   struct m3ap_MCE_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m3ap_MCE_data_s));
+
+  STAILQ_FOREACH (inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head,  m3ap_MCE_entries) {
+    found = RB_FIND(m3ap_mce_map, &inst->m3ap_mce_head, &temp);
+    m3ap_dump_MCE (found);
+  }
+}
+
+void m3ap_dump_MCE (m3ap_MCE_data_t  * MCE_ref) {
+
+  if (MCE_ref == NULL) {
+    return;
+  }
+
+  M3AP_MCE_LIST_OUT ("");
+  M3AP_MCE_LIST_OUT ("MCE name:          %s", MCE_ref->MCE_name == NULL ? "not present" : MCE_ref->MCE_name);
+  M3AP_MCE_LIST_OUT ("MCE STATE:         %07x", MCE_ref->state);
+  M3AP_MCE_LIST_OUT ("MCE ID:            %07x", MCE_ref->MCE_id);
+  indent++;
+  M3AP_MCE_LIST_OUT ("SCTP cnx id:     %d", MCE_ref->cnx_id);
+  M3AP_MCE_LIST_OUT ("SCTP assoc id:     %d", MCE_ref->assoc_id);
+  M3AP_MCE_LIST_OUT ("SCTP instreams:    %d", MCE_ref->in_streams);
+  M3AP_MCE_LIST_OUT ("SCTP outstreams:   %d", MCE_ref->out_streams);
+  indent--;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_pci_in_list (const uint32_t pci)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    RB_FOREACH(elm, m3ap_mce_map, &inst->m3ap_mce_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_id_in_list (const uint32_t MCE_id)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    RB_FOREACH(elm, m3ap_mce_map, &inst->m3ap_mce_head) {
+      if (elm->MCE_id == MCE_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m3ap_MCE_data_t  * m3ap_is_MCE_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m3ap_MCE_instance_t    *inst;
+  struct m3ap_MCE_data_s *found;
+  struct m3ap_MCE_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) {
+    found = RB_FIND(m3ap_mce_map, &inst->m3ap_mce_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair3/M3AP/m3ap_MCE_management_procedures.h b/openair3/M3AP/m3ap_MCE_management_procedures.h
new file mode 100644
index 00000000000..2d18df8c26d
--- /dev/null
+++ b/openair3/M3AP/m3ap_MCE_management_procedures.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_management_procedures.h
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MCE_MANAGEMENT_PROCEDURES_H_
+#define M3AP_MCE_MANAGEMENT_PROCEDURES_H
+
+void m3ap_MCE_prepare_internal_data(void);
+
+void dump_trees_m3(void);
+
+void m3ap_MCE_insert_new_instance(m3ap_MCE_instance_t *new_instance_p);
+
+m3ap_MCE_instance_t *m3ap_MCE_get_instance(uint8_t mod_id);
+
+uint16_t m3ap_MCE_fetch_add_global_cnx_id(void);
+
+
+m3ap_MCE_data_t* m3ap_is_MCE_id_in_list(uint32_t MCE_id);
+
+m3ap_MCE_data_t* m3ap_is_MCE_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m3ap_MCE_data_t* m3ap_is_MCE_pci_in_list (const uint32_t pci);
+
+struct m3ap_MCE_data_s *m3ap_get_MCE(m3ap_MCE_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M3AP_MCE_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair3/M3AP/m3ap_MME.c b/openair3/M3AP/m3ap_MME.c
new file mode 100644
index 00000000000..fbfe6e13278
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME.c
@@ -0,0 +1,730 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME.c
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include "intertask_interface.h"
+
+#include "m3ap_MME.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_MME_management_procedures.h"
+#include "m3ap_MME_handler.h"
+//#include "m3ap_MME_generate_messages.h"
+#include "m3ap_common.h"
+#include "m3ap_MME_interface_management.h"
+#include "m3ap_ids.h"
+#include "m3ap_timers.h"
+
+#include "queue.h"
+#include "assertions.h"
+#include "conversions.h"
+
+struct m3ap_mme_map;
+struct m3ap_MME_data_s;
+
+m3ap_setup_req_t *m3ap_mme_data_from_mce;
+
+RB_PROTOTYPE(m3ap_mme_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+static
+void m3ap_MME_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
+static
+void m3ap_MME_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
+
+static
+void m3ap_MME_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
+
+//static
+//void m3ap_MME_handle_register_MME(instance_t instance,
+//                                  m3ap_register_mce_req_t *m3ap_register_MME);
+static
+void m3ap_MME_register_MME(m3ap_MME_instance_t *instance_p,
+                           net_ip_address_t    *target_MME_ip_addr,
+                           net_ip_address_t    *local_ip_addr,
+                           uint16_t             in_streams,
+                           uint16_t             out_streams,
+                           uint32_t             mme_port_for_M3C,
+                           int                  multi_sd);
+
+//static
+//void m3ap_MME_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req);
+//
+//static
+//void m3ap_MME_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_handover_req_ack);
+//
+//static
+//void m3ap_MME_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release);
+//
+
+static
+void m3ap_MME_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
+  int result;
+  DevAssert(sctp_data_ind != NULL);
+  m3ap_MME_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 m3ap_MME_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
+
+   DevAssert(sctp_new_association_resp != NULL);
+
+  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+    LOG_W(M3AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+              sctp_new_association_resp->sctp_state,
+              instance,
+              sctp_new_association_resp->ulp_cnx_id);
+
+    if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN)
+      //proto_agent_stop(instance);
+      //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+    return; // exit -1 for debugging
+  }
+
+   // go to an init func
+  m3ap_mme_data_from_mce = (m3ap_setup_req_t *)calloc(1, sizeof(m3ap_setup_req_t));
+  // save the assoc id
+  m3ap_mme_data_from_mce->assoc_id         = sctp_new_association_resp->assoc_id;
+  m3ap_mme_data_from_mce->sctp_in_streams  = sctp_new_association_resp->in_streams;
+  m3ap_mme_data_from_mce->sctp_out_streams = sctp_new_association_resp->out_streams;
+
+
+
+ // m3ap_MME_instance_t *instance_p;
+ // m3ap_MME_data_t *m3ap_mme_data_p;
+ // DevAssert(sctp_new_association_resp != NULL);
+ // printf("m3ap_MME_handle_sctp_association_resp at 1\n");
+ // dump_mme_trees_m3();
+ // instance_p = instance;//m3ap_MME_get_instance(instance);
+ // DevAssert(instance_p != NULL);
+
+ // /* if the assoc_id is already known, it is certainly because an IND was received
+ //  * before. In this case, just update streams and return
+ //  */
+ // if (sctp_new_association_resp->assoc_id != -1) {
+ //   m3ap_mme_data_p = m3ap_get_MME(instance_p, sctp_new_association_resp->assoc_id,
+ //                                  sctp_new_association_resp->ulp_cnx_id);
+
+ //   if (m3ap_mme_data_p != NULL) {
+ //     /* some sanity check - to be refined at some point */
+ //     if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //       M3AP_ERROR("m3ap_mme_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
+ //       abort();
+ //     }
+
+ //     m3ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ //     m3ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+ //     return;
+ //   }
+ // }
+
+ // m3ap_mme_data_p = m3ap_get_MME(instance_p, -1,
+ //                                sctp_new_association_resp->ulp_cnx_id);
+ // DevAssert(m3ap_mme_data_p != NULL);
+ // printf("m3ap_MME_handle_sctp_association_resp at 2\n");
+ // dump_mme_trees_m3();
+
+ // if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
+ //   M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
+ //             sctp_new_association_resp->sctp_state,
+ //             instance,
+ //             sctp_new_association_resp->ulp_cnx_id);
+ //   //m3ap_eNB_handle_m3_setup_message(instance_p, m3ap_mme_data_p,
+ //                                //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
+ //   return;
+ // }
+
+ // printf("m3ap_MME_handle_sctp_association_resp at 3\n");
+ // dump_mme_trees_m3();
+ // /* Update parameters */
+ // m3ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+ // m3ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+ // m3ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+ // printf("m3ap_MME_handle_sctp_association_resp at 4\n");
+ // dump_mme_trees_m3();
+ // /* Prepare new m3 Setup Request */
+ // //m3ap_MME_generate_m3_setup_request(instance_p, m3ap_mme_data_p);
+}
+
+static
+void m3ap_MME_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) {
+  //m3ap_MME_instance_t *instance_p;
+  //m3ap_MME_data_t *m3ap_mme_data_p;
+  //printf("m3ap_MME_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
+  ///dump_mme_trees_m3();
+  ///DevAssert(sctp_new_association_ind != NULL);
+  ///instance_p = instance;//m3ap_MME_get_instance(instance);
+  ///DevAssert(instance_p != NULL);
+  ///m3ap_mme_data_p = m3ap_get_MME(instance_p, sctp_new_association_ind->assoc_id, -1);
+
+  ///if (m3ap_mme_data_p != NULL) abort();
+
+  /////  DevAssert(m3ap_enb_data_p != NULL);
+  ///if (m3ap_mme_data_p == NULL) {
+  ///  /* Create new MME descriptor */
+  ///  m3ap_mme_data_p = calloc(1, sizeof(*m3ap_mme_data_p));
+  ///  DevAssert(m3ap_mme_data_p != NULL);
+  ///  m3ap_mme_data_p->cnx_id                = m3ap_MME_fetch_add_global_cnx_id();
+  ///  m3ap_mme_data_p->m3ap_MME_instance = instance_p;
+  ///  /* Insert the new descriptor in list of known MME
+  ///   * but not yet associated.
+  ///   */
+  ///  RB_INSERT(m3ap_mme_map, &instance_p->m3ap_mme_head, m3ap_mme_data_p);
+  ///  m3ap_mme_data_p->state = M3AP_MME_STATE_CONNECTED;
+  ///  instance_p->m3_target_mme_nb++;
+
+  ///  if (instance_p->m3_target_mme_pending_nb > 0) {
+  ///    instance_p->m3_target_mme_pending_nb--;
+  ///  }
+  ///} else {
+  ///  M3AP_WARN("m3ap_mme_data_p already exists\n");
+  ///}
+
+  ///printf("m3ap_MME_handle_sctp_association_ind at 2\n");
+  ///dump_mme_trees_m3();
+  ////* Update parameters */
+  ///m3ap_mme_data_p->assoc_id    = sctp_new_association_ind->assoc_id;
+  ///m3ap_mme_data_p->in_streams  = sctp_new_association_ind->in_streams;
+  ///m3ap_mme_data_p->out_streams = sctp_new_association_ind->out_streams;
+  ///printf("m3ap_MME_handle_sctp_association_ind at 3\n");
+  ///dump_mme_trees_m3();
+}
+
+int m3ap_MME_init_sctp (m3ap_MME_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t mme_port_for_M3C) {
+  // Create and alloc new message
+  MessageDef                             *message;
+  sctp_init_t                            *sctp_init  = NULL;
+  DevAssert(instance_p != NULL);
+  DevAssert(local_ip_addr != NULL);
+  message = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG_MULTI_REQ);
+  sctp_init = &message->ittiMsg.sctp_init_multi;
+  sctp_init->port = mme_port_for_M3C;
+  sctp_init->ppid = M3AP_SCTP_PPID;
+  sctp_init->ipv4 = 1;
+  sctp_init->ipv6 = 0;
+  sctp_init->nb_ipv4_addr = 1;
+#if 0
+  memcpy(&sctp_init->ipv4_address,
+         local_ip_addr,
+         sizeof(*local_ip_addr));
+#endif
+  sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  sctp_init->nb_ipv6_addr = 0;
+  sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
+  return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
+}
+
+static void m3ap_MME_register_MME(m3ap_MME_instance_t *instance_p,
+                                  net_ip_address_t    *target_MME_ip_address,
+                                  net_ip_address_t    *local_ip_addr,
+                                  uint16_t             in_streams,
+                                  uint16_t             out_streams,
+                                  uint32_t             mme_port_for_M3C,
+                                  int                  multi_sd) {
+ // MessageDef                       *message                   = NULL;
+ // sctp_new_association_req_multi_t *sctp_new_association_req  = NULL;
+ // m3ap_MME_data_t                  *m3ap_mme_data             = NULL;
+ // DevAssert(instance_p != NULL);
+ // DevAssert(target_MME_ip_address != NULL);
+ // message = itti_alloc_new_message(TASK_M3AP_MME, SCTP_NEW_ASSOCIATION_REQ_MULTI);
+ // sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
+ // sctp_new_association_req->port = mme_port_for_M3C;
+ // sctp_new_association_req->ppid = M3AP_SCTP_PPID;
+ // sctp_new_association_req->in_streams  = in_streams;
+ // sctp_new_association_req->out_streams = out_streams;
+ // sctp_new_association_req->multi_sd = multi_sd;
+ // memcpy(&sctp_new_association_req->remote_address,
+ //        target_MME_ip_address,
+ //        sizeof(*target_MME_ip_address));
+ // memcpy(&sctp_new_association_req->local_address,
+ //        local_ip_addr,
+ //        sizeof(*local_ip_addr));
+ // /* Create new MME descriptor */
+ // m3ap_mme_data = calloc(1, sizeof(*m3ap_mme_data));
+ // DevAssert(m3ap_mme_data != NULL);
+ // m3ap_mme_data->cnx_id                = m3ap_MME_fetch_add_global_cnx_id();
+ // sctp_new_association_req->ulp_cnx_id = m3ap_mme_data->cnx_id;
+ // m3ap_mme_data->assoc_id          = -1;
+ // m3ap_mme_data->m3ap_MME_instance = instance_p;
+ // /* Insert the new descriptor in list of known MME
+ //  * but not yet associated.
+ //  */
+ // RB_INSERT(m3ap_mme_map, &instance_p->m3ap_mme_head, m3ap_mme_data);
+ // m3ap_mme_data->state = M3AP_MME_STATE_WAITING;
+ // instance_p->m3_target_mme_nb ++;
+ // instance_p->m3_target_mme_pending_nb ++;
+ // itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
+}
+
+//static
+//void m3ap_MME_handle_register_MME(instance_t instance,
+//                                  m3ap_register_mce_req_t *m3ap_register_MME) {
+//  m3ap_MME_instance_t *new_instance;
+//  DevAssert(m3ap_register_MME != NULL);
+//  /* Look if the provided instance already exists */
+//  new_instance = m3ap_MME_get_instance(instance);
+//
+//  if (new_instance != NULL) {
+//    /* Checks if it is a retry on the same MME */
+//    DevCheck(new_instance->MME_id == m3ap_register_MME->MME_id, new_instance->MME_id, m3ap_register_MME->MME_id, 0);
+//    DevCheck(new_instance->cell_type == m3ap_register_MME->cell_type, new_instance->cell_type, m3ap_register_MME->cell_type, 0);
+//    DevCheck(new_instance->tac == m3ap_register_MME->tac, new_instance->tac, m3ap_register_MME->tac, 0);
+//    DevCheck(new_instance->mcc == m3ap_register_MME->mcc, new_instance->mcc, m3ap_register_MME->mcc, 0);
+//    DevCheck(new_instance->mnc == m3ap_register_MME->mnc, new_instance->mnc, m3ap_register_MME->mnc, 0);
+//    M3AP_WARN("MME[%d] already registered\n", instance);
+//  } else {
+//    new_instance = calloc(1, sizeof(m3ap_MME_instance_t));
+//    DevAssert(new_instance != NULL);
+//    RB_INIT(&new_instance->m3ap_mme_head);
+//    /* Copy usefull parameters */
+//    new_instance->instance         = instance;
+//    new_instance->MME_name         = m3ap_register_MME->MME_name;
+//    new_instance->MME_id           = m3ap_register_MME->MME_id;
+//    new_instance->cell_type        = m3ap_register_MME->cell_type;
+//    new_instance->tac              = m3ap_register_MME->tac;
+//    new_instance->mcc              = m3ap_register_MME->mcc;
+//    new_instance->mnc              = m3ap_register_MME->mnc;
+//    new_instance->mnc_digit_length = m3ap_register_MME->mnc_digit_length;
+//    new_instance->num_cc           = m3ap_register_MME->num_cc;
+//
+//    m3ap_id_manager_init(&new_instance->id_manager);
+//    m3ap_timers_init(&new_instance->timers,
+//                     m3ap_register_MME->t_reloc_prep,
+//                     m3ap_register_MME->tm3_reloc_overall);
+//
+//    for (int i = 0; i< m3ap_register_MME->num_cc; i++) {
+//      new_instance->eutra_band[i]              = m3ap_register_MME->eutra_band[i];
+//      new_instance->downlink_frequency[i]      = m3ap_register_MME->downlink_frequency[i];
+//      new_instance->uplink_frequency_offset[i] = m3ap_register_MME->uplink_frequency_offset[i];
+//      new_instance->Nid_cell[i]                = m3ap_register_MME->Nid_cell[i];
+//      new_instance->N_RB_DL[i]                 = m3ap_register_MME->N_RB_DL[i];
+//      new_instance->frame_type[i]              = m3ap_register_MME->frame_type[i];
+//      new_instance->fdd_earfcn_DL[i]           = m3ap_register_MME->fdd_earfcn_DL[i];
+//      new_instance->fdd_earfcn_UL[i]           = m3ap_register_MME->fdd_earfcn_UL[i];
+//    }
+//
+//    DevCheck(m3ap_register_MME->nb_m3 <= M3AP_MAX_NB_MME_IP_ADDRESS,
+//             M3AP_MAX_NB_MME_IP_ADDRESS, m3ap_register_MME->nb_m3, 0);
+//    memcpy(new_instance->target_mme_m3_ip_address,
+//           m3ap_register_MME->target_mme_m3_ip_address,
+//           m3ap_register_MME->nb_m3 * sizeof(net_ip_address_t));
+//    new_instance->nb_m3             = m3ap_register_MME->nb_m3;
+//    new_instance->mme_m3_ip_address = m3ap_register_MME->mme_m3_ip_address;
+//    new_instance->sctp_in_streams   = m3ap_register_MME->sctp_in_streams;
+//    new_instance->sctp_out_streams  = m3ap_register_MME->sctp_out_streams;
+//    new_instance->mme_port_for_M3C  = m3ap_register_MME->mme_port_for_M3C;
+//    /* Add the new instance to the list of MME (meaningfull in virtual mode) */
+//    m3ap_MME_insert_new_instance(new_instance);
+//    M3AP_INFO("Registered new MME[%d] and %s MME id %u\n",
+//              instance,
+//              m3ap_register_MME->cell_type == CELL_MACRO_ENB ? "macro" : "home",
+//              m3ap_register_MME->MME_id);
+//
+//    /* initiate the SCTP listener */
+//    if (m3ap_MME_init_sctp(new_instance,&m3ap_register_MME->mme_m3_ip_address,m3ap_register_MME->mme_port_for_M3C) <  0 ) {
+//      M3AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
+//      return;
+//    }
+//
+//    M3AP_INFO("MME[%d] MME id %u acting as a listner (server)\n",
+//              instance, m3ap_register_MME->MME_id);
+//  }
+//}
+
+static
+void m3ap_MME_handle_sctp_init_msg_multi_cnf(
+  instance_t instance_id,
+  sctp_init_msg_multi_cnf_t *m) {
+  m3ap_MME_instance_t *instance;
+  int index;
+  DevAssert(m != NULL);
+  instance = m3ap_MME_get_instance(instance_id);
+  DevAssert(instance != NULL);
+  instance->multi_sd = m->multi_sd;
+
+  /* Exit if CNF message reports failure.
+   * Failure means multi_sd < 0.
+   */
+  if (instance->multi_sd < 0) {
+    M3AP_ERROR("Error: be sure to properly configure M2 in your configuration file.\n");
+    DevAssert(instance->multi_sd >= 0);
+  }
+
+  /* Trying to connect to the provided list of MME ip address */
+
+  for (index = 0; index < instance->nb_m3; index++) {
+    M3AP_INFO("MME[%d] MME id %u acting as an initiator (client)\n",
+              instance_id, instance->MME_id);
+    m3ap_MME_register_MME(instance,
+                          &instance->target_mme_m3_ip_address[index],
+                          &instance->mme_m3_ip_address,
+                          instance->sctp_in_streams,
+                          instance->sctp_out_streams,
+                          instance->mme_port_for_M3C,
+                          instance->multi_sd);
+  }
+}
+
+//static
+//void m3ap_MME_handle_handover_req(instance_t instance,
+//                                  m3ap_handover_req_t *m3ap_handover_req)
+//{
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  m3ap_id_manager     *id_manager;
+//  int                 ue_id;
+//
+//  int target_pci = m3ap_handover_req->target_physCellId;
+//
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_is_MME_pci_in_list(target_pci);
+//  DevAssert(target != NULL);
+//
+//  /* allocate m3ap ID */
+//  id_manager = &instance_p->id_manager;
+//  ue_id = m3ap_allocate_new_id(id_manager);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not allocate a new M3AP UE ID\n");
+//    /* TODO: cancel handover: send (to be defined) message to RRC */
+//    exit(1);
+//  }
+//  /* id_source is ue_id, id_target is unknown yet */
+//  m3ap_set_ids(id_manager, ue_id, m3ap_handover_req->rnti, ue_id, -1);
+//  m3ap_id_set_state(id_manager, ue_id, M2ID_STATE_SOURCE_PREPARE);
+//  m3ap_set_reloc_prep_timer(id_manager, ue_id,
+//                            m3ap_timer_get_tti(&instance_p->timers));
+//  m3ap_id_set_target(id_manager, ue_id, target);
+//
+//  m3ap_MME_generate_m3_handover_request(instance_p, target, m3ap_handover_req, ue_id);
+//}
+
+//static
+//void m3ap_MME_handle_handover_req_ack(instance_t instance,
+//                                      m3ap_handover_req_ack_t *m3ap_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 M3AP to identify eNodeBs
+//   * RRC knows about mod_id and M3AP knows about MME_id (MME_ID in
+//   * the configuration file)
+//   * as far as I understand.. CROUX
+//   */
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  int source_assoc_id = m3ap_handover_req_ack->source_assoc_id;
+//  int                 ue_id;
+//  int                 id_source;
+//  int                 id_target;
+//
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_MME(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  /* rnti is a new information, save it */
+//  ue_id     = m3ap_handover_req_ack->m3_id_target;
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, m3ap_handover_req_ack->rnti, id_source, id_target);
+//
+//  m3ap_MME_generate_m3_handover_request_ack(instance_p, target, m3ap_handover_req_ack);
+//}
+//
+//static
+//void m3ap_MME_ue_context_release(instance_t instance,
+//                                 m3ap_ue_context_release_t *m3ap_ue_context_release)
+//{
+//  m3ap_MME_instance_t *instance_p;
+//  m3ap_MME_data_t     *target;
+//  int source_assoc_id = m3ap_ue_context_release->source_assoc_id;
+//  int ue_id;
+//  instance_p = m3ap_MME_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  target = m3ap_get_MME(NULL, source_assoc_id, 0);
+//  DevAssert(target != NULL);
+//
+//  m3ap_MME_generate_m3_ue_context_release(instance_p, target, m3ap_ue_context_release);
+//
+//  /* free the M3AP UE ID */
+//  ue_id = m3ap_find_id_from_rnti(&instance_p->id_manager, m3ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not find UE %x\n", m3ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//}
+
+void MME_task_send_sctp_init_req(instance_t enb_id, m3ap_mme_sctp_req_t * m3ap_mme_sctp_req) {
+  // 1. get the itti msg, and retrive the enb_id from the message
+  // 2. use RC.rrc[enb_id] to fill the sctp_init_t with the ip, port
+  // 3. creat an itti message to init
+
+  MessageDef  *message_p = NULL;
+
+  message_p = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG);
+if(m3ap_mme_sctp_req==NULL) {
+  LOG_I(M3AP, "M3AP_SCTP_REQ(create socket)\n");
+  message_p->ittiMsg.sctp_init.port = M3AP_PORT_NUMBER;
+  message_p->ittiMsg.sctp_init.ppid = M3AP_SCTP_PPID;
+  message_p->ittiMsg.sctp_init.ipv4 = 1;
+  message_p->ittiMsg.sctp_init.ipv6 = 0;
+  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr("127.0.0.8");
+
+}else{
+
+  LOG_I(M3AP, "M3AP_SCTP_REQ(create socket) %s\n",m3ap_mme_sctp_req->mme_m3_ip_address.ipv4_address);
+ message_p->ittiMsg.sctp_init.port = m3ap_mme_sctp_req->mme_port_for_M3C;
+  message_p->ittiMsg.sctp_init.ppid = M3AP_SCTP_PPID;
+  message_p->ittiMsg.sctp_init.ipv4 = 1;
+  message_p->ittiMsg.sctp_init.ipv6 = 0;
+  message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
+  //message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(m3ap_mme_sctp_req->mme_m3_ip_address.ipv4_address);
+ } 
+
+  /*
+   * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
+   * * * * Disable it for now.
+   */
+  message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0;
+  message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1";
+
+  itti_send_msg_to_task(TASK_SCTP, enb_id, message_p);
+}
+
+void *m3ap_MME_task(void *arg) {
+  MessageDef *received_msg = NULL;
+  int         result;
+  M3AP_DEBUG("Starting M3AP layer\n");
+  m3ap_MME_prepare_internal_data();
+  itti_mark_task_ready(TASK_M3AP_MME);
+
+  //MME_task_send_sctp_init_req(0,NULL);
+
+
+  while (1) {
+    itti_receive_msg(TASK_M3AP_MME, &received_msg);
+
+    switch (ITTI_MSG_ID(received_msg)) {
+      case MESSAGE_TEST:
+	LOG_W(M3AP,"MME Received MESSAGE_TEST Message\n");
+	//MessageDef * message_p = itti_alloc_new_message(TASK_M3AP_MME, MESSAGE_TEST);
+        //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p);
+	break;
+      case TERMINATE_MESSAGE:
+        M3AP_WARN(" *** Exiting M3AP thread\n");
+        itti_exit_task();
+        break;
+
+//      case M3AP_SUBFRAME_PROCESS:
+//        m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
+//        break;
+//
+//      case M3AP_REGISTER_MME_REQ:
+//	LOG_W(M3AP,"MME Received M3AP_REGISTER_MME_REQ Message\n");
+//        m3ap_MME_handle_register_MME(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_REGISTER_MME_REQ(received_msg));
+//        break;
+//
+
+      case M3AP_MME_SCTP_REQ:
+  	MME_task_send_sctp_init_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M3AP_MME_SCTP_REQ(received_msg));
+	break;
+
+      case M3AP_SETUP_RESP:
+	LOG_I(M3AP,"MME Received M3AP_SETUP_RESP Message\n");
+	MME_send_M3_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+				    &M3AP_SETUP_RESP(received_msg));
+	break;
+//	break;
+//
+//      case M3AP_SETUP_FAILURE:
+//	LOG_W(M3AP,"MME Received M3AP_SETUP_FAILURE Message\n");
+//	MME_send_M2_SETUP_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//				    &M3AP_SETUP_FAILURE(received_msg));
+//	break;
+//
+//      case M3AP_MBMS_SCHEDULING_INFORMATION:
+//	LOG_W(M3AP,"MME Received M3AP_MBMS_SCHEDULING_INFORMATION Message\n");
+//        MME_send_MBMS_SCHEDULING_INFORMATION(0,
+//						&M3AP_MBMS_SCHEDULING_INFORMATION(received_msg));
+//
+       case M3AP_MBMS_SESSION_START_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_START_REQ Message\n");
+        MME_send_MBMS_SESSION_START_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+						&M3AP_MBMS_SESSION_START_REQ(received_msg));
+	break;
+//
+       case M3AP_MBMS_SESSION_STOP_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_STOP_REQ Message\n");
+        MME_send_MBMS_SESSION_STOP_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+						&M3AP_MBMS_SESSION_STOP_REQ(received_msg));
+	break;
+//	
+       case M3AP_MBMS_SESSION_UPDATE_REQ:
+	LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_UPDATE_REQ Message\n");
+       // MME_send_MBMS_SESSION_UPDATE_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+	//					&M3AP_MBMS_SESSION_UPDATE_REQ(received_msg));
+	break;
+//
+//       case M3AP_RESET:
+//	LOG_W(M3AP,"MME Received M3AP_RESET Message\n");
+//        MME_send_RESET(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_RESET(received_msg));
+//	break;
+//
+//       case M3AP_ENB_CONFIGURATION_UPDATE_ACK:
+//	LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_ACK Message\n");
+//        MME_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_ENB_CONFIGURATION_UPDATE_ACK(received_msg));
+//	break;
+//
+//       case M3AP_ENB_CONFIGURATION_UPDATE_FAILURE:
+//	LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_FAILURE Message\n");
+//        MME_send_ENB_CONFIGURATION_UPDATE_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_ENB_CONFIGURATION_UPDATE_FAILURE(received_msg))//	break;
+//
+//
+//       case M3AP_MME_CONFIGURATION_UPDATE:
+//	LOG_W(M3AP,"MME Received M3AP_MME_CONFIGURATION_UPDATE Message\n");
+//        MME_send_MME_CONFIGURATION_UPDATE(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//						&M3AP_MME_CONFIGURATION_UPDATE(received_msg));
+//	break;
+//
+
+//      case M3AP_HANDOVER_REQ:
+//        m3ap_MME_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                     &M3AP_HANDOVER_REQ(received_msg));
+//        break;
+//
+//      case M3AP_HANDOVER_REQ_ACK:
+//        m3ap_MME_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                         &M3AP_HANDOVER_REQ_ACK(received_msg));
+//        break;
+//
+//      case M3AP_UE_CONTEXT_RELEASE:
+//        m3ap_MME_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+//                                                &M3AP_UE_CONTEXT_RELEASE(received_msg));
+//        break;
+//
+      case SCTP_INIT_MSG_MULTI_CNF:
+        LOG_E(M3AP,"MME Received SCTP_INIT_MSG_MULTI_CNF Message ... shoudn't be happening ... it doesn't at leaast with M2AP_MCEC\n");
+        m3ap_MME_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                               &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_RESP:
+        LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION_RESP Message\n");
+        m3ap_MME_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                              &received_msg->ittiMsg.sctp_new_association_resp);
+        break;
+
+      case SCTP_NEW_ASSOCIATION_IND:
+        LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION Message\n");
+        m3ap_MME_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                             &received_msg->ittiMsg.sctp_new_association_ind);
+        break;
+
+      case SCTP_DATA_IND:
+        LOG_D(M3AP,"MME Received SCTP_DATA_IND Message\n");
+        m3ap_MME_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                      &received_msg->ittiMsg.sctp_data_ind);
+        break;
+
+      default:
+        M3AP_ERROR("MME Received unhandled message: %d:%s\n",
+                   ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
+        break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    received_msg = NULL;
+  }
+
+  return NULL;
+}
+
+#include "common/config/config_userapi.h"
+
+int is_m3ap_MME_enabled(void)
+{
+  static volatile int config_loaded = 0;
+  static volatile int enabled = 0;
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  if (pthread_mutex_lock(&mutex)) goto mutex_error;
+
+  if (config_loaded) {
+    if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+    return enabled;
+  }
+
+  char *enable_m3 = NULL;
+  paramdef_t p[] = {
+   { "enable_mme_m3", "yes/no", 0, strptr:&enable_m3, defstrval:"", TYPE_STRING, 0 }
+  };
+
+  /* TODO: do it per module - we check only first MME */
+  config_get(p, sizeof(p)/sizeof(paramdef_t), "MMEs.[0]");
+  if (enable_m3 != NULL && strcmp(enable_m3, "yes") == 0)
+    enabled = 1;
+
+  config_loaded = 1;
+
+  if (pthread_mutex_unlock(&mutex)) goto mutex_error;
+
+  return enabled;
+
+mutex_error:
+  LOG_E(M3AP, "mutex error\n");
+  exit(1);
+}
diff --git a/openair3/M3AP/m3ap_MME.h b/openair3/M3AP/m3ap_MME.h
new file mode 100644
index 00000000000..f5d1b158e43
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME.h
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
+ * @ingroup _ref_implementation_
+ * @{
+ */
+
+#ifndef M3AP_MME_H_
+#define M3AP_MME_H_
+
+#include "m3ap_MME_defs.h"
+
+
+int m3ap_MME_init_sctp (m3ap_MME_instance_t *instance_p,
+                        net_ip_address_t    *local_ip_addr,
+                        uint32_t enb_port_for_M3C);
+
+void *m3ap_MME_task(void *arg);
+
+int is_m3ap_MME_enabled(void);
+
+#endif /* M3AP_MCE_H_ */
+
+/**
+ * @}
+ */
diff --git a/openair3/M3AP/m3ap_MME_defs.h b/openair3/M3AP/m3ap_MME_defs.h
new file mode 100644
index 00000000000..3b5725655de
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_defs.h
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_defs.h
+ * \brief m2ap struct definitions for MME
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "tree.h"
+
+#include "sctp_eNB_defs.h"
+
+#include "m3ap_ids.h" //looks X2AP specific for HO
+#include "m3ap_timers.h"
+
+#ifndef M3AP_MME_DEFS_H_
+#define M3AP_MME_DEFS_H_
+
+#define M3AP_MME_NAME_LENGTH_MAX    (150)
+
+typedef enum {
+  /* Disconnected state: initial state for any association. */
+  M3AP_MME_STATE_DISCONNECTED = 0x0,
+
+  /* State waiting for m2 Setup response message if the target MME accepts or
+   * M2 Setup failure if rejects the MME.
+   */
+  M3AP_MME_STATE_WAITING     = 0x1,
+
+  /* The MME is successfully connected to another MME. */
+  M3AP_MME_STATE_CONNECTED   = 0x2,
+
+  /* M3AP is ready, and the MME is successfully connected to another MME. */
+  M3AP_MME_STATE_READY             = 0x3,
+
+  M3AP_MME_STATE_OVERLOAD          = 0x4,
+
+  M3AP_MME_STATE_RESETTING         = 0x5,
+
+  /* Max number of states available */
+  M3AP_MME_STATE_MAX,
+} m3ap_MME_state_t;
+
+/* Served PLMN identity element */
+/*struct plmn_identity_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_digit_length;
+  STAILQ_ENTRY(plmn_identity_s) next;
+};*/
+
+/* Served group id element */
+/*struct served_group_id_s {
+  uint16_t mce_group_id;
+  STAILQ_ENTRY(served_group_id_s) next;
+};*/
+
+/* Served enn code for a particular MME */
+/*struct mce_code_s {
+  uint8_t mce_code;
+  STAILQ_ENTRY(mce_code_s) next;
+};*/
+
+struct m3ap_MME_instance_s;
+
+/* This structure describes association of a MME to another MME */
+typedef struct m3ap_MME_data_s {
+  /* MME descriptors tree, ordered by sctp assoc id */
+  RB_ENTRY(m3ap_MME_data_s) entry;
+
+  /* This is the optional name provided by the MME */
+  char *MME_name;
+
+  /*  target MME ID */
+  uint32_t MME_id;
+
+  /* Current MME load information (if any). */
+  //m3ap_load_state_t overload_state;
+
+  /* Current MME->MME M3AP association state */
+  m3ap_MME_state_t state;
+
+  /* Next usable stream for UE signalling */
+  int32_t nextstream;
+
+  /* Number of input/ouput streams */
+  uint16_t in_streams;
+  uint16_t out_streams;
+
+  /* Connexion id used between SCTP/M3AP */
+  uint16_t cnx_id;
+
+  /* SCTP association id */
+  int32_t  assoc_id;
+
+  /* Nid cells */
+  uint32_t                Nid_cell[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* Only meaningfull in virtual mode */
+  struct m3ap_MME_instance_s *m3ap_MME_instance;
+} m3ap_MME_data_t;
+
+typedef struct m3ap_MME_instance_s {
+  /* used in simulation to store multiple MME instances*/
+  STAILQ_ENTRY(m3ap_MME_instance_s) m3ap_MME_entries;
+
+  /* Number of target MMEs requested by MME (tree size) */
+  uint32_t m2_target_mce_nb;
+  /* Number of target MMEs for which association is pending */
+  uint32_t m2_target_mce_pending_nb;
+  /* Number of target MME successfully associated to MME */
+  uint32_t m2_target_mce_associated_nb;
+  /* Tree of M3AP MME associations ordered by association ID */
+  RB_HEAD(m3ap_mme_map, m3ap_MME_data_s) m3ap_mme_head;
+
+  /* Tree of UE ordered by MME_ue_m3ap_id's */
+  //  RB_HEAD(m3ap_ue_map, m3ap_MME_ue_context_s) m3ap_ue_head;
+
+  /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
+  instance_t instance;
+
+  /* Displayable name of MME */
+  char *MME_name;
+
+  /* Unique MME_id to identify the MME within EPC.
+   * In our case the MME is a macro MME so the id will be 20 bits long.
+   * For Home MME id, this field should be 28 bits long.
+   */
+  uint32_t MME_id;
+  /* The type of the cell */
+  cell_type_t cell_type;
+
+  /* Tracking area code */
+  uint16_t tac;
+
+  /* Mobile Country Code
+   * Mobile Network Code
+   */
+  uint16_t  mcc;
+  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_mme_m3_ip_address[M3AP_MAX_NB_MME_IP_ADDRESS];
+  uint8_t          nb_m3;
+  net_ip_address_t mme_m3_ip_address;
+  uint16_t         sctp_in_streams;
+  uint16_t         sctp_out_streams;
+  uint32_t         mme_port_for_M3C;
+  int              multi_sd;
+
+  m3ap_id_manager  id_manager;
+  m3ap_timers_t    timers;
+} m3ap_MME_instance_t;
+
+typedef struct {
+  /* List of served MMEs
+   * Only used for virtual mode
+   */
+  STAILQ_HEAD(m3ap_MME_instances_head_s, m3ap_MME_instance_s) m3ap_MME_instances_head;
+  /* Nb of registered MMEs */
+  uint8_t nb_registered_MMEs;
+
+  /* Generate a unique connexion id used between M3AP and SCTP */
+  uint16_t global_cnx_id;
+} m3ap_MME_internal_data_t;
+
+int m3ap_MME_compare_assoc_id(struct m3ap_MME_data_s *p1, struct m3ap_MME_data_s *p2);
+
+/* Generate the tree management functions */
+struct m3ap_MME_map;
+struct m3ap_MME_data_s;
+RB_PROTOTYPE(m3ap_MME_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+
+#endif /* M3AP_MME_DEFS_H_ */
diff --git a/openair3/M3AP/m3ap_MME_generate_messages.c b/openair3/M3AP/m3ap_MME_generate_messages.c
new file mode 100644
index 00000000000..a28097cf1af
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_generate_messages.c
@@ -0,0 +1,804 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.c
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M2AP_LastVisitedCell-Item.h"
+
+#include "m2ap_common.h"
+#include "m2ap_MCE.h"
+#include "m2ap_MCE_generate_messages.h"
+#include "m2ap_encoder.h"
+#include "m2ap_decoder.h"
+#include "m2ap_ids.h"
+
+#include "m2ap_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m2ap_MCE_generate_m2_setup_request(
+  m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupRequest_t              *out;
+  M2AP_M2SetupRequest_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t               *plmn;
+  //ServedCells__Member                *servedCellMember;
+  //M2AP_GU_Group_ID_t                 *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_WAITING;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_M2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M2SetupRequest;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_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_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_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 = M2AP_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 = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setuprequest not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupRequest_Ies_t *)calloc(1, sizeof(M2AP_M2SetupRequest_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupRequest_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_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 (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup request\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupResponse_t              *out;
+  M2AP_M2SetupResponse_Ies_t          *ie;
+  //M2AP_PLMN_Identity_t                *plmn;
+  //ServedCells__Member                 *servedCellMember;
+  //M2AP_GU_Group_ID_t                  *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m2ap_MCE_data_p != NULL);
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_M2SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.M2SetupResponse;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GlobalMCE_ID;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GlobalMCE_ID;
+  //MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+  //                  &ie->value.choice.GlobalMCE_ID.pLMN_Identity);
+  //ie->value.choice.GlobalMCE_ID.MCE_ID.present = M2AP_MCE_ID_PR_macro_MCE_ID;
+  //MACRO_MCE_ID_TO_BIT_STRING(instance_p->MCE_id,
+  //                           &ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID);
+  //M2AP_INFO("%d -> %02x%02x%02x\n", instance_p->MCE_id,
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[0],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[1],
+  //          ie->value.choice.GlobalMCE_ID.MCE_ID.choice.macro_MCE_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_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_MCE_ID_TO_CELL_IDENTITY(instance_p->MCE_id,0,
+  //                                 &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+  //      INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+  //      plmn = (M2AP_PLMN_Identity_t *)calloc(1,sizeof(M2AP_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 = M2AP_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 = M2AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M2AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setupresponse not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M2AP_M2SetupResponse_Ies_t *)calloc(1, sizeof(M2AP_M2SetupResponse_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M2AP_Criticality_reject;
+  //ie->value.present = M2AP_M2SetupResponse_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M2AP_GU_Group_ID_t *)calloc(1, sizeof(M2AP_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 (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup response\n");
+    return -1;
+  }
+
+  m2ap_MCE_data_p->state = M2AP_MCE_STATE_READY;
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 M2Setup/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait)
+{
+  M2AP_M2AP_PDU_t                     pdu;
+  M2AP_M2SetupFailure_t              *out;
+  M2AP_M2SetupFailure_Ies_t          *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  /* Prepare the M2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_m2Setup;
+  pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+
+  /* mandatory */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_Cause;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_Cause;
+
+  //m2ap_MCE_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional: consider to handle this later */
+  ie = (M2AP_M2SetupFailure_Ies_t *)calloc(1, sizeof(M2AP_M2SetupFailure_Ies_t));
+  //ie->id = M2AP_ProtocolIE_ID_id_TimeToWait;
+  //ie->criticality = M2AP_Criticality_ignore;
+  //ie->value.present = M2AP_M2SetupFailure_IEs__value_PR_TimeToWait;
+
+  //if (time_to_wait > -1) {
+  //  ie->value.choice.TimeToWait = time_to_wait;
+  //}
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M2AP_ERROR("Failed to encode M2 setup failure\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE,
+  //                    MSC_M2AP_TARGET_MCE, NULL, 0,
+  //                    "0 M2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+  //                    assoc_id, cause_type, cause_value);
+
+  m2ap_MCE_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id)
+//{
+//
+//  M2AP_M2AP_PDU_t                     pdu;
+//  M2AP_HandoverRequest_t              *out;
+//  M2AP_HandoverRequest_IEs_t          *ie;
+//  M2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_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_MCE_ID_TO_CELL_IDENTITY(m2ap_MCE_data_p->MCE_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_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(m2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m2ap_handover_req->mme_ue_s1ap_id;
+//
+//  KMCE_STAR_TO_BIT_STRING(m2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m2ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m2ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m2ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m2ap_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<m2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M2AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M2AP_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 = m2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m2ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m2ap_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 = m2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m2ap_handover_req->e_rabs_tobesetup[i].MCE_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,
+//                        m2ap_handover_req->e_rabs_tobesetup[i].MCE_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m2ap_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*) m2ap_handover_req->rrc_buffer, m2ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequest_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M2AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M2AP_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_MCE_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 = M2AP_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 (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack)
+//{
+//
+//  M2AP_M2AP_PDU_t                        pdu;
+//  M2AP_HandoverRequestAcknowledge_t      *out;
+//  M2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id     = m2ap_handover_req_ack->m2_id_target;
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M2AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M2AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M2AP_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 = m2ap_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 = (M2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M2AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_TargetMCEtoSource_MCETransparentContainer;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverRequestAcknowledge_IEs__value_PR_TargetMCEtoSource_MCETransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargetMCEtoSource_MCETransparentContainer, (char*) m2ap_handover_req_ack->rrc_buffer, m2ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p, m2ap_ue_context_release_t *m2ap_ue_context_release)
+//{
+//
+//  M2AP_M2AP_PDU_t                pdu;
+//  M2AP_UEContextRelease_t        *out;
+//  M2AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2ap_find_id_from_rnti(&instance_p->id_manager, m2ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M2AP_ERROR("could not find UE %x\n", m2ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m2ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M2AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M2AP_UEContextRelease_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_UEContextRelease_IEs__value_PR_UE_M2AP_ID_1;
+//  ie->value.choice.UE_M2AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause)
+//{
+//  M2AP_M2AP_PDU_t              pdu;
+//  M2AP_HandoverCancel_t        *out;
+//  M2AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m2ap_MCE_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m2ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M2AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M2AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Old_MCE_UE_M2AP_ID;
+//  ie->criticality = M2AP_Criticality_reject;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID;
+//  ie->value.choice.UE_M2AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//    ie->id = M2AP_ProtocolIE_ID_id_New_MCE_UE_M2AP_ID;
+//    ie->criticality = M2AP_Criticality_ignore;
+//    ie->value.present = M2AP_HandoverCancel_IEs__value_PR_UE_M2AP_ID_1;
+//    ie->value.choice.UE_M2AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M2AP_HandoverCancel_IEs_t));
+//  ie->id = M2AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M2AP_Criticality_ignore;
+//  ie->value.present = M2AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M2AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M2AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M2AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M2AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m2ap_MCE_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M2AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M2AP_SRC_MCE, MSC_M2AP_TARGET_MCE, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m2ap_MCE_data_p->assoc_id);
+//
+//  m2ap_MCE_itti_send_sctp_data_req(instance_p->instance, m2ap_MCE_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair3/M3AP/m3ap_MME_generate_messages.h b/openair3/M3AP/m3ap_MME_generate_messages.h
new file mode 100644
index 00000000000..1632dc807ac
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_MCE_generate_messages.h
+ * \brief m2ap procedures for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_GENERATE_MESSAGES_H_
+#define M2AP_MCE_GENERATE_MESSAGES_H_
+
+#include "m2ap_MCE_defs.h"
+#include "m2ap_common.h"
+
+int m2ap_MCE_generate_m2_setup_request(m2ap_MCE_instance_t *instance_p,
+				       m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_response(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p);
+
+int m2ap_MCE_generate_m2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);
+
+int m2ap_MCE_set_cause (M2AP_Cause_t * cause_p,
+                        M2AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m2ap_MCE_generate_m2_handover_request (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                           m2ap_handover_req_t *m2ap_handover_req, int ue_id);
+//
+//int m2ap_MCE_generate_m2_handover_request_ack (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                               m2ap_handover_req_ack_t *m2ap_handover_req_ack);
+//
+//int m2ap_MCE_generate_m2_ue_context_release (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                             m2ap_ue_context_release_t *m2ap_ue_context_release);
+//
+//int m2ap_MCE_generate_m2_handover_cancel (m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_MCE_data_p,
+//                                          int m2_ue_id,
+//                                          m2ap_handover_cancel_cause_t cause);
+
+#endif /*  M2AP_MCE_GENERATE_MESSAGES_H_ */
diff --git a/openair3/M3AP/m3ap_MME_handler.c b/openair3/M3AP/m3ap_MME_handler.c
new file mode 100644
index 00000000000..9af8cbe14fc
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_handler.c
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MME_management_procedures.h"
+//#include "m3ap_MCE_generate_messages.h"
+
+#include "m3ap_MME_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_MCE_message_decoded_callback m3ap_MME_messages_callback[][3] = {
+  { 0, MME_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { 0, MME_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { 0, MME_handle_MBMS_SESSION_UPDATE_RESPONSE, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { MME_handle_M3_SETUP_REQUEST, 0, 0 } /* M3 Setup */
+};
+
+static char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_MME_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+ 
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_MME_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[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_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_MME_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_MME_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_MME_handler.h b/openair3/M3AP/m3ap_MME_handler.h
new file mode 100644
index 00000000000..feabfe256c4
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_handler.h
+ * \brief m3ap handler procedures for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MME_HANDLERS_H_
+#define M3AP_MME_HANDLERS_H_
+
+#include "m3ap_MME_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_MME_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M3AP_MME_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_MME_interface_management.c b/openair3/M3AP/m3ap_MME_interface_management.c
new file mode 100644
index 00000000000..e5cb03cf263
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_interface_management.c
@@ -0,0 +1,1162 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_interface_management.c
+ * \brief m3ap interface management for MME
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "m3ap_common.h"
+#include "m3ap_encoder.h"
+#include "m3ap_decoder.h"
+#include "m3ap_itti_messaging.h"
+#include "m3ap_MME_interface_management.h"
+
+#include "conversions.h"
+
+#include "M3AP_ECGI.h"
+
+extern m3ap_setup_req_t *m3ap_mme_data_from_mce;
+
+
+
+uint8_t m3ap_start_message[] = {
+  0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00,
+  0x07, 0x00, 0x55, 0xf5, 0x01, 0x00, 0x00, 0x01,
+  0x00, 0x04, 0x00, 0x0d, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x01,
+  0x7a, 0x00, 0x05, 0x00, 0x03, 0x07, 0x08, 0x00,
+  0x00, 0x06, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+  0x0e, 0x00, 0xe8, 0x0a, 0x0a, 0x0a, 0x00, 0x0a,
+  0xc8, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01
+};
+
+
+/*
+ * MBMS Session start
+ */
+int MME_send_MBMS_SESSION_START_REQUEST(instance_t instance/*, uint32_t assoc_id*/,m3ap_session_start_req_t* m3ap_session_start_req){
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+    
+  //module_id_t enb_mod_idP=0;
+  //module_id_t du_mod_idP=0;
+
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionStartRequest_t       *out;
+  M3AP_MBMSSessionStartRequest_IEs_t   *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStart;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionStartRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionStartRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. TMGI */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TMGI; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_TMGI;
+  M3AP_TMGI_t	*tmgi 		= &ie->value.choice.TMGI;
+  {
+	  MCC_MNC_TO_PLMNID(0,0,3,&tmgi->pLMNidentity);
+	  uint8_t TMGI[5] = {4,3,2,1,0};
+	  OCTET_STRING_fromBuf(&tmgi->serviceID,(const char*)&TMGI[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2. MBMS_Session_ID */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_ID;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Session_ID;
+	  //M3AP_MBMS_Session_ID_t * mbms_session_id = &ie->value.choice.MBMS_Session_ID;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2. MBMS_E_RAB_QoS_Parameters */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_E_RAB_QoS_Parameters; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_E_RAB_QoS_Parameters;
+  M3AP_MBMS_E_RAB_QoS_Parameters_t * mbms_e_rab_qos_parameters = &ie->value.choice.MBMS_E_RAB_QoS_Parameters;
+  {
+	//M3AP_QCI_t * qci = &mbms_e_rab_qos_parameters->qCI; //long
+	mbms_e_rab_qos_parameters->qCI = 1;
+	//struct M3AP_GBR_QosInformation  *gbrQosInformation;     /* OPTIONAL */
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2. MBMS_Session_Duration */ 
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_Duration; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Session_Duration; 
+  M3AP_MBMS_Session_Duration_t * mbms_session_duration = &ie->value.choice.MBMS_Session_Duration;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_session_duration,(const char*)&duration[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 MBMS_Service_Area */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Service_Area;
+  ie->criticality               = M3AP_Criticality_ignore;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Service_Area;
+  M3AP_MBMS_Service_Area_t * mbms_service_area = &ie->value.choice.MBMS_Service_Area;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_service_area,(const char*)&duration[2],1);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 MinimumTimeToMBMSDataTransfer */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MinimumTimeToMBMSDataTransfer; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MinimumTimeToMBMSDataTransfer; 
+  M3AP_MinimumTimeToMBMSDataTransfer_t * minimumtimetombmsdatatransfer = &ie->value.choice.MinimumTimeToMBMSDataTransfer;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(minimumtimetombmsdatatransfer,(const char*)&duration[2],1);
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2 TNL_Information */
+  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TNL_Information; 
+  ie->criticality               = M3AP_Criticality_ignore;
+  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_TNL_Information; 
+  M3AP_TNL_Information_t * tnl_information = &ie->value.choice.TNL_Information;
+  {
+        //OCTET_STRING_fromBuf(&tnl_information->iPMCAddress,"1204",strlen("1234"));
+        //OCTET_STRING_fromBuf(&tnl_information->iPSourceAddress,"1204",strlen("1234"));
+        //OCTET_STRING_fromBuf(&tnl_information->gTP_DLTEID,"1204",strlen("1234"));
+	uint32_t gtp_dlteid = 1;
+	GTP_TEID_TO_ASN1(gtp_dlteid,&tnl_information->gTP_DLTEID);
+	//tnl_information->iPMCAddress.buf = calloc(4,sizeof(uint8_t));
+	//tnl_information->iPMCAddress.buf[0]
+	//tnl_information->iPMCAddress.buf[1]
+	//tnl_information->iPMCAddress.buf[2]
+	//tnl_information->iPMCAddress.buf[3]
+	//tnl_information->iPMCAddress.buf.size = 4;
+	uint32_t ip= (224<<24) | (0) << 16 | (0) << 8 | (2);
+	INT32_TO_OCTET_STRING(ip,&tnl_information->iPMCAddress);
+	ip= (224<<24) | (0) << 16 | (0) << 8 | (2);
+	INT32_TO_OCTET_STRING(ip,&tnl_information->iPSourceAddress);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 Time_ofMBMS_DataTransfer */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_Time_ofMBMS_DataTransfer; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_Absolute_Time_ofMBMS_Data; 
+	  //M3AP_Absolute_Time_ofMBMS_Data_t * absolute_time_ofmbms_data	= &ie->value.choice.Absolute_Time_ofMBMS_Data;
+	  //{
+		//char duration[5] = {4,3,2,1,0};
+		//OCTET_STRING_fromBuf(absolute_time_ofmbms_data,(const char*)&duration[2],3);
+	  //}
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 MBMS_Cell_List */
+  if(0){
+	  ie = (M3AP_MBMSSessionStartRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStartRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Cell_List; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionStartRequest_IEs__value_PR_MBMS_Cell_List; 
+	  M3AP_MBMS_Cell_List_t * mbms_cell_list = &ie->value.choice.MBMS_Cell_List;
+	  M3AP_ECGI_t * ecgi = (M3AP_ECGI_t*)calloc(1,sizeof(M3AP_ECGI_t));	
+	  {
+		//MCC_MNC_TO_PLMNID(0,0,3,ecgi->pLMN_Identity);
+		//MACRO_ENB_ID_TO_CELL_IDENTITY(1,0,ecgi->eUTRANcellIdentifier);
+		ASN_SEQUENCE_ADD(&mbms_cell_list->list,ecgi);
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  
+//  buffer = &m3ap_start_message[0];
+//  len=8*9+7;
+//
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id, buffer, len, 0);
+  
+  return 0;
+
+}
+
+int MME_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+//  AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MME_handle_MBMS_SESSION_START_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+               "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionStart,
+               "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionStart\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+               "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse,
+               "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionStartResponse\n");
+
+
+  M3AP_MBMSSessionStartResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionStartResponse;
+  M3AP_MBMSSessionStartResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_START_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: SessionStart-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionStartResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionStart-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionStartResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionStart-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+  ////M3AP_SESSION_START_RESP(msg_p).
+////  MSC_LOG_RX_MESSAGE(
+////    MSC_M3AP_MME,
+////    MSC_M3AP_MCE,
+  //      //return 0;
+////    0,
+////    0,
+////    MSC_AS_TIME_FMT" MME_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d",
+////    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+////    assoc_id);
+////
+  // LOG_W(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+  //       assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+  itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+  return 0;
+
+}
+int MME_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ * MBMS Session stop
+ */
+int MME_send_MBMS_SESSION_STOP_REQUEST(instance_t instance, m3ap_session_stop_req_t* m3ap_session_stop_req){
+
+    
+ // module_id_t enb_mod_idP=0;
+ // module_id_t du_mod_idP=0;
+
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionStopRequest_t        *out;
+  M3AP_MBMSSessionStopRequest_IEs_t    *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionStop;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionStopRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionStopRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionStopRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionStopRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionStopRequest_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  //MME_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+  return 0;
+
+
+                        
+}
+
+int MME_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "eNB_handle_MBMS_SESSION_STOP_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+	       "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionStop,
+	       "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionStop\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+	       "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse,
+	       "pdu->choice.successfulOutcome->value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionStopResponse\n");
+
+
+  M3AP_MBMSSessionStopResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionStopResponse;
+  M3AP_MBMSSessionStopResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_STOP_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStopResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_MBMSStopResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_MBMSStopResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+ // M3AP_SESSION_STOP_RESP(msg_p).
+ // MSC_LOG_RX_MESSAGE(
+ //   MSC_M3AP_MME,
+ //   MSC_M3AP_MCE,
+ //   0,
+ //   0,
+ //   MSC_AS_TIME_FMT" MME_handle_M2_SESSION_STOP_RESPONSE successfulOutcome assoc_id %d",
+ //   0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+ //   assoc_id);
+
+ //  LOG_D(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+ //        assoc_id,MCE_MODULE_ID_TO_INSTANCE(assoc_id));
+   itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+// //                      
+	return 0;
+}
+
+
+
+int MME_handle_MBMS_SESSION_STOP_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+                      
+}
+
+
+
+
+
+/*
+ * Reset
+ */
+
+int MME_send_RESET(instance_t instance, m3ap_reset_t * m3ap_reset) {
+  AssertFatal(1==0,"Not implemented yet\n");
+  //M3AP_Reset_t     Reset;
+                        
+}
+
+
+int MME_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                  uint32_t assoc_id,
+                                  uint32_t stream,
+                                  M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+int MME_handle_RESET(instance_t instance,
+                     uint32_t assoc_id,
+                     uint32_t stream,
+                     M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+int MME_send_RESET_ACKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+/*
+ *    M3 Setup
+ */
+int MME_handle_M3_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu)
+{
+  LOG_D(M2AP, "MCE_handle_M3_SETUP_REQUEST assoc_id %d\n",assoc_id);
+
+  //AssertFatal(1==0,"Not implemented yet\n");
+//  LOG_W(M3AP, "MME_handle_M3_SETUP_REQUEST assoc_id %d\n",assoc_id);
+//
+    MessageDef                         *message_p;
+//  M3AP_M3SetupRequest_t              *container;
+//  M3AP_M3SetupRequestIEs_t           *ie;
+//  int i = 0,j=0;
+//
+//  DevAssert(pdu != NULL);
+//
+//  container = &pdu->choice.initiatingMessage.value.choice.M3SetupRequest;
+//
+//  /* M3 Setup Request == Non UE-related procedure -> stream 0 */
+//  if (stream != 0) {
+//    LOG_W(M3AP, "[SCTP %d] Received m3 setup request on stream != 0 (%d)\n",
+//              assoc_id, stream);
+//  }
+//
+    message_p = itti_alloc_new_message(TASK_M3AP_MME, M3AP_SETUP_REQ); 
+    //printf("M3AP_SETUP_REQ(message_p).assoc_id %d\n",M3AP_SETUP_REQ(message_p).assoc_id);
+//  
+//  /* assoc_id */
+    M3AP_SETUP_REQ(message_p).assoc_id = assoc_id;
+//
+// /* GlobalMCE_id */
+// // this function exits if the ie is mandatory
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                             M3AP_ProtocolIE_ID_id_Global_MCE_ID, true);
+//  asn_INTEGER2ulong(&ie->value.choice.GlobalMCE_ID, &M3AP_SETUP_REQ(message_p).GlobalMCE_ID);
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).GlobalMCE_ID %lu \n", M3AP_SETUP_REQ(message_p).GlobalMCE_ID);
+//
+//  /* MCE_name */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                              M3AP_ProtocolIE_ID_id_MCEname, true);
+//  M3AP_SETUP_REQ(message_p).MCEname = calloc(ie->value.choice.MCEname.size + 1, sizeof(char));
+//  memcpy(M3AP_SETUP_REQ(message_p).MCEname, ie->value.choice.MCEname.buf,
+//         ie->value.choice.MCEname.size);
+//
+//  /* Convert the mme name to a printable string */
+//  M3AP_SETUP_REQ(message_p).MCEname[ie->value.choice.MCEname.size] = '\0';
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).gNB_DU_name %s \n", M3AP_SETUP_REQ(message_p).MCEname);
+//   /* MCE_MBMS_Configuration_data_List */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, container,
+//                              M3AP_ProtocolIE_ID_id_MCE_MBMS_Configuration_data_List, true);
+//  M3AP_SETUP_REQ(message_p).num_mbms_available = ie->value.choice.MCE_MBMS_Configuration_data_List.list.count;
+//  LOG_W(M3AP, "M3AP_SETUP_REQ(message_p).num_mbms_available %d \n",
+//        M3AP_SETUP_REQ(message_p).num_mbms_available);
+//  int num_mbms_available = M3AP_SETUP_REQ(message_p).num_mbms_available;
+//  for (i=0; i<num_mbms_available; i++) {
+//	 M3AP_MCE_MBMS_Configuration_data_Item_t *mbms_configuration_item_p;
+//         mbms_configuration_item_p = &(((M3AP_MCE_MBMS_Configuration_data_ItemIEs_t *)ie->value.choice.MCE_MBMS_Configuration_data_List.list.array[i])->value.choice.MCE_MBMS_Configuration_data_Item);
+//    /* eCGI */
+//       //mbms_configuration_item_p->eCGI ... (M3AP_ECGI_t)
+//
+//    OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.pLMN_Identity),M3AP_SETUP_REQ(message_p).plmn_identity[i]);
+//    //OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->eCGI.eUTRANcellIdentifier),M3AP_SETUP_REQ(message_p).eutran_cell_identifier[i]);
+//    /* mbsfnSynchronisationArea */
+//       //mbms_configuration_item_p->mbsfnSynchronisationArea ... (M3AP_MBSFN_SynchronisationArea_ID_t)
+//
+//    M3AP_SETUP_REQ(message_p).mbsfn_synchronization_area[i]=mbms_configuration_item_p->mbsfnSynchronisationArea;
+//    /* mbmsServiceAreaList */
+//       //mbms_configuration_item_p->mbmsServiceAreaList ... (M3AP_MBMS_Service_Area_ID_List_t)
+//   for(j=0;j<1;j++){
+//   	//OCTET_STRING_TO_INT16(&(mbms_configuration_item_p->mbmsServiceAreaList.list.array[j]), M3AP_SETUP_REQ(message_p).service_area_id[i][j]);
+//   }
+//
+// }
+//    
+////    /* tac */
+////    OCTET_STRING_TO_INT16(&(served_celles_item_p->served_Cell_Information.fiveGS_TAC), M3AP_SETUP_REQ(message_p).tac[i]);
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).tac[%d] %d \n",
+////          i, M3AP_SETUP_REQ(message_p).tac[i]);
+////
+////    /* - nRCGI */
+////    TBCD_TO_MCC_MNC(&(served_celles_item_p->served_Cell_Information.nRCGI.pLMN_Identity), M3AP_SETUP_REQ(message_p).mcc[i],
+////                    M3AP_SETUP_REQ(message_p).mnc[i],
+////                    M3AP_SETUP_REQ(message_p).mnc_digit_length[i]);
+////    
+////    
+////    // NR cellID
+////    BIT_STRING_TO_NR_CELL_IDENTITY(&served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity,
+////				   M3AP_SETUP_REQ(message_p).nr_cellid[i]);
+////    LOG_D(M3AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
+////          M3AP_SETUP_REQ(message_p).mcc[i],
+////          M3AP_SETUP_REQ(message_p).mnc[i],
+////          (long long unsigned int)M3AP_SETUP_REQ(message_p).nr_cellid[i]);
+////    LOG_D(M3AP, "nr_cellId : %x %x %x %x %x\n",
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[0],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[1],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[2],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[3],
+////          served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[4]);
+////    /* - nRPCI */
+////    M3AP_SETUP_REQ(message_p).nr_pci[i] = served_celles_item_p->served_Cell_Information.nRPCI;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).nr_pci[%d] %d \n",
+////          i, M3AP_SETUP_REQ(message_p).nr_pci[i]);
+////  
+////    // System Information
+////    /* mib */
+////    M3AP_SETUP_REQ(message_p).mib[i] = calloc(served_celles_item_p->gNB_DU_System_Information->mIB_message.size + 1, sizeof(char));
+////    memcpy(M3AP_SETUP_REQ(message_p).mib[i], served_celles_item_p->gNB_DU_System_Information->mIB_message.buf,
+////           served_celles_item_p->gNB_DU_System_Information->mIB_message.size);
+////    /* Convert the mme name to a printable string */
+////    M3AP_SETUP_REQ(message_p).mib[i][served_celles_item_p->gNB_DU_System_Information->mIB_message.size] = '\0';
+////    M3AP_SETUP_REQ(message_p).mib_length[i] = served_celles_item_p->gNB_DU_System_Information->mIB_message.size;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).mib[%d] %s , len = %d \n",
+////          i, M3AP_SETUP_REQ(message_p).mib[i], M3AP_SETUP_REQ(message_p).mib_length[i]);
+////
+////    /* sib1 */
+////    M3AP_SETUP_REQ(message_p).sib1[i] = calloc(served_celles_item_p->gNB_DU_System_Information->sIB1_message.size + 1, sizeof(char));
+////    memcpy(M3AP_SETUP_REQ(message_p).sib1[i], served_celles_item_p->gNB_DU_System_Information->sIB1_message.buf,
+////           served_celles_item_p->gNB_DU_System_Information->sIB1_message.size);
+////    /* Convert the mme name to a printable string */
+////    M3AP_SETUP_REQ(message_p).sib1[i][served_celles_item_p->gNB_DU_System_Information->sIB1_message.size] = '\0';
+////    M3AP_SETUP_REQ(message_p).sib1_length[i] = served_celles_item_p->gNB_DU_System_Information->sIB1_message.size;
+////    LOG_D(M3AP, "M3AP_SETUP_REQ(message_p).sib1[%d] %s , len = %d \n",
+////          i, M3AP_SETUP_REQ(message_p).sib1[i], M3AP_SETUP_REQ(message_p).sib1_length[i]);
+////  }
+//
+//
+    //printf("m3ap_mme_data_from_mce->assoc_id %d %d\n",m3ap_mme_data_from_mce->assoc_id,assoc_id);
+    *m3ap_mme_data_from_mce = M3AP_SETUP_REQ(message_p);
+    //printf("m3ap_mme_data_from_mce->assoc_id %d %d\n",m3ap_mme_data_from_mce->assoc_id,assoc_id);
+//
+////  MSC_LOG_TX_MESSAGE(
+////  MSC_M3AP_MME,
+////  MSC_RRC_MCE,
+////  0,
+////  0,
+////  MSC_AS_TIME_FMT" MME_handle_M3_SETUP_REQUEST",
+////  0,0//MSC_AS_TIME_ARGS(ctxt_pP),
+////  );
+////
+    itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p);
+//  if (num_mbms_available > 0) {
+//    itti_send_msg_to_task(TASK_MME_APP, MCE_MODULE_ID_TO_INSTANCE(instance), message_p);
+//  } else {
+//       //MME_send_M3_SETUP_FAILURE(instance);
+//       return -1;
+//  }
+////  return 0;
+//    //TEST POINT MME -> eNB
+//    if(1){
+//	printf("instance %d\n",instance);
+//	//MME_send_M3_SETUP_RESPONSE(instance,assoc_id,m3ap_mce_data_from_enb->assoc_id);
+//	//MME_send_MBMS_SESSION_START_REQUEST(instance,assoc_id);
+//	//MME_send_MBMS_SESSION_STOP_REQUEST(instance,assoc_id);
+//	//MME_send_MBMS_SCHEDULING_INFORMATION(instance,assoc_id,NULL); //TODO
+//    }
+//    else 
+//	MME_send_M3_SETUP_FAILURE(instance,assoc_id);
+//
+    return 0;
+}
+
+int MME_send_M3_SETUP_RESPONSE(instance_t instance, /*uint32_t assoc_id,*/
+                               m3ap_setup_resp_t *m3ap_setup_resp) {
+ M3AP_M3AP_PDU_t           pdu;
+ M3AP_M3SetupResponse_t    *out;
+ M3AP_M3SetupResponseIEs_t *ie;
+
+ uint8_t  *buffer;
+ uint32_t  len;
+ //int       i = 0;
+
+ /* Create */
+ /* 0. Message Type */
+ memset(&pdu, 0, sizeof(pdu));
+ pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+ //pdu.choice.successfulOutcome = (M3AP_SuccessfulOutcome_t *)calloc(1, sizeof(M3AP_SuccessfulOutcome_t));
+ pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+ pdu.choice.successfulOutcome.criticality   = M3AP_Criticality_reject;
+ pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_M3SetupResponse;
+ out = &pdu.choice.successfulOutcome.value.choice.M3SetupResponse;
+
+ /* mandatory */
+  /* c4. CriticalityDiagnostics*/
+  if (0) {
+    ie = (M3AP_M3SetupResponseIEs_t *)calloc(1, sizeof(M3AP_M3SetupResponseIEs_t));
+    ie->id                        = M3AP_ProtocolIE_ID_id_CriticalityDiagnostics;
+    ie->criticality               = M3AP_Criticality_ignore;
+    ie->value.present             = M3AP_M3SetupFailureIEs__value_PR_CriticalityDiagnostics;
+    ie->value.choice.CriticalityDiagnostics.procedureCode = (M3AP_ProcedureCode_t *)calloc(1, sizeof(M3AP_ProcedureCode_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+    ie->value.choice.CriticalityDiagnostics.triggeringMessage = (M3AP_TriggeringMessage_t *)calloc(1, sizeof(M3AP_TriggeringMessage_t));
+    *ie->value.choice.CriticalityDiagnostics.triggeringMessage = M3AP_TriggeringMessage_initiating_message;
+    ie->value.choice.CriticalityDiagnostics.procedureCriticality = (M3AP_Criticality_t *)calloc(1, sizeof(M3AP_Criticality_t));
+    *ie->value.choice.CriticalityDiagnostics.procedureCriticality = M3AP_Criticality_reject;
+    //ie->value.choice.CriticalityDiagnostics.transactionID = (M2AP_TransactionID_t *)calloc(1, sizeof(M3AP_TransactionID_t));
+    //*ie->value.choice.CriticalityDiagnostics.transactionID = 0;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+    LOG_E(M3AP, "Failed to encode M3 response\n");
+    return -1;
+  }
+
+  //printf(",m3ap_mme_data_from_mce->assoc_id %d\n",m3ap_mme_data_from_mce->assoc_id);
+
+  m3ap_MME_itti_send_sctp_data_req(instance,m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+int MME_send_M3_SETUP_FAILURE(instance_t instance,m3ap_setup_failure_t* m3ap_setup_failure) {
+  AssertFatal(1==0,"Not implemented yet\n");
+  
+//  module_id_t enb_mod_idP;
+//  module_id_t mce_mod_idP;
+//
+//  // This should be fixed
+//  enb_mod_idP = (module_id_t)0;
+//  mce_mod_idP  = (module_id_t)0;
+//
+//  M3AP_M3AP_PDU_t           pdu;
+//  M3AP_M3SetupFailure_t    *out;
+//  M3AP_M3SetupFailureIEs_t *ie;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//
+//  /* Create */
+//  /* 0. Message Type */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+//  //pdu.choice.unsuccessfulOutcome = (M3AP_UnsuccessfulOutcome_t *)calloc(1, sizeof(M3AP_UnsuccessfulOutcome_t));
+//  pdu.choice.unsuccessfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+//  pdu.choice.unsuccessfulOutcome.criticality   = M3AP_Criticality_reject;
+//  pdu.choice.unsuccessfulOutcome.value.present = M3AP_UnsuccessfulOutcome__value_PR_M2SetupFailure;
+//  out = &pdu.choice.unsuccessfulOutcome.value.choice.M2SetupFailure;
+//
+//  /* mandatory */
+//  /* c1. Transaction ID (integer value)*/
+// // ie = (M3AP_M3SetupFailure_Ies_t *)calloc(1, sizeof(M3AP_M3SetupFailure_Ies_t));
+// // ie->id                        = M3AP_ProtocolIE_ID_id_GlobalMCE_ID;
+// // ie->criticality               = M3AP_Criticality_reject;
+// // ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_GlobalMCE_ID;
+// // ie->value.choice.GlobalMCE_ID = M3AP_get_next_transaction_identifier(enb_mod_idP, mce_mod_idP);
+// // ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  /* c2. Cause */
+//  ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//  ie->id                        = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality               = M3AP_Criticality_ignore;
+//  ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_Cause;
+//  ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M3AP_CauseRadioNetwork_unspecified;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  /* c3. TimeToWait */
+//  if (0) {
+//    ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//    ie->id                        = M3AP_ProtocolIE_ID_id_TimeToWait;
+//    ie->criticality               = M3AP_Criticality_ignore;
+//    ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_TimeToWait;
+//    ie->value.choice.TimeToWait = M3AP_TimeToWait_v10s;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* optional */
+//  /* c4. CriticalityDiagnostics*/
+//  if (0) {
+//    ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+//    ie->id                        = M3AP_ProtocolIE_ID_id_CriticalityDiagnostics;
+//    ie->criticality               = M3AP_Criticality_ignore;
+//    ie->value.present             = M3AP_M3SetupFailure_Ies__value_PR_CriticalityDiagnostics;
+//    ie->value.choice.CriticalityDiagnostics.procedureCode = (M3AP_ProcedureCode_t *)calloc(1, sizeof(M3AP_ProcedureCode_t));
+//    *ie->value.choice.CriticalityDiagnostics.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+//    ie->value.choice.CriticalityDiagnostics.triggeringMessage = (M3AP_TriggeringMessage_t *)calloc(1, sizeof(M3AP_TriggeringMessage_t));
+//    *ie->value.choice.CriticalityDiagnostics.triggeringMessage = M3AP_TriggeringMessage_initiating_message;
+//    ie->value.choice.CriticalityDiagnostics.procedureCriticality = (M3AP_Criticality_t *)calloc(1, sizeof(M3AP_Criticality_t));
+//    *ie->value.choice.CriticalityDiagnostics.procedureCriticality = M3AP_Criticality_reject;
+//    //ie->value.choice.CriticalityDiagnostics.transactionID = (M3AP_TransactionID_t *)calloc(1, sizeof(M3AP_TransactionID_t));
+//    //*ie->value.choice.CriticalityDiagnostics.transactionID = 0;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* encode */
+//  if (m3ap_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    LOG_E(M3AP, "Failed to encode M2 setup request\n");
+//    return -1;
+//  }
+//
+//  //mce_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_enb->assoc_id, buffer, len, 0);
+//  m3ap_MME_itti_send_sctp_data_req(instance,m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+
+  return 0;
+}
+
+/*
+ * MME Configuration Update
+ */
+
+
+int MME_handle_MME_CONFIGURATION_UPDATE_FAILURE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+int MME_handle_MME_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+/*
+ * MCE Configuration Update
+ */
+
+
+int MME_handle_MCE_CONFIGURATION_UPDATE(instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+
+
+
+/*
+ * Error Indication
+ */
+
+int MME_handle_ERROR_INDICATION(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu) {
+  AssertFatal(1==0,"Not implemented yet\n");
+
+
+}
+
+int MME_send_ERROR_INDICATION(instance_t instance, M3AP_ErrorIndication_t *ErrorIndication) {
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+
+/*
+ * Session Update Request
+ */
+int MME_send_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, m3ap_mbms_session_update_req_t * m3ap_mbms_session_update_req){
+  M3AP_M3AP_PDU_t          pdu; 
+  M3AP_MBMSSessionUpdateRequest_t        *out;
+  M3AP_MBMSSessionUpdateRequest_IEs_t    *ie;
+
+  uint8_t *buffer;
+  uint32_t len;
+  //int	   i=0; 
+  //int 	   j=0;
+
+  /* Create */
+  /* 0. pdu Type */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  //pdu.choice.initiatingMessage = (M3AP_InitiatingMessage_t *)calloc(1, sizeof(M3AP_InitiatingMessage_t));
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_mBMSsessionUpdate;
+  pdu.choice.initiatingMessage.criticality   = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_MBMSSessionUpdateRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.MBMSSessionUpdateRequest; 
+
+  /* mandatory */
+  /* c1. MME_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MME_MBMS_M3AP_ID;
+  //ie->value.choice.MME_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  /* c2. MCE_MBMS_M3AP_ID (integer value) */ //long
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID;
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MCE_MBMS_M3AP_ID;
+  //ie->value.choice.MCE_MBMS_M3AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //?
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+   /* mandatory */
+  /* c2. TMGI */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_TMGI; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_TMGI;
+  M3AP_TMGI_t	*tmgi 		= &ie->value.choice.TMGI;
+  {
+	  MCC_MNC_TO_PLMNID(0,0,3,&tmgi->pLMNidentity);
+	  uint8_t TMGI[5] = {4,3,2,1,0};
+	  OCTET_STRING_fromBuf(&tmgi->serviceID,(const char*)&TMGI[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2. MBMS_Session_ID */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_ID;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Session_ID;
+	  //M3AP_MBMS_Session_ID_t * mbms_session_id = &ie->value.choice.MBMS_Session_ID;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2. MBMS_E_RAB_QoS_Parameters */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_E_RAB_QoS_Parameters; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_E_RAB_QoS_Parameters;
+  M3AP_MBMS_E_RAB_QoS_Parameters_t * mbms_e_rab_qos_parameters = &ie->value.choice.MBMS_E_RAB_QoS_Parameters;
+  {
+	//M3AP_QCI_t * qci = &mbms_e_rab_qos_parameters->qCI; //long
+	mbms_e_rab_qos_parameters->qCI=1;
+	//struct M3AP_GBR_QosInformation  *gbrQosInformation;     /* OPTIONAL */
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  /* c2. MBMS_Session_Duration */ 
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Session_Duration; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Session_Duration; 
+  M3AP_MBMS_Session_Duration_t * mbms_session_duration = &ie->value.choice.MBMS_Session_Duration;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(mbms_session_duration,(const char*)&duration[2],3);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 MBMS_Service_Area */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Service_Area;
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Service_Area;
+	  //M3AP_MBMS_Service_Area_t * mbms_service_area = &ie->value.choice.MBMS_Service_Area;
+
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* mandatory */
+  /* c2 MinimumTimeToMBMSDataTransfer */
+  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+  ie->id                        = M3AP_ProtocolIE_ID_id_MinimumTimeToMBMSDataTransfer; 
+  ie->criticality               = M3AP_Criticality_reject;
+  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MinimumTimeToMBMSDataTransfer; 
+  M3AP_MinimumTimeToMBMSDataTransfer_t * minimumtimetombmsdatatransfer = &ie->value.choice.MinimumTimeToMBMSDataTransfer;
+  {
+	uint8_t duration[5] = {4,3,2,1,0};
+	OCTET_STRING_fromBuf(minimumtimetombmsdatatransfer,(const char*)&duration[2],1);
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* optional */
+  /* c2 TNL_Information */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_TNL_Information; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_TNL_Information; 
+	  M3AP_TNL_Information_t * tnl_information = &ie->value.choice.TNL_Information;
+	  {
+		OCTET_STRING_fromBuf(&tnl_information->iPMCAddress,"1204",strlen("1234"));
+		OCTET_STRING_fromBuf(&tnl_information->iPSourceAddress,"1204",strlen("1234"));
+		OCTET_STRING_fromBuf(&tnl_information->gTP_DLTEID,"1204",strlen("1234"));
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 Time_ofMBMS_DataTransfer */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_Time_ofMBMS_DataTransfer; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_Absolute_Time_ofMBMS_Data; 
+	  //M3AP_Absolute_Time_ofMBMS_Data_t * absolute_time_ofmbms_data	= &ie->value.choice.Absolute_Time_ofMBMS_Data;
+	  //{
+		//char duration[5] = {4,3,2,1,0};
+		//OCTET_STRING_fromBuf(absolute_time_ofmbms_data,(const char*)&duration[2],3);
+	  //}
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+  /* optional */
+  /* c2 MBMS_Cell_List */
+  if(0){
+	  ie = (M3AP_MBMSSessionUpdateRequest_IEs_t *)calloc(1, sizeof(M3AP_MBMSSessionUpdateRequest_IEs_t));
+	  ie->id                        = M3AP_ProtocolIE_ID_id_MBMS_Cell_List; 
+	  ie->criticality               = M3AP_Criticality_ignore;
+	  ie->value.present             = M3AP_MBMSSessionUpdateRequest_IEs__value_PR_MBMS_Cell_List; 
+	  M3AP_MBMS_Cell_List_t * mbms_cell_list = &ie->value.choice.MBMS_Cell_List;
+	  M3AP_ECGI_t * ecgi = (M3AP_ECGI_t*)calloc(1,sizeof(M3AP_ECGI_t));	
+	  {
+		//MCC_MNC_TO_PLMNID(0,0,3,ecgi->pLMN_Identity);
+		//MACRO_ENB_ID_TO_CELL_IDENTITY(1,0,ecgi->eUTRANcellIdentifier);
+		ASN_SEQUENCE_ADD(&mbms_cell_list->list,ecgi);
+	  }
+	  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* encode */
+  if (m3ap_encode_pdu(&pdu,&buffer,&len) < 0){
+        return -1;
+  }
+
+  //MME_m3ap_itti_send_sctp_data_req(instance, m3ap_mce_data_from_mce->assoid,buffer,len,0); 
+  m3ap_MME_itti_send_sctp_data_req(instance, m3ap_mme_data_from_mce->assoc_id,buffer,len,0);
+  return 0;
+
+
+
+}
+
+
+
+int MME_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  //AssertFatal(1==0,"Not implemented yet\n");
+  LOG_D(M3AP, "MME_handle_MBMS_SESSION_UPDATE_RESPONSE\n");
+
+   AssertFatal(pdu->present == M3AP_M3AP_PDU_PR_successfulOutcome,
+               "pdu->present != M3AP_M3AP_PDU_PR_successfulOutcome\n");
+   AssertFatal(pdu->choice.successfulOutcome.procedureCode  == M3AP_ProcedureCode_id_mBMSsessionUpdate,
+               "pdu->choice.successfulOutcome->procedureCode != M3AP_ProcedureCode_id_sessionUpdate\n");
+   AssertFatal(pdu->choice.successfulOutcome.criticality  == M3AP_Criticality_reject,
+               "pdu->choice.successfulOutcome->criticality != M3AP_Criticality_reject\n");
+   AssertFatal(pdu->choice.successfulOutcome.value.present  == M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse,
+               "pdu->choice.successfulOutcome.value.present != M3AP_SuccessfulOutcome__value_PR_MBMSSessionUpdateResponse\n");
+
+
+  M3AP_MBMSSessionUpdateResponse_t    *in = &pdu->choice.successfulOutcome.value.choice.MBMSSessionUpdateResponse;
+  M3AP_MBMSSessionUpdateResponse_IEs_t  *ie;
+  int MME_MBMS_M3AP_ID=-1;
+  int MCE_MBMS_M3AP_ID=-1;
+
+
+  MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_UPDATE_RESP); //TODO
+
+  LOG_D(M3AP, "M3AP: SessionUpdate-Resp: protocolIEs.list.count %d\n",
+         in->protocolIEs.list.count);
+  for (int i=0;i < in->protocolIEs.list.count; i++) {
+     ie = in->protocolIEs.list.array[i];
+     switch (ie->id) {
+     case M3AP_ProtocolIE_ID_id_MME_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MME_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionUpdateResponse_IEs__value_PR_MME_MBMS_M3AP_ID\n");
+       MME_MBMS_M3AP_ID=ie->value.choice.MME_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionUpdate-Resp: MME_MBMS_M3AP_ID %d\n",
+             MME_MBMS_M3AP_ID);
+       break;
+      case M3AP_ProtocolIE_ID_id_MCE_MBMS_M3AP_ID:
+       AssertFatal(ie->criticality == M3AP_Criticality_reject,
+                   "ie->criticality != M3AP_Criticality_reject\n");
+       AssertFatal(ie->value.present == M3AP_MBMSSessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID,
+                   "ie->value.present != M3AP_sessionUpdateResponse_IEs__value_PR_MCE_MBMS_M3AP_ID\n");
+       MCE_MBMS_M3AP_ID=ie->value.choice.MCE_MBMS_M3AP_ID;
+       LOG_D(M3AP, "M3AP: SessionUpdate-Resp: MCE_MBMS_M3AP_ID %d\n",
+             MCE_MBMS_M3AP_ID);
+       break;
+     }
+  }
+
+  //AssertFatal(MME_MBMS_M3AP_ID!=-1,"MME_MBMS_M3AP_ID was not sent\n");
+  //AssertFatal(MCE_MBMS_M3AP_ID!=-1,"MCE_MBMS_M3AP_ID was not sent\n");
+  ////M3AP_SESSION_START_RESP(msg_p).
+////  MSC_LOG_RX_MESSAGE(
+////    MSC_M3AP_MME,
+////    MSC_M3AP_MCE,
+  //      //return 0;
+////    0,
+////    0,
+////    MSC_AS_TIME_FMT" MME_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d",
+////    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+////    assoc_id);
+////
+  // LOG_W(M3AP, "Sending M3AP_SESSION_START_RESP ITTI message to MCE_APP with assoc_id (%d->%d)\n",
+  //       assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id));
+  itti_send_msg_to_task(TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g);
+
+  return 0;
+
+}
+
+
+
+int MME_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+int MME_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance,
+                                                  uint32_t assoc_id,
+                                                  uint32_t stream,
+                                                  M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+}
+
+
+
+int MME_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Service Counting Results Report
+ */
+
+int MME_handle_MBMS_SESSION_COUNTING_RESULTS_REPORT(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+
+}
+
+
+/*
+ * Overload Notification
+ */
+int MME_handle_MBMS_OVERLOAD_NOTIFICATION(instance_t instance,
+                                                      uint32_t assoc_id,
+                                                      uint32_t stream,
+                                                      M3AP_M3AP_PDU_t *pdu){
+  AssertFatal(1==0,"Not implemented yet\n");
+ 
+}
+
+
+
+
diff --git a/openair3/M3AP/m3ap_MME_interface_management.h b/openair3/M3AP/m3ap_MME_interface_management.h
new file mode 100644
index 00000000000..d3765182ce4
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_interface_management.h
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_interface_management.h
+ * \brief m3ap interface management for MME
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_MME_INTERFACE_MANAGEMENT_H_
+#define M3AP_MME_INTERFACE_MANAGEMENT_H_
+/*
+ * MBMS Session start
+ */
+int MME_send_MBMS_SESSION_START_REQUEST(instance_t instance/*,
+                                uint32_t assoc_id*/,m3ap_session_start_req_t* m3ap_session_start_req);
+int MME_handle_MBMS_SESSION_START_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_MBMS_SESSION_START_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+/*
+ * MBMS Session stop
+ */
+int MME_send_MBMS_SESSION_STOP_REQUEST(instance_t instance,
+                                m3ap_session_stop_req_t* m3ap_session_stop_req);
+
+int MME_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+/*
+ * Update 
+ */
+int MME_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+
+
+/*
+ * Reset
+ */
+int MME_send_RESET(instance_t instance, m3ap_reset_t * m3ap_reset);
+
+int MME_handle_RESET_ACKKNOWLEDGE(instance_t instance,
+                                uint32_t assoc_id,
+                                uint32_t stream,
+                                M3AP_M3AP_PDU_t *pdu);
+
+int MME_handle_RESET(instance_t instance,
+                    uint32_t assoc_id,
+                    uint32_t stream,
+                    M3AP_M3AP_PDU_t *pdu);
+int MME_send_RESET_ACKNOWLEDGE(instance_t instance, M3AP_ResetAcknowledge_t *ResetAcknowledge);
+
+/*
+ * M3AP Setup
+ */
+int MME_handle_M3_SETUP_REQUEST(instance_t instance,
+                               uint32_t assoc_id,
+                               uint32_t stream,
+                               M3AP_M3AP_PDU_t *pdu);
+
+int MME_send_M3_SETUP_RESPONSE(instance_t instance,/*uint32_t assoc_id,*/  m3ap_setup_resp_t *m3ap_setup_resp);
+
+int MME_send_M3_SETUP_FAILURE(instance_t instance, /*uint32_t assoc_id*/ m3ap_setup_failure_t * m3ap_setup_failure);
+
+
+
+
+
+
+#endif /* M3AP_MME_INTERFACE_MANAGEMENT_H_ */
+
+
+
diff --git a/openair3/M3AP/m3ap_MME_management_procedures.c b/openair3/M3AP/m3ap_MME_management_procedures.c
new file mode 100644
index 00000000000..11d29242494
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_management_procedures.c
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MME_management_procedures.c
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade  <javier.morade@ieee.org>
+ * \date 2018
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "assertions.h"
+#include "conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MME_defs.h"
+#include "m3ap_MME.h"
+
+
+#define M3AP_DEBUG_LIST
+#ifdef M3AP_DEBUG_LIST
+#  define M3AP_MME_LIST_OUT(x, args...) M3AP_DEBUG("[MME]%*s"x"\n", 4*indent, "", ##args)
+#else
+#  define M3AP_MME_LIST_OUT(x, args...)
+#endif
+
+static int                  indent = 0;
+
+
+m3ap_MME_internal_data_t m3ap_MME_internal_data;
+
+RB_GENERATE(m3ap_mme_map, m3ap_MME_data_s, entry, m3ap_MME_compare_assoc_id);
+
+int m3ap_MME_compare_assoc_id(
+  struct m3ap_MME_data_s *p1, struct m3ap_MME_data_s *p2)
+{
+  if (p1->assoc_id == -1) {
+    if (p1->cnx_id < p2->cnx_id) {
+      return -1;
+    }
+
+    if (p1->cnx_id > p2->cnx_id) {
+      return 1;
+    }
+  } else {
+    if (p1->assoc_id < p2->assoc_id) {
+      return -1;
+    }
+
+    if (p1->assoc_id > p2->assoc_id) {
+      return 1;
+    }
+  }
+
+  /* Matching reference */
+  return 0;
+}
+
+uint16_t m3ap_MME_fetch_add_global_cnx_id(void)
+{
+  return ++m3ap_MME_internal_data.global_cnx_id;
+}
+
+void m3ap_MME_prepare_internal_data(void)
+{
+  memset(&m3ap_MME_internal_data, 0, sizeof(m3ap_MME_internal_data));
+  STAILQ_INIT(&m3ap_MME_internal_data.m3ap_MME_instances_head);
+}
+
+void m3ap_MME_insert_new_instance(m3ap_MME_instance_t *new_instance_p)
+{
+  DevAssert(new_instance_p != NULL);
+
+  STAILQ_INSERT_TAIL(&m3ap_MME_internal_data.m3ap_MME_instances_head,
+                     new_instance_p, m3ap_MME_entries);
+}
+
+void dump_mme_tree_m2(m3ap_MME_data_t *t)
+{
+  if (t == NULL) return;
+  printf("-----------------------\n");
+  printf("MME id %d %s\n", t->MME_id, t->MME_name);
+  printf("state %d\n", t->state);
+  printf("nextstream %d\n", t->nextstream);
+  printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
+  printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
+  dump_mme_tree_m2(t->entry.rbe_left);
+  dump_mme_tree_m2(t->entry.rbe_right);
+}
+
+void dump_mme_trees_m2(void)
+{
+m3ap_MME_instance_t *zz;
+STAILQ_FOREACH(zz, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+               m3ap_MME_entries) {
+printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
+dump_mme_tree_m2(zz->m3ap_mme_head.rbh_root);
+printf("---------------------------------------------\n");
+}
+}
+
+struct m3ap_MME_data_s *m3ap_get_MME(m3ap_MME_instance_t *instance_p,
+				     int32_t assoc_id,
+				     uint16_t cnx_id)
+{
+  struct m3ap_MME_data_s  temp;
+  struct m3ap_MME_data_s *found;
+
+printf("m3ap_get_MME at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
+dump_mme_trees_m2();
+
+  memset(&temp, 0, sizeof(struct m3ap_MME_data_s));
+
+  temp.assoc_id = assoc_id;
+  temp.cnx_id   = cnx_id;
+
+  if (instance_p == NULL) {
+    STAILQ_FOREACH(instance_p, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+                   m3ap_MME_entries) {
+      found = RB_FIND(m3ap_mme_map, &instance_p->m3ap_mme_head, &temp);
+
+      if (found != NULL) {
+        return found;
+      }
+    }
+  } else {
+    return RB_FIND(m3ap_mme_map, &instance_p->m3ap_mme_head, &temp);
+  }
+
+  return NULL;
+}
+
+
+m3ap_MME_instance_t *m3ap_MME_get_instance(instance_t instance)
+{
+  m3ap_MME_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &m3ap_MME_internal_data.m3ap_MME_instances_head,
+                 m3ap_MME_entries) {
+    if (temp->instance == instance) {
+      /* Matching occurence */
+      return temp;
+    }
+  }
+
+  return NULL;
+}
+
+/// utility functions
+
+void m3ap_dump_MME (m3ap_MME_data_t  * MME_ref);
+
+void
+m3ap_dump_MME_list (void) {
+   m3ap_MME_instance_t *inst = NULL;
+   struct m3ap_MME_data_s *found = NULL;
+   struct m3ap_MME_data_s temp;
+
+   memset(&temp, 0, sizeof(struct m3ap_MME_data_s));
+
+  STAILQ_FOREACH (inst, &m3ap_MME_internal_data.m3ap_MME_instances_head,  m3ap_MME_entries) {
+    found = RB_FIND(m3ap_mme_map, &inst->m3ap_mme_head, &temp);
+    m3ap_dump_MME (found);
+  }
+}
+
+void m3ap_dump_MME (m3ap_MME_data_t  * MME_ref) {
+
+  if (MME_ref == NULL) {
+    return;
+  }
+
+  M3AP_MME_LIST_OUT ("");
+  M3AP_MME_LIST_OUT ("MME name:          %s", MME_ref->MME_name == NULL ? "not present" : MME_ref->MME_name);
+  M3AP_MME_LIST_OUT ("MME STATE:         %07x", MME_ref->state);
+  M3AP_MME_LIST_OUT ("MME ID:            %07x", MME_ref->MME_id);
+  indent++;
+  M3AP_MME_LIST_OUT ("SCTP cnx id:     %d", MME_ref->cnx_id);
+  M3AP_MME_LIST_OUT ("SCTP assoc id:     %d", MME_ref->assoc_id);
+  M3AP_MME_LIST_OUT ("SCTP instreams:    %d", MME_ref->in_streams);
+  M3AP_MME_LIST_OUT ("SCTP outstreams:   %d", MME_ref->out_streams);
+  indent--;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_pci_in_list (const uint32_t pci)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    RB_FOREACH(elm, m3ap_mme_map, &inst->m3ap_mme_head) {
+      for (int i = 0; i<elm->num_cc; i++) {
+        if (elm->Nid_cell[i] == pci) {
+          return elm;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_id_in_list (const uint32_t MME_id)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *elm;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    RB_FOREACH(elm, m3ap_mme_map, &inst->m3ap_mme_head) {
+      if (elm->MME_id == MME_id)
+        return elm;
+    }
+  }
+  return NULL;
+}
+
+m3ap_MME_data_t  * m3ap_is_MME_assoc_id_in_list (const uint32_t sctp_assoc_id)
+{
+  m3ap_MME_instance_t    *inst;
+  struct m3ap_MME_data_s *found;
+  struct m3ap_MME_data_s temp;
+
+  temp.assoc_id = sctp_assoc_id;
+  temp.cnx_id = -1;
+
+  STAILQ_FOREACH(inst, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) {
+    found = RB_FIND(m3ap_mme_map, &inst->m3ap_mme_head, &temp);
+    if (found != NULL){
+      if (found->assoc_id == sctp_assoc_id) {
+	return found;
+      }
+    }
+  }
+  return NULL;
+}
diff --git a/openair3/M3AP/m3ap_MME_management_procedures.h b/openair3/M3AP/m3ap_MME_management_procedures.h
new file mode 100644
index 00000000000..e966ee1f17e
--- /dev/null
+++ b/openair3/M3AP/m3ap_MME_management_procedures.h
@@ -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
+ */
+
+/*! \file m3ap_eNB_management_procedures.h
+ * \brief m3ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MME_MANAGEMENT_PROCEDURES_H_
+#define M3AP_MME_MANAGEMENT_PROCEDURES_H
+
+void m3ap_MME_prepare_internal_data(void);
+
+void dump_trees_m2(void);
+
+void m3ap_MME_insert_new_instance(m3ap_MME_instance_t *new_instance_p);
+
+m3ap_MME_instance_t *m3ap_MME_get_instance(uint8_t mod_id);
+
+uint16_t m3ap_MME_fetch_add_global_cnx_id(void);
+
+void m3ap_MME_prepare_internal_data(void);
+
+m3ap_MME_data_t* m3ap_is_MME_id_in_list(uint32_t MME_id);
+
+m3ap_MME_data_t* m3ap_is_MME_assoc_id_in_list(uint32_t sctp_assoc_id);
+
+m3ap_MME_data_t* m3ap_is_MME_pci_in_list (const uint32_t pci);
+
+struct m3ap_MME_data_s *m3ap_get_MME(m3ap_MME_instance_t *instance_p,
+                                     int32_t assoc_id,
+                                     uint16_t cnx_id);
+
+#endif /* M3AP_MME_MANAGEMENT_PROCEDURES_H_ */
diff --git a/openair3/M3AP/m3ap_common.c b/openair3/M3AP/m3ap_common.c
index d61ead35802..55019976389 100644
--- a/openair3/M3AP/m3ap_common.c
+++ b/openair3/M3AP/m3ap_common.c
@@ -20,7 +20,7 @@
  */
 
 /*! \file m3ap_common.c
- * \brief m3ap procedures for both MCE and MME
+ * \brief m3ap procedures for both eNB and MCE
  * \author Javier Morgade  <javier.morgade@ieee.org>
  * \date 2019
  * \version 0.1
diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h
index 83969bf9ef9..7f68510314f 100644
--- a/openair3/M3AP/m3ap_common.h
+++ b/openair3/M3AP/m3ap_common.h
@@ -38,14 +38,6 @@
 #ifndef M3AP_COMMON_H_
 #define M3AP_COMMON_H_
 
-/*! \file m3ap_common.h
- * \brief m3ap procedures for both MCE and MME
- * \author Javier Morgade  <javier.morgade@ieee.org>
- * \date 2019
- * \version 0.1
- */
-
-
 /** @defgroup _m3ap_impl_ M3AP Layer Reference Implementation
  * @ingroup _ref_implementation_
  * @{
diff --git a/openair3/M3AP/m3ap_decoder.c b/openair3/M3AP/m3ap_decoder.c
new file mode 100644
index 00000000000..cee0a5ff41d
--- /dev/null
+++ b/openair3/M3AP/m3ap_decoder.c
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_decoder.c
+ * \brief m3ap decoder procedures 
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+
+#include "assertions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_decoder.h"
+
+static int m3ap_decode_initiating_message(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.initiatingMessage.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    default:
+      M3AP_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 m3ap_decode_successful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.successfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_successfuloutcome_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_succesfuloutcome_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_succesfuloutcome_message!\n");
+      break;
+    default:
+      M3AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
+                  (int)pdu->choice.successfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int m3ap_decode_unsuccessful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_mBMSsessionStart:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionStop:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_errorIndication:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_privateMessage:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_Reset:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mBMSsessionUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_mCEConfigurationUpdate:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap__decode_initiating_message!\n");
+      break;
+    default:
+       M3AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
+                  (int)pdu->choice.unsuccessfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+int m3ap_decode_pdu(M3AP_M3AP_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_M3AP_M3AP_PDU,
+                        (void **)&pdu,
+                        buffer,
+                        length,
+                        0,
+                        0);
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, pdu);
+  }
+
+  if (dec_ret.code != RC_OK) {
+    M3AP_ERROR("Failed to decode pdu\n");
+    return -1;
+  }
+
+  switch(pdu->present) {
+    case M3AP_M3AP_PDU_PR_initiatingMessage:
+      return m3ap_decode_initiating_message(pdu);
+
+    case M3AP_M3AP_PDU_PR_successfulOutcome:
+      return m3ap_decode_successful_outcome(pdu);
+
+    case M3AP_M3AP_PDU_PR_unsuccessfulOutcome:
+      return m3ap_decode_unsuccessful_outcome(pdu);
+
+    default:
+      M3AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
+      break;
+  }
+
+
+  return -1;
+}
diff --git a/openair3/M3AP/m3ap_decoder.h b/openair3/M3AP/m3ap_decoder.h
new file mode 100644
index 00000000000..6d228a1ceb1
--- /dev/null
+++ b/openair3/M3AP/m3ap_decoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_decoder.h
+ * \brief m3ap decoder procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_DECODER_H_
+#define M3AP_DECODER_H_
+
+int m3ap_decode_pdu(M3AP_M3AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_DECODER_H_ */
diff --git a/openair3/M3AP/m3ap_default_values.h b/openair3/M3AP/m3ap_default_values.h
new file mode 100644
index 00000000000..79c78d5b96f
--- /dev/null
+++ b/openair3/M3AP/m3ap_default_values.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_default_values.h
+ * \brief default values for m3ap procedures
+ * \author Javier Morgade
+ * \date 2019
+ * \version 0.1
+ * \company Vicomtech
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#ifndef M3AP_DEFAULT_VALUES_H_
+#define M3AP_DEFAULT_VALUES_H_
+
+#define ENB_TAC (1)
+#define ENB_MCC (208)
+#define ENB_MNC (92)
+
+#define ENB_NAME        "Eurecom ENB"
+#define ENB_NAME_FORMAT (ENB_NAME" %u")
+
+#define M3AP_PORT_NUMBER        (36444)
+#define M3AP_SCTP_PPID          (44)
+
+#endif /* M3AP_DEFAULT_VALUES_H_ */
+
diff --git a/openair3/M3AP/m3ap_eNB_decoder.c b/openair3/M3AP/m3ap_eNB_decoder.c
new file mode 100644
index 00000000000..ee0aaca3886
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_decoder.c
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_decoder.c
+ * \brief m3ap decoder procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+
+#include "assertions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_eNB_decoder.h"
+
+static int m3ap_eNB_decode_initiating_message(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.initiatingMessage.procedureCode) {
+
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap_eNB_decode_initiating_message!\n");
+      break;
+
+//    case M3AP_ProcedureCode_id_handoverPreparation:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+//      M3AP_INFO("m3ap_eNB_decode_initiating_message!\n");
+//      break;
+//
+//    case M3AP_ProcedureCode_id_uEContextRelease:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+//      M3AP_INFO("m3ap_eNB_decode_initiating_message!\n");
+//      break;
+//
+//    case M3AP_ProcedureCode_id_handoverCancel:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+//      M3AP_INFO("m3ap_eNB_decode_initiating_message!\n");
+//      break;
+//
+    default:
+      M3AP_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 m3ap_eNB_decode_successful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.successfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap_eNB_decode_successfuloutcome_message!\n");
+      break;
+
+//    case M3AP_ProcedureCode_id_handoverPreparation:
+//      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+//      M3AP_INFO("m3ap_eNB_decode_successfuloutcome_message!\n");
+//      break;
+//
+    default:
+      M3AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
+                  (int)pdu->choice.successfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int m3ap_eNB_decode_unsuccessful_outcome(M3AP_M3AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
+    case M3AP_ProcedureCode_id_m3Setup:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_M3AP_M3AP_PDU, pdu);
+      M3AP_INFO("m3ap_eNB_decode_unsuccessfuloutcome_message!\n");
+      break;
+
+    default:
+       M3AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
+                  (int)pdu->choice.unsuccessfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+int m3ap_eNB_decode_pdu(M3AP_M3AP_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_M3AP_M3AP_PDU,
+                        (void **)&pdu,
+                        buffer,
+                        length,
+                        0,
+                        0);
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_M3AP_M3AP_PDU, pdu);
+  }
+
+  if (dec_ret.code != RC_OK) {
+    M3AP_ERROR("Failed to decode pdu\n");
+    return -1;
+  }
+
+  switch(pdu->present) {
+    case M3AP_M3AP_PDU_PR_initiatingMessage:
+      return m3ap_eNB_decode_initiating_message(pdu);
+
+    case M3AP_M3AP_PDU_PR_successfulOutcome:
+      return m3ap_eNB_decode_successful_outcome(pdu);
+
+    case M3AP_M3AP_PDU_PR_unsuccessfulOutcome:
+      return m3ap_eNB_decode_unsuccessful_outcome(pdu);
+
+    default:
+      M3AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
+      break;
+  }
+
+
+  return -1;
+}
diff --git a/openair3/M3AP/m3ap_eNB_decoder.h b/openair3/M3AP/m3ap_eNB_decoder.h
new file mode 100644
index 00000000000..eddf10781e1
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_decoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_decoder.h
+ * \brief m3ap 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 M3AP_ENB_DECODER_H_
+#define M3AP_ENB_DECODER_H_
+
+int m3ap_eNB_decode_pdu(M3AP_M3AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_ENB_DECODER_H_ */
diff --git a/openair3/M3AP/m3ap_eNB_encoder.c b/openair3/M3AP/m3ap_eNB_encoder.c
new file mode 100644
index 00000000000..0f0d3c3188c
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_encoder.c
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_encoder.c
+ * \brief m3ap encoder procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "assertions.h"
+#include "conversions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_eNB_encoder.h"
+
+int m3ap_eNB_encode_pdu(M3AP_M3AP_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_M3AP_M3AP_PDU, (void *)pdu);
+  }
+
+  encoded = aper_encode_to_new_buffer(&asn_DEF_M3AP_M3AP_PDU, 0, pdu, (void **)buffer);
+
+  if (encoded < 0) {
+    return -1;
+  }
+
+  *len = encoded;
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, pdu);
+  return encoded;
+}
diff --git a/openair3/M3AP/m3ap_eNB_encoder.h b/openair3/M3AP/m3ap_eNB_encoder.h
new file mode 100644
index 00000000000..1e22b593913
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_encoder.h
+ * \brief m3ap encoder procedures for eNB
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENB_ENCODER_H_
+#define M3AP_ENB_ENCODER_H_
+
+int m3ap_eNB_encode_pdu(M3AP_M3AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_ENB_ENCODER_H_ */
diff --git a/openair3/M3AP/m3ap_eNB_generate_messages.c b/openair3/M3AP/m3ap_eNB_generate_messages.c
new file mode 100644
index 00000000000..157146ee0fa
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_generate_messages.c
@@ -0,0 +1,804 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_generate_messages.c
+ * \brief m3ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+//#include "M3AP_LastVisitedCell-Item.h"
+
+#include "m3ap_common.h"
+#include "m3ap_eNB.h"
+#include "m3ap_eNB_generate_messages.h"
+#include "m3ap_eNB_encoder.h"
+#include "m3ap_eNB_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_eNB_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int m3ap_eNB_generate_m3_setup_request(
+  m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p)
+{
+  M3AP_M3AP_PDU_t                     pdu;
+  M3AP_M3SetupRequest_t              *out;
+  M3AP_M3SetupRequestIEs_t          *ie;
+  //M3AP_PLMN_Identity_t               *plmn;
+  //ServedCells__Member                *servedCellMember;
+  //M3AP_GU_Group_ID_t                 *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m3ap_eNB_data_p != NULL);
+
+  m3ap_eNB_data_p->state = M3AP_ENB_STATE_WAITING;
+
+  /* Prepare the M3AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+  pdu.choice.initiatingMessage.criticality = M3AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_M3SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.M3SetupRequest;
+
+  /* mandatory */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_GlobalENB_ID;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M2SetupRequest_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 = M3AP_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);
+  //M3AP_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 = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M2SetupRequest_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 = (M3AP_PLMN_Identity_t *)calloc(1,sizeof(M3AP_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 = M3AP_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 = M3AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M2Setuprequest not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M3AP_M3SetupRequestIEs_t *)calloc(1, sizeof(M3AP_M3SetupRequestIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M2SetupRequest_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M3AP_GU_Group_ID_t *)calloc(1, sizeof(M3AP_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 (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M3AP_ERROR("Failed to encode M3 setup request\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 M3Setup/initiatingMessage assoc_id %u", m3ap_eNB_data_p->assoc_id);
+
+  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m3ap_eNB_generate_m3_setup_response(m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p)
+{
+  M3AP_M3AP_PDU_t                     pdu;
+  M3AP_M3SetupResponse_t              *out;
+  M3AP_M3SetupResponseIEs_t          *ie;
+  //M3AP_PLMN_Identity_t                *plmn;
+  //ServedCells__Member                 *servedCellMember;
+  //M3AP_GU_Group_ID_t                  *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(m3ap_eNB_data_p != NULL);
+
+  /* Prepare the M3AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+  pdu.choice.successfulOutcome.criticality = M3AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_M3SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.M3SetupResponse;
+
+  /* mandatory */
+  ie = (M3AP_M3SetupResponseIEs_t *)calloc(1, sizeof(M3AP_M3SetupResponseIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_GlobalENB_ID;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M3SetupResponse_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 = M3AP_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);
+  //M3AP_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 = (M3AP_M3SetupResponseIEs_t *)calloc(1, sizeof(M3AP_M3SetupResponseIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_ServedCells;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M3SetupResponse_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 = (M3AP_PLMN_Identity_t *)calloc(1,sizeof(M3AP_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 = M3AP_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 = M3AP_Transmission_Bandwidth_bw6;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw6;
+  //            break;
+  //          case 15:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw15;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw15;
+  //            break;
+  //          case 25:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw25;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw25;
+  //            break;
+  //          case 50:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw50;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw50;
+  //            break;
+  //          case 75:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw75;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw75;
+  //            break;
+  //          case 100:
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw100;
+  //            servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = M3AP_Transmission_Bandwidth_bw100;
+  //            break;
+  //          default:
+  //            AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+  //            break;
+  //        }
+  //      }
+  //      else {
+  //        AssertFatal(0,"M3Setupresponse not supported for TDD!");
+  //      }
+  //    }
+  //    ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+  //  }
+  //}
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (M3AP_M3SetupResponseIEs_t *)calloc(1, sizeof(M3AP_M3SetupResponseIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_GUGroupIDList;
+  //ie->criticality = M3AP_Criticality_reject;
+  //ie->value.present = M3AP_M3SetupResponse_IEs__value_PR_GUGroupIDList;
+  //{
+  //  gu = (M3AP_GU_Group_ID_t *)calloc(1, sizeof(M3AP_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 (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M3AP_ERROR("Failed to encode M3 setup response\n");
+    return -1;
+  }
+
+  m3ap_eNB_data_p->state = M3AP_ENB_STATE_READY;
+
+  //MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 M3Setup/successfulOutcome assoc_id %u", m3ap_eNB_data_p->assoc_id);
+
+  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m3ap_eNB_generate_m3_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M3AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait)
+{
+  M3AP_M3AP_PDU_t                     pdu;
+  M3AP_M3SetupFailure_t              *out;
+  M3AP_M3SetupFailureIEs_t          *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  /* Prepare the M3AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = M3AP_M3AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.unsuccessfulOutcome.procedureCode = M3AP_ProcedureCode_id_m3Setup;
+  pdu.choice.unsuccessfulOutcome.criticality = M3AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = M3AP_UnsuccessfulOutcome__value_PR_M3SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.M3SetupFailure;
+
+  /* mandatory */
+  ie = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_Cause;
+  //ie->criticality = M3AP_Criticality_ignore;
+  //ie->value.present = M3AP_M3SetupFailure_IEs__value_PR_Cause;
+
+  //m3ap_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 = (M3AP_M3SetupFailureIEs_t *)calloc(1, sizeof(M3AP_M3SetupFailureIEs_t));
+  //ie->id = M3AP_ProtocolIE_ID_id_TimeToWait;
+  //ie->criticality = M3AP_Criticality_ignore;
+  //ie->value.present = M3AP_M3SetupFailure_IEs__value_PR_TimeToWait;
+
+  //if (time_to_wait > -1) {
+  //  ie->value.choice.TimeToWait = time_to_wait;
+  //}
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    M3AP_ERROR("Failed to encode M3 setup failure\n");
+    return -1;
+  }
+
+  //MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB,
+  //                    MSC_M3AP_TARGET_ENB, NULL, 0,
+  //                    "0 M3Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+  //                    assoc_id, cause_type, cause_value);
+
+  m3ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int m3ap_eNB_set_cause (M3AP_Cause_t * cause_p,
+                        M3AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case M3AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M3AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M3AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case M3AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+//int m3ap_eNB_generate_m2_handover_request (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                           m3ap_handover_req_t *m3ap_handover_req, int ue_id)
+//{
+//
+//  M3AP_M3AP_PDU_t                     pdu;
+//  M3AP_HandoverRequest_t              *out;
+//  M3AP_HandoverRequest_IEs_t          *ie;
+//  M3AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+//  M3AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+//  M3AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m3ap_eNB_data_p != NULL);
+//
+//  /* Prepare the M3AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.initiatingMessage.criticality = M3AP_Criticality_reject;
+//  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_HandoverRequest;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_HandoverRequest_IEs__value_PR_UE_M3AP_ID;
+//  ie->value.choice.UE_M3AP_ID = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequest_IEs__value_PR_Cause;
+//  ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//  ie->value.choice.Cause.choice.radioNetwork = M3AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_TargetCell_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_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(m3ap_eNB_data_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_GUMMEI_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_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(m3ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+//  MME_CODE_TO_OCTET_STRING(m3ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_UE_ContextInformation;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+//  //@TODO: consider to update this value
+//  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = m3ap_handover_req->mme_ue_s1ap_id;
+//
+//  KENB_STAR_TO_BIT_STRING(m3ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+//
+//  if (m3ap_handover_req->kenb_ncc >=0) { // Check this condition
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = m3ap_handover_req->kenb_ncc;
+//  }
+//  else {
+//    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+//  }
+//
+//  ENCRALG_TO_BIT_STRING(m3ap_handover_req->security_capabilities.encryption_algorithms,
+//              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//
+//  INTPROTALG_TO_BIT_STRING(m3ap_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<m3ap_handover_req->nb_e_rabs_tobesetup;i++) {
+//      e_RABS_ToBeSetup_ItemIEs = (M3AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(M3AP_E_RABs_ToBeSetup_ItemIEs_t));
+//      e_RABS_ToBeSetup_ItemIEs->id = M3AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+//      e_RABS_ToBeSetup_ItemIEs->criticality = M3AP_Criticality_ignore;
+//      e_RABS_ToBeSetup_ItemIEs->value.present = M3AP_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 = m3ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = m3ap_handover_req->e_rab_param[i].qos.qci;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = m3ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+//        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = m3ap_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 = m3ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(m3ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
+//        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = m3ap_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,
+//                        m3ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
+//                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+//
+//        INT32_TO_OCTET_STRING(m3ap_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*) m3ap_handover_req->rrc_buffer, m3ap_handover_req->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequest_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequest_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_UE_HistoryInformation;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+//  //@TODO: consider to update this value
+//  {
+//   lastVisitedCell_Item = (M3AP_LastVisitedCell_Item_t *)calloc(1, sizeof(M3AP_LastVisitedCell_Item_t));
+//   lastVisitedCell_Item->present = M3AP_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 = M3AP_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 (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M3AP_ERROR("Failed to encode X2 handover request\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", m3ap_eNB_data_p->assoc_id);
+//
+//  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m3ap_eNB_generate_m2_handover_request_ack (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                               m3ap_handover_req_ack_t *m3ap_handover_req_ack)
+//{
+//
+//  M3AP_M3AP_PDU_t                        pdu;
+//  M3AP_HandoverRequestAcknowledge_t      *out;
+//  M3AP_HandoverRequestAcknowledge_IEs_t  *ie;
+//  M3AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+//  M3AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+//  int                                    ue_id;
+//  int                                    id_source;
+//  int                                    id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m3ap_eNB_data_p != NULL);
+//
+//  ue_id     = m3ap_handover_req_ack->m2_id_target;
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M3AP handover message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_successfulOutcome;
+//  pdu.choice.successfulOutcome.procedureCode = M3AP_ProcedureCode_id_handoverPreparation;
+//  pdu.choice.successfulOutcome.criticality = M3AP_Criticality_reject;
+//  pdu.choice.successfulOutcome.value.present = M3AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+//  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M3AP_ID;
+//  ie->value.choice.UE_M3AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequestAcknowledge_IEs__value_PR_UE_M3AP_ID_1;
+//  ie->value.choice.UE_M3AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+//
+//  {
+//      for (int i=0;i<m3ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+//        e_RABS_Admitted_ItemIEs = (M3AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(M3AP_E_RABs_Admitted_ItemIEs_t));
+//        e_RABS_Admitted_ItemIEs->id = M3AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+//        e_RABS_Admitted_ItemIEs->criticality = M3AP_Criticality_ignore;
+//        e_RABS_Admitted_ItemIEs->value.present = M3AP_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 = m3ap_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 = (M3AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(M3AP_HandoverRequestAcknowledge_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
+//
+//  OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) m3ap_handover_req_ack->rrc_buffer, m3ap_handover_req_ack->rrc_buffer_size);
+//
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M3AP_ERROR("Failed to encode X2 handover response\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", m3ap_eNB_data_p->assoc_id);
+//
+//  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m3ap_eNB_generate_m2_ue_context_release (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p, m3ap_ue_context_release_t *m3ap_ue_context_release)
+//{
+//
+//  M3AP_M3AP_PDU_t                pdu;
+//  M3AP_UEContextRelease_t        *out;
+//  M3AP_UEContextRelease_IEs_t    *ie;
+//  int                            ue_id;
+//  int                            id_source;
+//  int                            id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m3ap_eNB_data_p != NULL);
+//
+//  ue_id = m3ap_find_id_from_rnti(&instance_p->id_manager, m3ap_ue_context_release->rnti);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not find UE %x\n", m3ap_ue_context_release->rnti);
+//    exit(1);
+//  }
+//  id_source = m3ap_id_get_id_source(&instance_p->id_manager, ue_id);
+//  id_target = ue_id;
+//
+//  /* Prepare the M3AP ue context relase message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_uEContextRelease;
+//  pdu.choice.initiatingMessage.criticality = M3AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_UEContextRelease;
+//  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  /* mandatory */
+//  ie = (M3AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M3AP_UEContextRelease_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_UEContextRelease_IEs__value_PR_UE_M3AP_ID;
+//  ie->value.choice.UE_M3AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* mandatory */
+//  ie = (M3AP_UEContextRelease_IEs_t *)calloc(1, sizeof(M3AP_UEContextRelease_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_UEContextRelease_IEs__value_PR_UE_M3AP_ID_1;
+//  ie->value.choice.UE_M3AP_ID_1 = id_target;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M3AP_ERROR("Failed to encode X2 UE Context Release\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", m3ap_eNB_data_p->assoc_id);
+//
+//  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
+//
+//int m3ap_eNB_generate_m2_handover_cancel (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m3ap_handover_cancel_cause_t cause)
+//{
+//  M3AP_M3AP_PDU_t              pdu;
+//  M3AP_HandoverCancel_t        *out;
+//  M3AP_HandoverCancel_IEs_t    *ie;
+//  int                          ue_id;
+//  int                          id_source;
+//  int                          id_target;
+//
+//  uint8_t  *buffer;
+//  uint32_t  len;
+//  int       ret = 0;
+//
+//  DevAssert(instance_p != NULL);
+//  DevAssert(m3ap_eNB_data_p != NULL);
+//
+//  ue_id = m2_ue_id;
+//  id_source = ue_id;
+//  id_target = m3ap_id_get_id_target(&instance_p->id_manager, ue_id);
+//
+//  /* Prepare the M3AP handover cancel message to encode */
+//  memset(&pdu, 0, sizeof(pdu));
+//  pdu.present = M3AP_M3AP_PDU_PR_initiatingMessage;
+//  pdu.choice.initiatingMessage.procedureCode = M3AP_ProcedureCode_id_handoverCancel;
+//  pdu.choice.initiatingMessage.criticality = M3AP_Criticality_ignore;
+//  pdu.choice.initiatingMessage.value.present = M3AP_InitiatingMessage__value_PR_HandoverCancel;
+//  out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M3AP_HandoverCancel_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID;
+//  ie->criticality = M3AP_Criticality_reject;
+//  ie->value.present = M3AP_HandoverCancel_IEs__value_PR_UE_M3AP_ID;
+//  ie->value.choice.UE_M3AP_ID = id_source;
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  /* optional */
+//  if (id_target != -1) {
+//    ie = (M3AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M3AP_HandoverCancel_IEs_t));
+//    ie->id = M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID;
+//    ie->criticality = M3AP_Criticality_ignore;
+//    ie->value.present = M3AP_HandoverCancel_IEs__value_PR_UE_M3AP_ID_1;
+//    ie->value.choice.UE_M3AP_ID_1 = id_target;
+//    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//  }
+//
+//  /* mandatory */
+//  ie = (M3AP_HandoverCancel_IEs_t *)calloc(1, sizeof(M3AP_HandoverCancel_IEs_t));
+//  ie->id = M3AP_ProtocolIE_ID_id_Cause;
+//  ie->criticality = M3AP_Criticality_ignore;
+//  ie->value.present = M3AP_HandoverCancel_IEs__value_PR_Cause;
+//  switch (cause) {
+//  case M3AP_T_RELOC_PREP_TIMEOUT:
+//    ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M3AP_CauseRadioNetwork_trelocprep_expiry;
+//    break;
+//  case M3AP_TX2_RELOC_OVERALL_TIMEOUT:
+//    ie->value.choice.Cause.present = M3AP_Cause_PR_radioNetwork;
+//    ie->value.choice.Cause.choice.radioNetwork =
+//      M3AP_CauseRadioNetwork_tx2relocoverall_expiry;
+//    break;
+//  default:
+//    /* we can't come here */
+//    M3AP_ERROR("unhandled cancel cause\n");
+//    exit(1);
+//  }
+//  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+//
+//  if (m3ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+//    M3AP_ERROR("Failed to encode X2 Handover Cancel\n");
+//    abort();
+//    return -1;
+//  }
+//
+//  MSC_LOG_TX_MESSAGE (MSC_M3AP_SRC_ENB, MSC_M3AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", m3ap_eNB_data_p->assoc_id);
+//
+//  m3ap_eNB_itti_send_sctp_data_req(instance_p->instance, m3ap_eNB_data_p->assoc_id, buffer, len, 1);
+//
+//  return ret;
+//}
diff --git a/openair3/M3AP/m3ap_eNB_generate_messages.h b/openair3/M3AP/m3ap_eNB_generate_messages.h
new file mode 100644
index 00000000000..ab6c7ca6151
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_generate_messages.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_generate_messages.h
+ * \brief m3ap procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENB_GENERATE_MESSAGES_H_
+#define M3AP_ENB_GENERATE_MESSAGES_H_
+
+#include "m3ap_eNB_defs.h"
+#include "m3ap_common.h"
+
+int m3ap_eNB_generate_m3_setup_request(m3ap_eNB_instance_t *instance_p,
+				       m3ap_eNB_data_t *m3ap_eNB_data_p);
+
+int m3ap_eNB_generate_m3_setup_response(m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p);
+
+int m3ap_eNB_generate_m3_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       M3AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);
+
+int m3ap_eNB_set_cause (M3AP_Cause_t * cause_p,
+                        M3AP_Cause_PR cause_type,
+                        long cause_value);
+
+//int m3ap_eNB_generate_m2_handover_request (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                           m3ap_handover_req_t *m3ap_handover_req, int ue_id);
+//
+//int m3ap_eNB_generate_m2_handover_request_ack (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                               m3ap_handover_req_ack_t *m3ap_handover_req_ack);
+//
+//int m3ap_eNB_generate_m2_ue_context_release (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                             m3ap_ue_context_release_t *m3ap_ue_context_release);
+//
+//int m3ap_eNB_generate_m2_handover_cancel (m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *m3ap_eNB_data_p,
+//                                          int m2_ue_id,
+//                                          m3ap_handover_cancel_cause_t cause);
+
+#endif /*  M3AP_ENB_GENERATE_MESSAGES_H_ */
diff --git a/openair3/M3AP/m3ap_eNB_handler.c b/openair3/M3AP/m3ap_eNB_handler.c
new file mode 100644
index 00000000000..4fda97142d6
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_handler.c
@@ -0,0 +1,985 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_eNB_defs.h"
+#include "m3ap_eNB_handler.h"
+#include "m3ap_eNB_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_eNB_management_procedures.h"
+#include "m3ap_eNB_generate_messages.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+static
+int m3ap_eNB_handle_m3_setup_request (instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      M3AP_M3AP_PDU_t *pdu);
+static
+int m3ap_eNB_handle_m3_setup_response (instance_t instance,
+                                       uint32_t assoc_id,
+                                       uint32_t stream,
+                                       M3AP_M3AP_PDU_t *pdu);
+static
+int m3ap_eNB_handle_m3_setup_failure (instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      M3AP_M3AP_PDU_t *pdu);
+//
+//static
+//int m3ap_eNB_handle_handover_preparation (instance_t instance,
+//                                          uint32_t assoc_id,
+//                                          uint32_t stream,
+//                                          M3AP_M3AP_PDU_t *pdu);
+//static
+//int m3ap_eNB_handle_handover_response (instance_t instance,
+//                                      uint32_t assoc_id,
+//                                      uint32_t stream,
+//                                      M3AP_M3AP_PDU_t *pdu);
+//
+//static
+//int m3ap_eNB_handle_ue_context_release (instance_t instance,
+//                                        uint32_t assoc_id,
+//                                        uint32_t stream,
+//                                        M3AP_M3AP_PDU_t *pdu);
+//
+//static
+//int m3ap_eNB_handle_handover_cancel (instance_t instance,
+//                                     uint32_t assoc_id,
+//                                     uint32_t stream,
+//                                     M3AP_M3AP_PDU_t *pdu);
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_message_decoded_callback m3ap_messages_callback[][3] = {
+  { 0, 0, 0 }, /* MBMSSessionStart  */
+  { 0, 0, 0 }, /* MBMSSessionStop   */
+  { 0, 0, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MBMSSchedulingInformation */
+  { 0, 0, 0 }, /* reset */
+  { m3ap_eNB_handle_m3_setup_request, m3ap_eNB_handle_m3_setup_response, m3ap_eNB_handle_m3_setup_failure }, /* M3 Setup */
+  { 0, 0, 0 }, /* eNBConfigurationUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { 0, 0, 0 }, /* MBMSServiceCounting */
+};
+
+char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+void m3ap_handle_m3_setup_message(m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *enb_desc_p, int sctp_shutdown)
+{
+  if (sctp_shutdown) {
+    /* A previously connected eNB has been shutdown */
+
+    /* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated eNB */
+    if (enb_desc_p->state == M3AP_ENB_STATE_CONNECTED) {
+      enb_desc_p->state = M3AP_ENB_STATE_DISCONNECTED;
+
+      if (instance_p-> m3_target_enb_associated_nb > 0) {
+        /* Decrease associated eNB number */
+        instance_p-> m3_target_enb_associated_nb --;
+      }
+
+      /* If there are no more associated eNB, inform eNB app */
+      if (instance_p->m3_target_enb_associated_nb == 0) {
+        MessageDef                 *message_p;
+
+        message_p = itti_alloc_new_message(TASK_M3AP, M3AP_DEREGISTERED_MCE_IND);
+        M3AP_DEREGISTERED_MCE_IND(message_p).nb_mme = 0;
+        itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p);
+      }
+    }
+  } else {
+    /* Check that at least one setup message is pending */
+    DevCheck(instance_p->m3_target_enb_pending_nb > 0,
+             instance_p->instance,
+             instance_p->m3_target_enb_pending_nb, 0);
+
+    if (instance_p->m3_target_enb_pending_nb > 0) {
+      /* Decrease pending messages number */
+      instance_p->m3_target_enb_pending_nb --;
+    }
+
+    /* If there are no more pending messages, inform eNB app */
+    if (instance_p->m3_target_enb_pending_nb == 0) {
+      MessageDef                 *message_p;
+
+      message_p = itti_alloc_new_message(TASK_M3AP, M3AP_REGISTER_MCE_CNF);
+      M3AP_REGISTER_MCE_CNF(message_p).nb_mme = instance_p->m3_target_enb_associated_nb;
+      itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p);
+    }
+  }
+}
+
+
+int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                                const uint8_t *const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret = 0;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  //printf("Data length received: %d\n", data_length);
+
+  if (m3ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
+    M3AP_ERROR("Failed to decode PDU\n");
+    return -1;
+  }
+
+  switch (pdu.present) {
+
+  case M3AP_M3AP_PDU_PR_initiatingMessage:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_messages_callback) / (3 * sizeof(
+          m3ap_message_decoded_callback))) {
+        //|| (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+      M3AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.initiatingMessage.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+      M3AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.initiatingMessage.procedureCode,
+                 m3ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+    break;
+
+  case M3AP_M3AP_PDU_PR_successfulOutcome:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.successfulOutcome.procedureCode > sizeof(m3ap_messages_callback) / (3 * sizeof(
+          m3ap_message_decoded_callback))) {
+        //|| (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+      M3AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.successfulOutcome.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (m3ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1] == NULL) {
+      M3AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.successfulOutcome.procedureCode,
+                 m3ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*m3ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+    break;
+
+  case M3AP_M3AP_PDU_PR_unsuccessfulOutcome:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.unsuccessfulOutcome.procedureCode > sizeof(m3ap_messages_callback) / (3 * sizeof(
+          m3ap_message_decoded_callback))) {
+        //|| (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+      M3AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (m3ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1] == NULL) {
+      M3AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode,
+                  m3ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*m3ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+    break;
+
+  default:
+    M3AP_ERROR("[SCTP %d] Direction %d exceed expected\n",
+               assoc_id, pdu.present);
+    break;
+  }
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+int
+m3ap_eNB_handle_m3_setup_request(instance_t instance,
+                                 uint32_t assoc_id,
+                                 uint32_t stream,
+                                 M3AP_M3AP_PDU_t *pdu)
+{
+
+  M3AP_M3SetupRequest_t              *m3SetupRequest;
+  //M3AP_M3SetupRequestIEs_t          *ie;
+  //ServedCells__Member                *servedCellMember;
+
+  m3ap_eNB_instance_t                *instance_p;
+  m3ap_eNB_data_t                    *m3ap_eNB_data;
+  uint32_t                           eNB_id = 0;
+
+  DevAssert (pdu != NULL);
+  m3SetupRequest = &pdu->choice.initiatingMessage.value.choice.M3SetupRequest;
+
+  /*
+   * We received a new valid M3 Setup Request on a stream != 0.
+   * * * * This should not happen -> reject eNB m3 setup request.
+   */
+
+  if (stream != 0) {
+    M3AP_ERROR("Received new m3 setup request on stream != 0\n");
+      /*
+       * Send a m3 setup failure with protocol cause unspecified
+       */
+    return m3ap_eNB_generate_m3_setup_failure (instance,
+                                               assoc_id,
+                                               M3AP_Cause_PR_protocol,
+                                               M3AP_CauseProtocol_unspecified,
+                                               -1);
+  }
+
+  M3AP_DEBUG("Received a new M3 setup request\n");
+
+  //M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequestIEs_t, ie, m3SetupRequest,
+  //                           M3AP_ProtocolIE_ID_id_GlobalENB_ID, true);
+  //if (ie == NULL ) {
+  //  M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+  //  return -1;
+  //} else {
+  //  if (ie->value.choice.GlobalENB_ID.eNB_ID.present == M3AP_ENB_ID_PR_macro_eNB_ID) {
+  //  // Home eNB ID = 28 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 != 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);
+  //    M3AP_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);
+  //    M3AP_DEBUG("macro eNB id: %05x\n", eNB_id);
+  //  }
+  //}
+
+  M3AP_DEBUG("Adding eNB to the list of associated eNBs\n");
+
+  if ((m3ap_eNB_data = m3ap_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 ((m3ap_eNB_data = m3ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
+      /*
+       * ??
+       */
+      return -1;
+    } else {
+      m3ap_eNB_data->state = M3AP_ENB_STATE_RESETTING;
+      m3ap_eNB_data->eNB_id = eNB_id;
+    }
+  } else {
+    m3ap_eNB_data->state = M3AP_ENB_STATE_RESETTING;
+    /*
+     * eNB has been found in list, consider the m3 setup request as a reset connection,
+     * * * * reseting any previous UE state if sctp association is != than the previous one
+     */
+    if (m3ap_eNB_data->assoc_id != assoc_id) {
+      /*
+       * ??: Send an overload cause...
+       */
+      M3AP_ERROR("Rejecting m3 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, m3ap_eNB_data->assoc_id, assoc_id);
+
+      m3ap_eNB_generate_m3_setup_failure (instance,
+                                          assoc_id,
+                                          M3AP_Cause_PR_protocol,
+                                          M3AP_CauseProtocol_unspecified,
+                                          -1);
+      return -1;
+    }
+    /*
+     * TODO: call the reset procedure
+     */
+  }
+
+  /* Set proper pci */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupRequest_IEs_t, ie, m2SetupRequest,
+//                             M3AP_ProtocolIE_ID_id_ServedCells, true);
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//  if (ie->value.choice.ServedCells.list.count > 0) {
+//    m3ap_eNB_data->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];
+//      m3ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI;
+//    }
+//  }
+//
+  instance_p = m3ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  return m3ap_eNB_generate_m3_setup_response(instance_p, m3ap_eNB_data);
+}
+
+static
+int m3ap_eNB_handle_m3_setup_response(instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      M3AP_M3AP_PDU_t *pdu)
+{
+
+  M3AP_M3SetupResponse_t              *m3SetupResponse;
+  //M3AP_M3SetupResponseIEs_t          *ie;
+  //ServedCells__Member                 *servedCellMember;
+
+  m3ap_eNB_instance_t                 *instance_p;
+  m3ap_eNB_data_t                     *m3ap_eNB_data;
+  //uint32_t                            eNB_id = 0;
+
+  DevAssert (pdu != NULL);
+  m3SetupResponse = &pdu->choice.successfulOutcome.value.choice.M3SetupResponse;
+
+  /*
+   * We received a new valid M3 Setup Response on a stream != 0.
+   * * * * This should not happen -> reject eNB m3 setup response.
+   */
+
+  if (stream != 0) {
+    M3AP_ERROR("Received new m3 setup response on stream != 0\n");
+  }
+
+  if ((m3ap_eNB_data = m3ap_get_eNB(NULL, assoc_id, 0)) == NULL) {
+    M3AP_ERROR("[SCTP %d] Received M3 setup response for non existing "
+               "eNB context\n", assoc_id);
+    return -1;
+  }
+
+  M3AP_DEBUG("Received a new M3 setup response\n");
+
+ // M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupResponseIEs_t, ie, m3SetupResponse,
+ //                            M3AP_ProtocolIE_ID_id_GlobalENB_ID, true);
+
+ // if (ie == NULL ) {
+ //   M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+ //   return -1;
+ // } 
+//  if (ie->value.choice.GlobalENB_ID.eNB_ID.present == M3AP_ENB_ID_PR_macro_eNB_ID) {
+//    // Home eNB ID = 28 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 != 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);
+//    M3AP_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);
+//    M3AP_DEBUG("macro eNB id: %05x\n", eNB_id);
+//  }
+//
+  M3AP_DEBUG("Adding eNB to the list of associated eNBs\n");
+
+//  if ((m3ap_eNB_data = m3ap_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 ((m3ap_eNB_data = m3ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
+//      /*
+//       * ??: Send an overload cause...
+//       */
+//      return -1;
+//    } else {
+//      m3ap_eNB_data->state = M3AP_ENB_STATE_RESETTING;
+//      m3ap_eNB_data->eNB_id = eNB_id;
+//    }
+//  } else {
+//    m3ap_eNB_data->state = M3AP_ENB_STATE_RESETTING;
+//    /*
+//     * TODO: call the reset procedure
+//     */
+//  }
+//
+  /* Set proper pci */
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupResponse_IEs_t, ie, m2SetupResponse,
+//                             M3AP_ProtocolIE_ID_id_ServedCells, true);
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  if (ie->value.choice.ServedCells.list.count > 0) {
+//    m3ap_eNB_data->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];
+//      m3ap_eNB_data->Nid_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.
+   * Mark the association as connected.
+   */
+  m3ap_eNB_data->state = M3AP_ENB_STATE_READY;
+
+  instance_p = m3ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  instance_p->m3_target_enb_associated_nb ++;
+  m3ap_handle_m3_setup_message(instance_p, m3ap_eNB_data, 0);
+
+  return 0;
+}
+
+static
+int m3ap_eNB_handle_m3_setup_failure(instance_t instance,
+                                     uint32_t assoc_id,
+                                     uint32_t stream,
+                                     M3AP_M3AP_PDU_t *pdu)
+{
+
+  M3AP_M3SetupFailure_t              *m3SetupFailure;
+  M3AP_M3SetupFailureIEs_t          *ie;
+
+  m3ap_eNB_instance_t                *instance_p;
+  m3ap_eNB_data_t                    *m3ap_eNB_data;
+
+  DevAssert(pdu != NULL);
+
+  m3SetupFailure = &pdu->choice.unsuccessfulOutcome.value.choice.M3SetupFailure;
+
+  /*
+   * We received a new valid M3 Setup Failure on a stream != 0.
+   * * * * This should not happen -> reject eNB m3 setup failure.
+  */
+
+  if (stream != 0) {
+    M3AP_WARN("[SCTP %d] Received m3 setup failure on stream != 0 (%d)\n",
+    assoc_id, stream);
+  }
+
+  if ((m3ap_eNB_data = m3ap_get_eNB (NULL, assoc_id, 0)) == NULL) {
+    M3AP_ERROR("[SCTP %d] Received M3 setup failure for non existing "
+    "eNB context\n", assoc_id);
+    return -1;
+  }
+
+  M3AP_DEBUG("Received a new M3 setup failure\n");
+
+  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_M3SetupFailureIEs_t, ie, m3SetupFailure,
+                             M3AP_ProtocolIE_ID_id_Cause, true);
+
+  if (ie == NULL ) {
+    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    return -1;
+  } 
+  // need a FSM to handle all cases
+  if ((ie->value.choice.Cause.present == M3AP_Cause_PR_misc) &&
+      (ie->value.choice.Cause.choice.misc == M3AP_CauseMisc_unspecified)) {
+    M3AP_WARN("Received M3 setup failure for eNB ... eNB is not ready\n");
+  } else {
+    M3AP_ERROR("Received m3 setup failure for eNB... please check your parameters\n");
+  }
+
+  m3ap_eNB_data->state = M3AP_ENB_STATE_WAITING;
+
+  instance_p = m3ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  m3ap_handle_m3_setup_message(instance_p, m3ap_eNB_data, 0);
+
+  return 0;
+}
+
+//static
+//int m3ap_eNB_handle_handover_preparation (instance_t instance,
+//                                          uint32_t assoc_id,
+//                                          uint32_t stream,
+//                                          M3AP_M3AP_PDU_t *pdu)
+//{
+//
+//  M3AP_HandoverRequest_t             *x2HandoverRequest;
+//  M3AP_HandoverRequest_IEs_t         *ie;
+//
+//  M3AP_E_RABs_ToBeSetup_ItemIEs_t    *e_RABS_ToBeSetup_ItemIEs;
+//  M3AP_E_RABs_ToBeSetup_Item_t       *e_RABs_ToBeSetup_Item;
+//
+//  m3ap_eNB_instance_t                *instance_p;
+//  m3ap_eNB_data_t                    *m3ap_eNB_data;
+//  MessageDef                         *msg;
+//  int                                ue_id;
+//
+//  DevAssert (pdu != NULL);
+//  x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest;
+//
+//  if (stream == 0) {
+//    M3AP_ERROR ("Received new x2 handover request on stream == 0\n");
+//    /* TODO: send a x2 failure response */
+//    return 0;
+//  }
+//
+//  M3AP_DEBUG ("Received a new X2 handover request\n");
+//
+//  m3ap_eNB_data = m3ap_get_eNB(NULL, assoc_id, 0);
+//  DevAssert(m3ap_eNB_data != NULL);
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  msg = itti_alloc_new_message(TASK_M3AP, M3AP_HANDOVER_REQ);
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+//                             M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID, true);
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  /* allocate a new M3AP UE ID */
+//  ue_id = m3ap_allocate_new_id(&instance_p->id_manager);
+//  if (ue_id == -1) {
+//    M3AP_ERROR("could not allocate a new M3AP UE ID\n");
+//    /* TODO: cancel handover: send HO preparation failure to source eNB */
+//    exit(1);
+//  }
+//  /* rnti is unknown yet, must not be set to -1, 0 is fine */
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, 0, ie->value.choice.UE_M3AP_ID, ue_id);
+//  m3ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_TARGET);
+//
+//  M3AP_HANDOVER_REQ(msg).m2_id = ue_id;
+//
+//  //M3AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
+//                                               //measResultListEUTRA.list.array[ncell_index]->physCellId;
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+//                             M3AP_ProtocolIE_ID_id_GUMMEI_ID, true);
+//
+//  TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, M3AP_HANDOVER_REQ(msg).ue_gummei.mcc,
+//                  M3AP_HANDOVER_REQ(msg).ue_gummei.mnc, M3AP_HANDOVER_REQ(msg).ue_gummei.mnc_len);
+//  OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, M3AP_HANDOVER_REQ(msg).ue_gummei.mme_code);
+//  OCTET_STRING_TO_INT16(&ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID, M3AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id);
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+//                             M3AP_ProtocolIE_ID_id_UE_ContextInformation, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  M3AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID;
+//
+//  /* TODO: properly store Target Cell ID */
+//
+//  M3AP_HANDOVER_REQ(msg).target_assoc_id = assoc_id;
+//
+//  M3AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms =
+//    BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+//  M3AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms =
+//    BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+//
+//  //M3AP_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(M3AP_HANDOVER_REQ(msg).kenb, ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf, 32);
+//    M3AP_HANDOVER_REQ(msg).kenb_ncc = ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount;
+//  } else {
+//    M3AP_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) {
+//
+//    M3AP_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 = (M3AP_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;
+//
+//      M3AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = e_RABs_ToBeSetup_Item->e_RAB_ID ;
+//
+//      memcpy(M3AP_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);
+//
+//      M3AP_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,
+//                                                M3AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid);
+//
+//      M3AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI;
+//      M3AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel;
+//      M3AP_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;
+//      M3AP_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 {
+//    M3AP_ERROR ("Can't decode the e_RABs_ToBeSetup_List \n");
+//  }
+//
+//  M3AP_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 m3ap_handover_req_ack_s*/)
+//    { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
+//
+//  memcpy(M3AP_HANDOVER_REQ(msg).rrc_buffer, c->buf, c->size);
+//  M3AP_HANDOVER_REQ(msg).rrc_buffer_size = c->size;
+//
+//  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+//
+//  return 0;
+//}
+//
+//static
+//int m3ap_eNB_handle_handover_response (instance_t instance,
+//                                       uint32_t assoc_id,
+//                                       uint32_t stream,
+//                                       M3AP_M3AP_PDU_t *pdu)
+//{
+//  M3AP_HandoverRequestAcknowledge_t             *x2HandoverRequestAck;
+//  M3AP_HandoverRequestAcknowledge_IEs_t         *ie;
+//
+//  m3ap_eNB_instance_t                           *instance_p;
+//  m3ap_eNB_data_t                               *m3ap_eNB_data;
+//  MessageDef                                    *msg;
+//  int                                           ue_id;
+//  int                                           id_source;
+//  int                                           id_target;
+//  int                                           rnti;
+//
+//  DevAssert (pdu != NULL);
+//  x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+//
+//  if (stream == 0) {
+//    M3AP_ERROR ("Received new x2 handover response on stream == 0\n");
+//    /* TODO: send a x2 failure response */
+//    return 0;
+//  }
+//
+//  M3AP_DEBUG ("Received a new X2 handover response\n");
+//
+//  m3ap_eNB_data = m3ap_get_eNB(NULL, assoc_id, 0);
+//  DevAssert(m3ap_eNB_data != NULL);
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  msg = itti_alloc_new_message(TASK_M3AP, M3AP_HANDOVER_REQ_ACK);
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
+//                             M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  id_source = ie->value.choice.UE_M3AP_ID;
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
+//                             M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  id_target = ie->value.choice.UE_M3AP_ID_1;
+//
+//  ue_id = id_source;
+//
+//  if (ue_id != m3ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
+//    M3AP_WARN("incorrect/unknown M3AP IDs for UE (old ID %d new ID %d), ignoring handover response\n",
+//              id_source, id_target);
+//    return 0;
+//  }
+//
+//  rnti = m3ap_id_get_rnti(&instance_p->id_manager, ue_id);
+//
+//  /* id_target is a new information, store it */
+//  m3ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
+//  m3ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL);
+//  m3ap_set_reloc_overall_timer(&instance_p->id_manager, ue_id,
+//                               m3ap_timer_get_tti(&instance_p->timers));
+//
+//  M3AP_HANDOVER_REQ_ACK(msg).rnti = rnti;
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
+//                             M3AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
+//
+//  M3AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer;
+//
+//  if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct m3ap_handover_req_ack_s*/)
+//    { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
+//
+//  memcpy(M3AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
+//  M3AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
+//
+//  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+//  return 0;
+//}
+//
+//
+//static
+//int m3ap_eNB_handle_ue_context_release (instance_t instance,
+//                                        uint32_t assoc_id,
+//                                        uint32_t stream,
+//                                        M3AP_M3AP_PDU_t *pdu)
+//{
+//  M3AP_UEContextRelease_t             *x2UEContextRelease;
+//  M3AP_UEContextRelease_IEs_t         *ie;
+//
+//  m3ap_eNB_instance_t                 *instance_p;
+//  m3ap_eNB_data_t                     *m3ap_eNB_data;
+//  MessageDef                          *msg;
+//  int                                 ue_id;
+//  int                                 id_source;
+//  int                                 id_target;
+//
+//  DevAssert (pdu != NULL);
+//  x2UEContextRelease = &pdu->choice.initiatingMessage.value.choice.UEContextRelease;
+//
+//  if (stream == 0) {
+//    M3AP_ERROR ("Received new x2 ue context release on stream == 0\n");
+//    /* TODO: send a x2 failure response */
+//    return 0;
+//  }
+//
+//  M3AP_DEBUG ("Received a new X2 ue context release\n");
+//
+//  m3ap_eNB_data = m3ap_get_eNB(NULL, assoc_id, 0);
+//  DevAssert(m3ap_eNB_data != NULL);
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  msg = itti_alloc_new_message(TASK_M3AP, M3AP_UE_CONTEXT_RELEASE);
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
+//                             M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  id_source = ie->value.choice.UE_M3AP_ID;
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
+//                             M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  id_target = ie->value.choice.UE_M3AP_ID_1;
+//
+//  ue_id = id_source;
+//  if (ue_id != m3ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
+//    M3AP_WARN("incorrect/unknown M3AP IDs for UE (old ID %d new ID %d), ignoring UE context release\n",
+//              id_source, id_target);
+//    return 0;
+//  }
+//
+//  if (id_target != m3ap_id_get_id_target(&instance_p->id_manager, ue_id)) {
+//    M3AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d, ignoring message\n",
+//               m3ap_id_get_rnti(&instance_p->id_manager, ue_id),
+//               id_source,
+//               m3ap_id_get_id_target(&instance_p->id_manager, ue_id),
+//               id_target);
+//    return 0;
+//  }
+//
+//  M3AP_UE_CONTEXT_RELEASE(msg).rnti = m3ap_id_get_rnti(&instance_p->id_manager, ue_id);
+//
+//  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+//
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//
+//  return 0;
+//}
+//
+//static
+//int m3ap_eNB_handle_handover_cancel (instance_t instance,
+//                                     uint32_t assoc_id,
+//                                     uint32_t stream,
+//                                     M3AP_M3AP_PDU_t *pdu)
+//{
+//  M3AP_HandoverCancel_t             *x2HandoverCancel;
+//  M3AP_HandoverCancel_IEs_t         *ie;
+//
+//  m3ap_eNB_instance_t               *instance_p;
+//  m3ap_eNB_data_t                   *m3ap_eNB_data;
+//  MessageDef                        *msg;
+//  int                               ue_id;
+//  int                               id_source;
+//  int                               id_target;
+//  m3ap_handover_cancel_cause_t      cause;
+//
+//  DevAssert (pdu != NULL);
+//  x2HandoverCancel = &pdu->choice.initiatingMessage.value.choice.HandoverCancel;
+//
+//  if (stream == 0) {
+//    M3AP_ERROR ("Received new x2 handover cancel on stream == 0\n");
+//    return 0;
+//  }
+//
+//  M3AP_DEBUG ("Received a new X2 handover cancel\n");
+//
+//  m3ap_eNB_data = m3ap_get_eNB(NULL, assoc_id, 0);
+//  DevAssert(m3ap_eNB_data != NULL);
+//
+//  instance_p = m3ap_eNB_get_instance(instance);
+//  DevAssert(instance_p != NULL);
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
+//                             M3AP_ProtocolIE_ID_id_Old_eNB_UE_M3AP_ID, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  id_source = ie->value.choice.UE_M3AP_ID;
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
+//                             M3AP_ProtocolIE_ID_id_New_eNB_UE_M3AP_ID, false);
+//
+//  if (ie == NULL ) {
+//    M3AP_INFO("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    id_target = -1;
+//  } else
+//    id_target = ie->value.choice.UE_M3AP_ID_1;
+//
+//  M3AP_FIND_PROTOCOLIE_BY_ID(M3AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
+//                             M3AP_ProtocolIE_ID_id_Cause, true);
+//
+//  if (ie == NULL ) {
+//    M3AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  if (ie->value.present != M3AP_HandoverCancel_IEs__value_PR_Cause ||
+//      ie->value.choice.Cause.present != M3AP_Cause_PR_radioNetwork ||
+//      !(ie->value.choice.Cause.choice.radioNetwork ==
+//            M3AP_CauseRadioNetwork_trelocprep_expiry ||
+//        ie->value.choice.Cause.choice.radioNetwork ==
+//            M3AP_CauseRadioNetwork_tx2relocoverall_expiry)) {
+//    M3AP_ERROR("%s %d: Cause not supported (only T_reloc_prep and TX2_reloc_overall handled)\n",__FILE__,__LINE__);
+//    return -1;
+//  }
+//
+//  switch (ie->value.choice.Cause.choice.radioNetwork) {
+//  case M3AP_CauseRadioNetwork_trelocprep_expiry:
+//    cause = M3AP_T_RELOC_PREP_TIMEOUT;
+//    break;
+//  case M3AP_CauseRadioNetwork_tx2relocoverall_expiry:
+//    cause = M3AP_TX2_RELOC_OVERALL_TIMEOUT;
+//    break;
+//  default: /* can't come here */ exit(1);
+//  }
+//
+//  ue_id = m3ap_find_id_from_id_source(&instance_p->id_manager, id_source);
+//  if (ue_id == -1) {
+//    M3AP_WARN("Handover cancel: UE not found (id_source = %d), ignoring message\n", id_source);
+//    return 0;
+//  }
+//
+//  if (id_target != -1 &&
+//      id_target != m3ap_id_get_id_target(&instance_p->id_manager, ue_id)) {
+//    M3AP_ERROR("Handover cancel: bad id_target for UE %x (id_source %d) expected %d got %d\n",
+//               m3ap_id_get_rnti(&instance_p->id_manager, ue_id),
+//               id_source,
+//               m3ap_id_get_id_target(&instance_p->id_manager, ue_id),
+//               id_target);
+//    exit(1);
+//  }
+//
+//  msg = itti_alloc_new_message(TASK_M3AP, M3AP_HANDOVER_CANCEL);
+//
+//  M3AP_HANDOVER_CANCEL(msg).rnti = m3ap_id_get_rnti(&instance_p->id_manager, ue_id);
+//  M3AP_HANDOVER_CANCEL(msg).cause = cause;
+//
+//  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+//
+//  m3ap_release_id(&instance_p->id_manager, ue_id);
+//
+//  return 0;
+//}
diff --git a/openair3/M3AP/m3ap_eNB_handler.h b/openair3/M3AP/m3ap_eNB_handler.h
new file mode 100644
index 00000000000..d0c97ac532d
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_handler.h
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.h
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENB_HANDLERS_H_
+#define M3AP_ENB_HANDLERS_H_
+
+#include "m3ap_eNB_defs.h"
+
+void m3ap_handle_m3_setup_message(m3ap_eNB_instance_t *instance_p, m3ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+#endif /* M3AP_ENB_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_eNB_itti_messaging.c b/openair3/M3AP/m3ap_eNB_itti_messaging.c
new file mode 100644
index 00000000000..834b429ccb3
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_itti_messaging.c
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_itti_messaging.c
+ * \brief m3ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+#include "m3ap_eNB_itti_messaging.h"
+
+void m3ap_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_M3AP, 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 m3ap_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_M3AP, 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/openair3/M3AP/m3ap_eNB_itti_messaging.h b/openair3/M3AP/m3ap_eNB_itti_messaging.h
new file mode 100644
index 00000000000..134b00e4a9d
--- /dev/null
+++ b/openair3/M3AP/m3ap_eNB_itti_messaging.h
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_itti_messaging.h
+ * \brief m3ap tasks for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENB_ITTI_MESSAGING_H_
+#define M3AP_ENB_ITTI_MESSAGING_H_
+
+void m3ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m3ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+#endif /* M3AP_ENB_ITTI_MESSAGING_H_ */
diff --git a/openair3/M3AP/m3ap_encoder.c b/openair3/M3AP/m3ap_encoder.c
new file mode 100644
index 00000000000..2e1cbf80af5
--- /dev/null
+++ b/openair3/M3AP/m3ap_encoder.c
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_encoder.c
+ * \brief m3ap encoder procedures
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "assertions.h"
+#include "conversions.h"
+#include "intertask_interface.h"
+#include "m3ap_common.h"
+#include "m3ap_encoder.h"
+
+int m3ap_encode_pdu(M3AP_M3AP_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_M3AP_M3AP_PDU, (void *)pdu);
+  }
+
+  encoded = aper_encode_to_new_buffer(&asn_DEF_M3AP_M3AP_PDU, 0, pdu, (void **)buffer);
+
+  if (encoded < 0) {
+    return -1;
+  }
+
+  *len = encoded;
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, pdu);
+  return encoded;
+}
diff --git a/openair3/M3AP/m3ap_encoder.h b/openair3/M3AP/m3ap_encoder.h
new file mode 100644
index 00000000000..db444a611e1
--- /dev/null
+++ b/openair3/M3AP/m3ap_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_encoder.h
+ * \brief m3ap encoder procedures
+ * \author Javier Morgade  <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_ENCODER_H_
+#define M3AP_ENCODER_H_
+
+int m3ap_encode_pdu(M3AP_M3AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+__attribute__ ((warn_unused_result));
+
+#endif /* M3AP_ENCODER_H_ */
diff --git a/openair3/M3AP/m3ap_handler.c b/openair3/M3AP/m3ap_handler.c
new file mode 100644
index 00000000000..832aa0dbacc
--- /dev/null
+++ b/openair3/M3AP/m3ap_handler.c
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_eNB_handler.c
+ * \brief m3ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include <stdint.h>
+
+#include "intertask_interface.h"
+
+#include "asn1_conversions.h"
+
+#include "m3ap_common.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_handler.h"
+#include "m3ap_decoder.h"
+#include "m3ap_ids.h"
+
+#include "m3ap_MCE_management_procedures.h"
+//#include "m3ap_MCE_generate_messages.h"
+
+#include "m3ap_MME_interface_management.h"
+#include "m3ap_MCE_interface_management.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+/* Handlers matrix. Only eNB related procedure present here */
+m3ap_message_decoded_callback m3ap_messages_callback[][3] = {
+  { MCE_handle_MBMS_SESSION_START_REQUEST, MME_handle_MBMS_SESSION_START_RESPONSE, 0 }, /* MBMSSessionStart  */
+  { MCE_handle_MBMS_SESSION_STOP_REQUEST, MME_handle_MBMS_SESSION_STOP_RESPONSE, 0 }, /* MBMSSessionStop */
+  { 0, 0, 0 }, /* Error Indication */
+  { 0, 0, 0 }, /* Reset */
+  { 0, 0, 0 }, /* ??? */
+  { MCE_handle_MBMS_SESSION_UPDATE_REQUEST, MME_handle_MBMS_SESSION_UPDATE_RESPONSE, 0 }, /* MBMSSessionUpdate */
+  { 0, 0, 0 }, /* MCEConfigurationUpdate */
+  { MME_handle_M3_SETUP_REQUEST, MCE_handle_M3_SETUP_RESPONSE, 0 } /* M3 Setup */
+};
+
+char *m3ap_direction2String(int m3ap_dir) {
+static char *m3ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(m3ap_direction_String[m3ap_dir]);
+}
+
+
+int m3ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length)
+{
+  M3AP_M3AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  int i=0; 
+  for( i=0; i < data_length; i++)
+	printf("%02X",data[i]);
+  printf("\n");
+
+  if (m3ap_decode_pdu(&pdu, data, data_length) < 0) {
+    LOG_E(M3AP, "Failed to decode PDU\n");
+    return -1;
+  }
+
+  /* Checking procedure Code and direction of message */
+  if (pdu.choice.initiatingMessage.procedureCode > sizeof(m3ap_messages_callback) / (3 * sizeof(
+        m3ap_message_decoded_callback))
+      || (pdu.present > M3AP_M3AP_PDU_PR_unsuccessfulOutcome)) {
+    LOG_E(M3AP, "[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_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+
+  /* No handler present.
+   * This can mean not implemented or no procedure for eNB (wrong direction).
+   */
+  if (m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+    LOG_E(M3AP, "[SCTP %d] No handler for procedureCode %ld in %s\n",
+                assoc_id, pdu.choice.initiatingMessage.procedureCode,
+               m3ap_direction2String(pdu.present - 1));
+    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+    return -1;
+  }
+  
+  /* Calling the right handler */
+  LOG_I(M3AP, "Calling handler with instance %d\n",instance);
+  ret = (*m3ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu);
+  return ret;
+}
+
+
diff --git a/openair3/M3AP/m3ap_handler.h b/openair3/M3AP/m3ap_handler.h
new file mode 100644
index 00000000000..4b01307807a
--- /dev/null
+++ b/openair3/M3AP/m3ap_handler.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m2ap_handler.h
+ * \brief m2ap handler procedures for eNB
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M2AP_MCE_OLD_HANDLERS_H_
+#define M2AP_MCE_OLD_HANDLERS_H_
+
+#include "m2ap_eNB_defs.h"
+
+//void m3ap_handle_m2_setup_message(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
+
+//int m3ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            //const uint8_t * const data, const uint32_t data_length);
+
+int m3ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
+
+
+#endif /* M2AP_MCE_HANDLERS_H_ */
diff --git a/openair3/M3AP/m3ap_ids.c b/openair3/M3AP/m3ap_ids.c
new file mode 100644
index 00000000000..8e0a9f2106b
--- /dev/null
+++ b/openair3/M3AP/m3ap_ids.c
@@ -0,0 +1,128 @@
+/*
+ * 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 "m3ap_ids.h"
+
+#include <string.h>
+
+void m3ap_id_manager_init(m3ap_id_manager *m)
+{
+  int i;
+  memset(m, 0, sizeof(m3ap_id_manager));
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    m->ids[i].rnti = -1;
+}
+
+int m3ap_allocate_new_id(m3ap_id_manager *m)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == -1) {
+      m->ids[i].rnti = 0;
+      m->ids[i].id_source = -1;
+      m->ids[i].id_target = -1;
+      return i;
+    }
+  return -1;
+}
+
+void m3ap_release_id(m3ap_id_manager *m, int id)
+{
+  m->ids[id].rnti = -1;
+}
+
+int m3ap_find_id(m3ap_id_manager *m, int id_source, int id_target)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source &&
+        m->ids[i].id_target == id_target)
+      return i;
+  return -1;
+}
+
+int m3ap_find_id_from_id_source(m3ap_id_manager *m, int id_source)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti != -1 &&
+        m->ids[i].id_source == id_source)
+      return i;
+  return -1;
+}
+
+int m3ap_find_id_from_rnti(m3ap_id_manager *m, int rnti)
+{
+  int i;
+  for (i = 0; i < M3AP_MAX_IDS; i++)
+    if (m->ids[i].rnti == rnti)
+      return i;
+  return -1;
+}
+
+void m3ap_set_ids(m3ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target)
+{
+  m->ids[ue_id].rnti      = rnti;
+  m->ids[ue_id].id_source = id_source;
+  m->ids[ue_id].id_target = id_target;
+}
+
+/* real type of target is m3ap_eNB_data_t * */
+void m3ap_id_set_target(m3ap_id_manager *m, int ue_id, void *target)
+{
+  m->ids[ue_id].target = target;
+}
+
+void m3ap_id_set_state(m3ap_id_manager *m, int ue_id, m3id_state_t state)
+{
+  m->ids[ue_id].state = state;
+}
+
+void m3ap_set_reloc_prep_timer(m3ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].t_reloc_prep_start = time;
+}
+
+void m3ap_set_reloc_overall_timer(m3ap_id_manager *m, int ue_id, uint64_t time)
+{
+  m->ids[ue_id].tm3_reloc_overall_start = time;
+}
+
+int m3ap_id_get_id_source(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_source;
+}
+
+int m3ap_id_get_id_target(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].id_target;
+}
+
+int m3ap_id_get_rnti(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].rnti;
+}
+
+void *m3ap_id_get_target(m3ap_id_manager *m, int ue_id)
+{
+  return m->ids[ue_id].target;
+}
diff --git a/openair3/M3AP/m3ap_ids.h b/openair3/M3AP/m3ap_ids.h
new file mode 100644
index 00000000000..bc5a3c38980
--- /dev/null
+++ b/openair3/M3AP/m3ap_ids.h
@@ -0,0 +1,80 @@
+/*
+ * 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 M3AP_IDS_H_
+#define M3AP_IDS_H_
+
+#include <stdint.h>
+
+/* maximum number of simultaneous handovers, do not set too high */
+#define M3AP_MAX_IDS	16
+
+/*
+ * state:
+ * - when starting handover in source, UE is in state M3ID_STATE_SOURCE_PREPARE
+ * - after receiving HO_ack in source, UE is in state M3ID_STATE_SOURCE_OVERALL
+ * - in target, UE is in state X2ID_STATE_TARGET
+ * The state is used to check timers.
+ */
+typedef enum {
+  M3ID_STATE_SOURCE_PREPARE,
+  M3ID_STATE_SOURCE_OVERALL,
+  M3ID_STATE_TARGET
+} m3id_state_t;
+
+typedef struct {
+  int           rnti;             /* -1 when free */
+  int           id_source;
+  int           id_target;
+
+  /* the target eNB. Real type is m3ap_eNB_data_t * */
+  void          *target;
+
+  /* state: needed to check timers */
+  m3id_state_t  state;
+
+  /* timers */
+  uint64_t      t_reloc_prep_start;
+  uint64_t      tm3_reloc_overall_start;
+} m3ap_id;
+
+typedef struct {
+  m3ap_id ids[M3AP_MAX_IDS];
+} m3ap_id_manager;
+
+void m3ap_id_manager_init(m3ap_id_manager *m);
+int m3ap_allocate_new_id(m3ap_id_manager *m);
+void m3ap_release_id(m3ap_id_manager *m, int id);
+int m3ap_find_id(m3ap_id_manager *, int id_source, int id_target);
+int m3ap_find_id_from_id_source(m3ap_id_manager *, int id_source);
+int m3ap_find_id_from_rnti(m3ap_id_manager *, int rnti);
+void m3ap_set_ids(m3ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
+void m3ap_id_set_state(m3ap_id_manager *m, int ue_id, m3id_state_t state);
+/* real type of target is m3ap_eNB_data_t * */
+void m3ap_id_set_target(m3ap_id_manager *m, int ue_id, void *target);
+void m3ap_set_reloc_prep_timer(m3ap_id_manager *m, int ue_id, uint64_t time);
+void m3ap_set_reloc_overall_timer(m3ap_id_manager *m, int ue_id, uint64_t time);
+int m3ap_id_get_id_source(m3ap_id_manager *m, int ue_id);
+int m3ap_id_get_id_target(m3ap_id_manager *m, int ue_id);
+int m3ap_id_get_rnti(m3ap_id_manager *m, int ue_id);
+void *m3ap_id_get_target(m3ap_id_manager *m, int ue_id);
+
+#endif /* M3AP_IDS_H_ */
diff --git a/openair3/M3AP/m3ap_itti_messaging.c b/openair3/M3AP/m3ap_itti_messaging.c
new file mode 100644
index 00000000000..b9067476407
--- /dev/null
+++ b/openair3/M3AP/m3ap_itti_messaging.c
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_MCE_itti_messaging.c
+ * \brief m3ap tasks for MCE
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#include "intertask_interface.h"
+
+#include "m3ap_itti_messaging.h"
+
+void m3ap_MCE_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_M3AP_MCE, 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;
+
+  //LOG_W(M3AP,"assoc_id %d, stream %d\n",assoc_id,stream);
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void m3ap_MCE_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_M3AP_MCE, 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);
+}
+
+
+void m3ap_MME_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_M3AP_MME, 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 m3ap_MME_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_M3AP_MME, 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/openair3/M3AP/m3ap_itti_messaging.h b/openair3/M3AP/m3ap_itti_messaging.h
new file mode 100644
index 00000000000..8a4069da9b3
--- /dev/null
+++ b/openair3/M3AP/m3ap_itti_messaging.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file m3ap_itti_messaging.h
+ * \brief m3ap tasks for MME
+ * \author Javier Morgade <javier.morgade@ieee.org>
+ * \date 2019
+ * \version 0.1
+ */
+
+#ifndef M3AP_MCE_ITTI_MESSAGING_H_
+#define M3AP_MCE_ITTI_MESSAGING_H_
+
+void m3ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m3ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+void m3ap_MME_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void m3ap_MME_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+
+
+#endif /* M3AP_MCE_ITTI_MESSAGING_H_ */
diff --git a/openair3/M3AP/m3ap_timers.c b/openair3/M3AP/m3ap_timers.c
new file mode 100644
index 00000000000..39498cc8eb0
--- /dev/null
+++ b/openair3/M3AP/m3ap_timers.c
@@ -0,0 +1,105 @@
+/*
+ * 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 "m3ap_timers.h"
+#include "assertions.h"
+#include "PHY/defs_common.h"         /* TODO: try to not include this */
+#include "m3ap_messages_types.h"
+#include "m3ap_MCE_defs.h"
+#include "m3ap_ids.h"
+#include "m3ap_MCE_management_procedures.h"
+//#include "m3ap_eNB_generate_messages.h"
+
+void m3ap_timers_init(m3ap_timers_t *t, int t_reloc_prep, int tm3_reloc_overall)
+{
+  t->tti               = 0;
+  t->t_reloc_prep      = t_reloc_prep;
+  t->tm3_reloc_overall = tm3_reloc_overall;
+}
+
+void m3ap_check_timers(instance_t instance)
+{
+  //m3ap_eNB_instance_t          *instance_p;
+  //m3ap_timers_t                *t;
+  //m3ap_id_manager              *m;
+  //int                          i;
+  //m3ap_handover_cancel_cause_t cause;
+  //void                         *target;
+  //MessageDef                   *msg;
+  //int                          m2_ongoing;
+
+  //instance_p = m3ap_eNB_get_instance(instance);
+  //DevAssert(instance_p != NULL);
+
+  //t = &instance_p->timers;
+  //m = &instance_p->id_manager;
+
+  ///* increment subframe count */
+  //t->tti++;
+
+  //m2_ongoing = 0;
+
+  //for (i = 0; i < M3AP_MAX_IDS; i++) {
+  //  if (m->ids[i].rnti == -1) continue;
+  //  m2_ongoing++;
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_PREPARE &&
+  //      t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
+  //    LOG_I(M3AP, "M2 timeout reloc prep\n");
+  //    /* t_reloc_prep timed out */
+  //    cause = M3AP_T_RELOC_PREP_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  if (m->ids[i].state == M2ID_STATE_SOURCE_OVERALL &&
+  //      t->tti > m->ids[i].tm2_reloc_overall_start + t->tm2_reloc_overall) {
+  //    LOG_I(M3AP, "M2 timeout reloc overall\n");
+  //    /* tm2_reloc_overall timed out */
+  //    cause = M3AP_TM2_RELOC_OVERALL_TIMEOUT;
+  //    goto timeout;
+  //  }
+
+  //  /* no timeout -> check next UE */
+  //  continue;
+
+  // timeout:
+  //  /* inform target about timeout */
+  //  target = m3ap_id_get_target(m, i);
+  //  m3ap_eNB_generate_m2_handover_cancel(instance_p, target, i, cause);
+
+  //  /* inform RRC of cancellation */
+  //  msg = itti_alloc_new_message(TASK_M3AP, M3AP_HANDOVER_CANCEL);
+  //  M3AP_HANDOVER_CANCEL(msg).rnti  = m3ap_id_get_rnti(m, i);
+  //  M3AP_HANDOVER_CANCEL(msg).cause = cause;
+  //  itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
+
+  //  /* remove UE from M3AP */
+  //  m3ap_release_id(m, i);
+  //}
+
+  //if (m2_ongoing && t->tti % 1000 == 0)
+  //  LOG_I(M3AP, "M2 has %d process ongoing\n", m2_ongoing);
+}
+
+uint64_t m3ap_timer_get_tti(m3ap_timers_t *t)
+{
+  return t->tti;
+}
diff --git a/openair3/M3AP/m3ap_timers.h b/openair3/M3AP/m3ap_timers.h
new file mode 100644
index 00000000000..95dcbfc9d96
--- /dev/null
+++ b/openair3/M3AP/m3ap_timers.h
@@ -0,0 +1,45 @@
+/*
+ * 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 M3AP_TIMERS_H_
+#define M3AP_TIMERS_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+typedef struct {
+  /* incremented every TTI (every millisecond when in realtime).
+   * Used to check timers.
+   * 64 bits gives us more than 500 million years of (realtime) processing.
+   * It should be enough.
+   */
+  uint64_t tti;
+
+  /* timer values (unit: TTI, ie. millisecond when in realtime) */
+  int      t_reloc_prep;
+  int      tm3_reloc_overall;
+} m3ap_timers_t;
+
+void m3ap_timers_init(m3ap_timers_t *t, int t_reloc_prep, int tm3_reloc_overall);
+void m3ap_check_timers(instance_t instance);
+uint64_t m3ap_timer_get_tti(m3ap_timers_t *t);
+
+#endif /* M3AP_TIMERS_H_ */
diff --git a/openair3/MME_APP/enb_paramdef_mme.h b/openair3/MME_APP/enb_paramdef_mme.h
new file mode 100644
index 00000000000..3d65036553b
--- /dev/null
+++ b/openair3/MME_APP/enb_paramdef_mme.h
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file openair2/ENB_APP/enb_paramdef_mce.h
+ * \brief definition of configuration parameters for MME modules 
+ * \author Javier MORGADE
+ * \date 2019
+ * \version 0.1
+ * \company VICOMTECH Spain
+ * \email: javier.morgade@ieee.org
+ * \note
+ * \warning
+ */
+
+#include "common/config/config_paramdesc.h"
+#include "RRC_paramsvalues.h"
+
+#define ENB_CONFIG_STRING_MME_PARAMETERS                                  "mme_parameters"
+//#define ENB_CONFIG_STRING_SCHEDULING_INFO_BR                               "scheduling_info_br"
+//#define ENB_CONFIG_STRING_RSRP_RANGE_LIST                                  "rsrp_range_list"
+//#define ENB_CONFIG_STRING_PRACH_CONFIG_COMMON_V1310                        "prach_ConfigCommon_v1310"
+//#define ENB_CONFIG_STRING_MPDCCH_START_SF_CSS_RA_R13                       "mpdcch_startSF_CSS_RA_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_START_SF_CSS_RA_R13_VAL                   "mpdcch_startSF_CSS_RA_r13_val"
+//#define ENB_CONFIG_STRING_PRACH_HOPPING_OFFSET_R13                         "prach_HoppingOffset_r13"
+//#define ENB_CONFIG_STRING_SCHEDULING_INFO_SIB1_BR_R13                      "schedulingInfoSIB1_BR_r13"
+//#define ENB_CONFIG_STRING_CELL_SELECTION_INFO_CE_R13                       "cellSelectionInfoCE_r13"
+//#define ENB_CONFIG_STRING_Q_RX_LEV_MIN_CE_R13                              "q_RxLevMinCE_r13"
+//#define ENB_CONFIG_STRING_BANDWIDTH_REDUCED_ACCESS_RELATED_INFO_R13        "bandwidthReducedAccessRelatedInfo_r13"
+//#define ENB_CONFIG_STRING_SI_WINDOW_LENGTH_BR_R13                          "si_WindowLength_BR_r13"
+//#define ENB_CONFIG_STRING_SI_REPETITION_PATTERN_R13                        "si_RepetitionPattern_r13"
+//#define ENB_CONFIG_STRING_FDD_DOWNLINK_OR_TDD_SUBFRAME_BITMAP_BR_R13       "fdd_DownlinkOrTddSubframeBitmapBR_r13"
+//#define ENB_CONFIG_STRING_FDD_DOWNLINK_OR_TDD_SUBFRAME_BITMAP_BR_VAL_R13   "fdd_DownlinkOrTddSubframeBitmapBR_val_r13"
+//#define ENB_CONFIG_STRING_START_SYMBOL_BR_R13                              "startSymbolBR_r13"
+//#define ENB_CONFIG_STRING_SI_HOPPING_CONFIG_COMMON_R13                     "si_HoppingConfigCommon_r13"
+//#define ENB_CONFIG_STRING_SI_VALIDITY_TIME_R13                             "si_ValidityTime_r13"
+//#define ENB_CONFIG_STRING_FREQ_HOPPING_PARAMETERS_DL_R13                   "freqHoppingParametersDL_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_PDSCH_HOPPING_NB_R13                      "mpdcch_pdsch_HoppingNB_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_A_R13     "interval_DLHoppingConfigCommonModeA_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_A_R13_VAL "interval_DLHoppingConfigCommonModeA_r13_val"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_B_R13     "interval_DLHoppingConfigCommonModeB_r13"
+//#define ENB_CONFIG_STRING_INTERVAL_DL_HOPPING_CONFIG_COMMON_MODE_B_R13_VAL "interval_DLHoppingConfigCommonModeB_r13_val"
+//#define ENB_CONFIG_STRING_MPDCCH_PDSCH_HOPPING_OFFSET_R13                  "mpdcch_pdsch_HoppingOffset_r13"
+//#define ENB_CONFIG_STRING_PREAMBLE_TRANSMAX_CE_R13                         "preamble_TransMax_ce_r13"
+//#define ENB_CONFIG_STRING_PREAMBLE_TRANSMAX_CE_R13_VAL                     "preamble_TransMax_ce_r13_val"
+//#define ENB_CONFIG_STRING_PDSCH_MAX_NUM_REPETITION_CE_MODE_A_R13           "pdsch_maxNumRepetitionCEmodeA_r13"
+//#define ENB_CONFIG_STRING_PDSCH_MAX_NUM_REPETITION_CE_MODE_B_R13           "pdsch_maxNumRepetitionCEmodeB_r13"
+//#define ENB_CONFIG_STRING_PUSCH_MAX_NUM_REPETITION_CE_MODE_A_R13           "pusch_maxNumRepetitionCEmodeA_r13"
+//#define ENB_CONFIG_STRING_PUSCH_MAX_NUM_REPETITION_CE_MODE_B_R13           "pusch_maxNumRepetitionCEmodeB_r13"
+//#define ENB_CONFIG_STRING_PUSCH_HOPPING_OFFSET_V1310                       "pusch_HoppingOffset_v1310"
+//#define ENB_CONFIG_STRING_SYSTEM_INFO_VALUE_TAG_LIST                       "system_info_value_tag_SI"
+//#define ENB_CONFIG_STRING_FIRST_PREAMBLE_R13                               "firstPreamble_r13"
+//#define ENB_CONFIG_STRING_LAST_PREAMBLE_R13                                "lastPreamble_r13"
+//#define ENB_CONFIG_STRING_RA_RESPONSE_WINDOW_SIZE_R13                      "ra_ResponseWindowSize_r13"
+//#define ENB_CONFIG_STRING_MAC_CONTENTION_RESOLUTION_TIMER_R13              "mac_ContentionResolutionTimer_r13"
+//#define ENB_CONFIG_STRING_RAR_HOPPING_CONFIG_R13                           "rar_HoppingConfig_r13"
+//#define ENB_CONFIG_STRING_RACH_CE_LEVELINFOLIST_R13                        "rach_CE_LevelInfoList_r13"
+//#define ENB_CONFIG_STRING_PRACH_CONFIG_INDEX_BR                            "prach_config_index_br"
+//#define ENB_CONFIG_STRING_PRACH_FREQ_OFFSET_BR                             "prach_freq_offset_br"
+//#define ENB_CONFIG_STRING_PRACH_STARTING_SUBFRAME_R13                      "prach_StartingSubframe_r13"
+//#define ENB_CONFIG_STRING_MAX_NUM_PER_PREAMBLE_ATTEMPT_CE_R13              "maxNumPreambleAttemptCE_r13"
+//#define ENB_CONFIG_STRING_NUM_REPETITION_PER_PREAMBLE_ATTEMPT_R13          "numRepetitionPerPreambleAttempt_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_NUM_REPETITION_RA_R13                     "mpdcch_NumRepetition_RA_r13"
+//#define ENB_CONFIG_STRING_PRACH_HOPPING_CONFIG_R13                         "prach_HoppingConfig_r13"
+//#define ENB_CONFIG_SRING_MAX_AVAILABLE_NARROW_BAND                         "max_available_narrow_band"
+//#define ENB_CONFIG_STRING_PRACH_PARAMETERS_CE_R13                          "prach_parameters_ce_r13"							
+//#define ENB_CONFIG_STRING_PUCCH_INFO_VALUE                                 "pucch_info_value"
+//#define ENB_CONFIG_STRING_N1PUCCH_AN_INFOLIST_R13                          "n1PUCCH_AN_InfoList_r13"
+//#define ENB_CONFIG_STRING_PCCH_CONFIG_V1310                                "pcch_config_v1310"
+//#define ENB_CONFIG_STRING_PAGING_NARROWBANDS_R13                           "paging_narrowbands_r13"
+//#define ENB_CONFIG_STRING_MPDCCH_NUMREPETITION_PAGING_R13                  "mpdcch_numrepetition_paging_r13"
+//#define ENB_CONFIG_STRING_NB_V1310                                         "nb_v1310"
+//#define ENB_CONFIG_STRING_SIB2_FREQ_HOPPINGPARAMETERS_R13                  "sib2_freq_hoppingParameters_r13" 
+
+typedef struct ccparams_MME_s {
+  /// indicator that eMTC is configured for this cell
+  int32_t        MME_configured;
+ // /// the SIB2 parameters for eMTC SIB2
+ // ccparams_lte_t ccparams;
+ // int            si_Narrowband_r13;
+ // int            si_TBS_r13;
+ // int            systemInfoValueTagSi_r13;
+ // int            firstPreamble_r13;
+ // int            lastPreamble_r13;
+ // int            ra_ResponseWindowSize_r13;
+ // int            mac_ContentionResolutionTimer_r13;
+ // int            rar_HoppingConfig_r13;
+ // int            rsrp_range_br;
+ // int            prach_config_index_br;
+ // int            prach_freq_offset_br;
+ // int            prach_StartingSubframe_r13;
+ // int            maxNumPreambleAttemptCE_r13;
+ // int            numRepetitionPerPreambleAttempt_r13;
+ // int            mpdcch_NumRepetition_RA_r13;
+ // int            prach_HoppingConfig_r13;
+ // int           *maxavailablenarrowband;
+ // int            pucch_info_value;
+ // int            paging_narrowbands_r13;
+ // int            mpdcch_numrepetition_paging_r13;
+ // int            nb_v1310;
+ // char          *pucch_NumRepetitionCE_Msg4_Level0_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level1_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level2_r13;
+ // char          *pucch_NumRepetitionCE_Msg4_Level3_r13;
+ // int            sib2_mpdcch_pdsch_hoppingNB_r13;
+ // char          *sib2_interval_DLHoppingConfigCommonModeA_r13;
+ // int            sib2_interval_DLHoppingConfigCommonModeA_r13_val;
+ // char          *sib2_interval_DLHoppingConfigCommonModeB_r13;
+ // int            sib2_interval_DLHoppingConfigCommonModeB_r13_val;
+ // char          *sib2_interval_ULHoppingConfigCommonModeA_r13;
+ // int            sib2_interval_ULHoppingConfigCommonModeA_r13_val;
+ // char          *sib2_interval_ULHoppingConfigCommonModeB_r13;
+ // int            sib2_interval_ULHoppingConfigCommonModeB_r13_val;
+ // int            sib2_mpdcch_pdsch_hoppingOffset_r13;
+ // int            pusch_HoppingOffset_v1310;
+ // int            hyperSFN_r13;
+ // int            eDRX_Allowed_r13;
+ // int            q_RxLevMinCE_r13;
+ // int            q_QualMinRSRQ_CE_r13;
+ // char          *si_WindowLength_BR_r13;
+ // char          *si_RepetitionPattern_r13;
+ // int            startSymbolBR_r13;
+ // char          *si_HoppingConfigCommon_r13;
+ // char          *si_ValidityTime_r13;
+ // char          *mpdcch_pdsch_HoppingNB_r13;
+ // int            interval_DLHoppingConfigCommonModeA_r13_val;
+ // int            interval_DLHoppingConfigCommonModeB_r13_val;
+ // int            mpdcch_pdsch_HoppingOffset_r13;
+ // char          *preambleTransMax_CE_r13;
+ // int            prach_HoppingOffset_r13;
+ // int            schedulingInfoSIB1_BR_r13;
+ // int64_t        fdd_DownlinkOrTddSubframeBitmapBR_val_r13;
+ // char          *cellSelectionInfoCE_r13;
+ // char          *bandwidthReducedAccessRelatedInfo_r13;
+ // char          *fdd_DownlinkOrTddSubframeBitmapBR_r13;
+ // char          *fdd_UplinkSubframeBitmapBR_r13;
+ // char          *freqHoppingParametersDL_r13;
+ // char          *interval_DLHoppingConfigCommonModeA_r13;
+ // char          *interval_DLHoppingConfigCommonModeB_r13;
+ // char          *prach_ConfigCommon_v1310;
+ // char          *mpdcch_startSF_CSS_RA_r13;
+ // char          *mpdcch_startSF_CSS_RA_r13_val;
+ // char          *pdsch_maxNumRepetitionCEmodeA_r13;
+ // char          *pdsch_maxNumRepetitionCEmodeB_r13;
+ // char          *pusch_maxNumRepetitionCEmodeA_r13;
+ // char          *pusch_maxNumRepetitionCEmodeB_r13;
+} ccparams_MME_t;
+
+
+#define MMEPARAMS_DESC(MMEconfig) {					\
+  {"MME_configured",                                              NULL,   0,           iptr:&MMEconfig->MME_configured,                             defintval:0,                       TYPE_UINT,         0} \
+}
+
+#define MMEPARAMS_CHECK                 {                                     \
+             { .s5= {NULL }}						     \
+}
+
diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c
new file mode 100644
index 00000000000..534aec8b34d
--- /dev/null
+++ b/openair3/MME_APP/mme_app.c
@@ -0,0 +1,580 @@
+/*
+ * 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
+ */
+
+/*
+                                mme_app.c
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "mme_app.h"
+#include "mme_config.h"
+#include "assertions.h"
+#include "common/ran_context.h"
+#include "targets/RT/USER/lte-softmodem.h"
+
+#include "common/utils/LOG/log.h"
+
+# include "intertask_interface.h"
+#   include "s1ap_eNB.h"
+#   include "sctp_eNB_task.h"
+#   include "gtpv1u_eNB_task.h"
+#   include "flexran_agent.h"
+
+#   include "x2ap_eNB.h"
+#   include "x2ap_messages_types.h"
+#   include "m2ap_eNB.h"
+#   include "m3ap_MME.h"
+#   include "m2ap_messages_types.h"
+//#   include "m3ap_eNB.h"
+#   include "m3ap_messages_types.h"
+#   define X2AP_ENB_REGISTER_RETRY_DELAY   10
+
+#include "openair1/PHY/INIT/phy_init.h"
+extern unsigned char NB_MCE_INST;
+
+extern RAN_CONTEXT_t RC;
+
+#   define MCE_REGISTER_RETRY_DELAY 10
+
+#include "targets/RT/USER/lte-softmodem.h"
+
+
+
+
+/*------------------------------------------------------------------------------*/
+
+//static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_pending = 0;
+//
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//      // M3AP registration
+//        /* note:  there is an implicit relationship between the data structure and the message name */
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_REGISTER_MCE_REQ);
+//        //RCconfig_S1(msg_p, mce_id);
+//
+//        //if (mce_id == 0) 
+//		//RCconfig_gtpu();
+//
+//        //LOG_I(MME_APP,"default drx %d\n",((M3AP_REGISTER_MCE_REQ(msg_p)).default_drx));
+//
+//        LOG_I(ENB_APP,"[MCE %d] MCE_app_register via M3AP for instance %d\n", mce_id, ENB_MODULE_ID_TO_INSTANCE(mce_id));
+//        itti_send_msg_to_task (TASK_M3AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//
+//      //if (NODE_IS_DU(node_type)) { // F1AP registration
+//      //  // configure F1AP here for F1C
+//      //  LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n");
+//      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ);
+//      //  RCconfig_DU_F1(msg_p, enb_id);
+//
+//      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+//      //  itti_send_msg_to_task (TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+//      //  // configure GTPu here for F1U
+//      //}
+//      //else { // S1AP registration
+//      //  /* note:  there is an implicit relationship between the data structure and the message name */
+//      //  msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ);
+//      //  RCconfig_S1(msg_p, enb_id);
+//
+//      //  if (enb_id == 0) RCconfig_gtpu();
+//
+//      //  LOG_I(ENB_APP,"default drx %d\n",((S1AP_REGISTER_ENB_REQ(msg_p)).default_drx));
+//
+//      //  LOG_I(ENB_APP,"[eNB %d] eNB_app_register via S1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
+//      //  itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
+//      //}
+//
+//      register_mce_pending++;
+//    }
+//  }
+//
+//  return register_mce_pending;
+//}
+
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_x2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//      msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
+//      RCconfig_X2(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//      register_mce_x2_pending++;
+//    }
+//  }
+//
+//  return register_mce_x2_pending;
+//}
+
+/*------------------------------------------------------------------------------*/
+//static uint32_t MCE_app_register_m2(uint32_t mce_id_start, uint32_t mce_id_end) {
+//  uint32_t         mce_id;
+//  MessageDef      *msg_p;
+//  uint32_t         register_mce_m2_pending = 0;
+//
+//  LOG_W(MME_APP,"Register ...");
+//  for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) {
+//    {
+//  //	LOG_W(MME_APP,"Register commes inside ...\n");
+//      msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_REGISTER_MCE_REQ);
+//      //RCconfig_M2_MCE(msg_p, mce_id);
+//      itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p);
+//  //	LOG_W(MME_APP,"Register sent ...\n");
+//      register_mce_m2_pending++;
+//    }
+//  }
+//
+//  return register_mce_m2_pending;
+//}
+//
+//
+//
+static uint32_t MME_app_handle_m3ap_setup_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_SETUP_RESP);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+static uint32_t MME_app_handle_m3ap_session_start_resp(instance_t instance){
+	
+  
+	return 0;
+}
+//
+//static uint32_t MME_app_handle_m3ap_session_stop_resp(instance_t instance){
+//	
+//  
+//	return 0;
+//}
+
+
+
+//
+//static uint32_t MCE_app_send_m2ap_mbms_scheduling_information(instance_t instance){
+//	
+//  	uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_MBMS_SCHEDULING_INFORMATION);
+//        itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+//
+static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_START_REQ);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+//static uint32_t MME_app_send_m3ap_session_stop_req(instance_t instance){
+//	
+//  	//uint32_t         mce_id=0;
+//  	MessageDef      *msg_p;
+//        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_STOP_REQ);
+//        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+//	
+//	return 0;
+//}
+static uint32_t MME_app_send_m3ap_session_update_req(instance_t instance){
+	
+  	//uint32_t         mce_id=0;
+  	MessageDef      *msg_p;
+        msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_UPDATE_REQ);
+        itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p);
+	
+	return 0;
+}
+/*------------------------------------------------------------------------------*/
+void *MME_app_task(void *args_p) {
+  //uint32_t                        mce_nb = RC.nb_inst; 
+  //uint32_t                        mce_id_start = 0;
+  //uint32_t                        mce_id_end = mce_id_start + mce_nb;
+  //uint32_t                        register_mce_pending=0;
+  //uint32_t                        registered_mce=0;
+  //long                            mce_register_retry_timer_id;
+  //uint32_t                        m2_register_mce_pending = 0;
+ // uint32_t                        x2_registered_mce = 0;
+ // long                            x2_mce_register_retry_timer_id;
+ // uint32_t                        m2_register_mce_pending = 0;
+ // uint32_t                        m2_registered_mce = 0;
+ // long                            m2_mce_register_retry_timer_id;
+  long                            m3_mme_register_session_start_timer_id;
+  MessageDef                     *msg_p           = NULL;
+  instance_t                      instance;
+  int                             result;
+  /* for no gcc warnings */
+  (void)instance;
+  itti_mark_task_ready (TASK_MME_APP);
+
+  /* Try to register each MCE */
+  // This assumes that node_type of all RRC instances is the same
+  if (EPC_MODE_ENABLED) {
+    //register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+  }
+
+    /* Try to register each MCE with each other */
+ // if (is_x2ap_enabled() && !NODE_IS_DU(RC.rrc[0]->node_type)) {
+ //   x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ // }
+  if ( is_m3ap_MME_enabled() ){
+ 	RCconfig_MME();
+  }
+ // /* Try to register each MCE with MCE each other */
+ //if (is_m3ap_MME_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) {
+   //m2_register_mce_pending = MCE_app_register_m2 (mce_id_start, mce_id_end);
+ //}
+
+  do {
+    // Wait for a message
+    itti_receive_msg (TASK_MME_APP, &msg_p);
+    instance = ITTI_MSG_INSTANCE (msg_p);
+
+    switch (ITTI_MSG_ID(msg_p)) {
+    case TERMINATE_MESSAGE:
+      LOG_W(MME_APP, " *** Exiting MME_APP thread\n");
+      itti_exit_task ();
+      break;
+
+    case MESSAGE_TEST:
+      LOG_I(MME_APP, "MME_APP Received %s\n", ITTI_MSG_NAME(msg_p));
+      break;
+
+    case SOFT_RESTART_MESSAGE:
+      //handle_reconfiguration(instance);
+      break;
+
+    case M3AP_REGISTER_MCE_CNF: //M3AP_REGISTER_MCE_CNF debería
+      //AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n");
+       // if (EPC_MODE_ENABLED) {
+       //   LOG_I(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+       //         M3AP_REGISTER_MCE_CNF(msg_p).nb_mme);
+       //   DevAssert(register_mce_pending > 0);
+       //   register_mce_pending--;
+
+       //   /* Check if at least MCE is registered with one MME */
+       //   if (M3AP_REGISTER_MCE_CNF(msg_p).nb_mme > 0) {
+       //     registered_mce++;
+       //   }
+
+       //   /* Check if all register MCE requests have been processed */
+       //   if (register_mce_pending == 0) {
+       //     if (registered_mce == mce_nb) {
+       //       /* If all MCE are registered, start L2L1 task */
+       //      // MessageDef *msg_init_p;
+       //      // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
+       //      // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+       //     } else {
+       //       LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+       //             mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+       //       /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+       //       if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+       //                        NULL, &mce_register_retry_timer_id) < 0) {
+       //         LOG_E(MME_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+       //         sleep(MCE_REGISTER_RETRY_DELAY);
+       //         /* Restart the registration process */
+       //         registered_mce = 0;
+       //         register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);
+       //       }
+       //     }
+       //   }
+       // } /* if (EPC_MODE_ENABLED) */
+
+      break;
+
+   // case M3AP_SETUP_RESP:
+   //   //AssertFatal(NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received F1AP_REGISTER_ENB_CNF in CU/MCE\n");
+
+   //   //LOG_I(MME_APP, "Received %s: associated ngran_MCE_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p),
+   //         //F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate);
+   //   
+   //   //handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p));
+   //   handle_m3ap_setup_resp(&M3AP_SETUP_RESP(msg_p));
+
+   //   DevAssert(register_mce_pending > 0);
+   //   register_mce_pending--;
+
+   //   /* Check if at least MCE is registered with one MME */
+   //   //if (M3AP_SETUP_RESP(msg_p).num_cells_to_activate > 0) {
+   //   //  registered_enb++;
+   //   //}
+
+   //   /* Check if all register MCE requests have been processed */
+   //   if (register_mce_pending == 0) {
+   //     if (registered_mce == mce_nb) {
+   //       /* If all MCE cells are registered, start L2L1 task */
+   //       MessageDef *msg_init_p;
+
+   //       //msg_init_p = itti_alloc_new_message (TASK_MME_APP, INITIALIZE_MESSAGE);
+   //       //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
+
+   //     } else {
+   //       LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n",
+   //             mce_nb - registered_mce,  MCE_REGISTER_RETRY_DELAY);
+
+   //       /* Restart the MCE registration process in MCE_REGISTER_RETRY_DELAY seconds */
+   //       if (timer_setup (MCE_REGISTER_RETRY_DELAY, 0, TASK_MME_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
+   //                        NULL, &mce_register_retry_timer_id) < 0) {
+   //         LOG_E(ENB_APP, " Can not start MCE register retry timer, use \"sleep\" instead!\n");
+
+   //         sleep(MCE_REGISTER_RETRY_DELAY);
+   //         /* Restart the registration process */
+   //         registered_mce = 0;
+   //         register_mce_pending = MCE_app_register (RC.rrc[0]->node_type,mce_id_start, mce_id_end);//, enb_properties_p);
+   //       }
+   //     }
+   //   }
+
+   //   break;
+
+    case M3AP_DEREGISTERED_MCE_IND: //M3AP_DEREGISTERED_MCE_IND debería
+      if (EPC_MODE_ENABLED) {
+  	LOG_W(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
+  	      M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme);
+  	/* TODO handle recovering of registration */
+      }
+
+      break;
+
+    case TIMER_HAS_EXPIRED:
+        //if (EPC_MODE_ENABLED) {
+	//      LOG_I(MME_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
+
+	//      if (TIMER_HAS_EXPIRED (msg_p).timer_id == mce_register_retry_timer_id) {
+	//	/* Restart the registration process */
+	//	registered_mce = 0;
+	//	//register_mce_pending = MCE_app_register (RC.rrc[0]->node_type, mce_id_start, mce_id_end);
+	//      }
+
+	//      //if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_mce_register_retry_timer_id) {
+	//      //  /* Restart the registration process */
+	//      //  x2_registered_mce = 0;
+	//      //  x2_register_mce_pending = MCE_app_register_x2 (mce_id_start, mce_id_end);
+	//      //}
+        //} /* if (EPC_MODE_ENABLED) */
+	if(TIMER_HAS_EXPIRED(msg_p).timer_id == m3_mme_register_session_start_timer_id){
+		MME_app_send_m3ap_session_start_req(0);
+	}
+
+      break;
+
+ //   case X2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case X2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
+ //     DevAssert(x2_register_enb_pending > 0);
+ //     x2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
+ //       x2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (x2_register_enb_pending == 0) {
+ //       if (x2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t x2_not_associated = enb_nb - x2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               x2_not_associated, x2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //       		   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //       		   &x2_enb_register_retry_timer_id) < 0) {
+ //           LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //           sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //           /* Restart the registration process */
+ //           x2_registered_enb = 0;
+ //           x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         }
+ //       }
+ //     }
+
+ //     break;
+
+ //   case M2AP_DEREGISTERED_ENB_IND:
+ //     LOG_W(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2);
+ //     /* TODO handle recovering of registration */
+ //     break;
+
+ //   case M2AP_REGISTER_ENB_CNF:
+ //     LOG_I(ENB_APP, "[MCE %d] Received %s: associated MCE %d\n", instance, ITTI_MSG_NAME (msg_p),
+ //           M2AP_REGISTER_ENB_CNF(msg_p).nb_m2);
+ //     DevAssert(m2_register_enb_pending > 0);
+ //     m2_register_enb_pending--;
+
+ //     /* Check if at least MCE is registered with one target MCE */
+ //     if (M2AP_REGISTER_ENB_CNF(msg_p).nb_m2 > 0) {
+ //       m2_registered_enb++;
+ //     }
+
+ //     /* Check if all register MCE requests have been processed */
+ //     if (m2_register_enb_pending == 0) {
+ //       if (m2_registered_enb == enb_nb) {
+ //         /* If all MCE are registered, start RRC HO task */
+ //         } else {
+ //         uint32_t m2_not_associated = enb_nb - m2_registered_enb;
+ //         LOG_W(ENB_APP, " %d MCE %s not associated with the target\n",
+ //               m2_not_associated, m2_not_associated > 1 ? "are" : "is");
+
+ //         // timer to retry
+ //         /* Restart the MCE registration process in ENB_REGISTER_RETRY_DELAY seconds */
+ //         //if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
+ //         //      	   INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
+ //         //      	   &x2_enb_register_retry_timer_id) < 0) {
+ //         //  LOG_E(ENB_APP, " Can not start MCE X2AP register: retry timer, use \"sleep\" instead!\n");
+ //         //  sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
+ //         //  /* Restart the registration process */
+ //         //  x2_registered_enb = 0;
+ //         //  x2_register_enb_pending = MCE_app_register_x2 (enb_id_start, enb_id_end);
+ //         //}
+ //       }
+ //     }
+
+ //     break;
+	case M3AP_RESET:
+	LOG_I(MME_APP,"Received M3AP_RESET message %s\n",ITTI_MSG_NAME(msg_p));	
+	break;
+
+	case M3AP_SETUP_REQ:
+	LOG_I(MME_APP,"Received M3AP_REQ message %s\n",ITTI_MSG_NAME(msg_p));	
+	MME_app_handle_m3ap_setup_req(0);
+	if(timer_setup(1,0,TASK_MME_APP,INSTANCE_DEFAULT,TIMER_ONE_SHOT,NULL,&m3_mme_register_session_start_timer_id)<0){
+	}
+	//MME_app_send_m3ap_session_start_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_START_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_START_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	MME_app_handle_m3ap_session_start_resp(0);
+	//MME_app_send_m3ap_session_stop_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_STOP_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_STOP_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	MME_app_send_m3ap_session_update_req(0);
+	break;
+
+	case M3AP_MBMS_SESSION_UPDATE_RESP:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_UPDATE_RESP message %s\n",ITTI_MSG_NAME(msg_p));
+	// trigger something new here !!!!!!
+	break;
+ 
+	case M3AP_MBMS_SESSION_UPDATE_FAILURE:
+	LOG_I(MME_APP,"Received M3AP_MBMS_SESSION_UPDATE_FAILURE message %s\n",ITTI_MSG_NAME(msg_p));	
+	break;
+ 
+	case M3AP_MCE_CONFIGURATION_UPDATE:
+	LOG_I(MME_APP,"Received M3AP_MCE_CONFIGURATION_UPDATE message %s\n",ITTI_MSG_NAME(msg_p)); 	   
+	break;
+ 
+    default:
+      LOG_E(MME_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+      break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+  } while (1);
+
+  return NULL;
+}
+
+//void handle_reconfiguration(module_id_t mod_id) {
+//  struct timespec start, end;
+//  clock_gettime(CLOCK_MONOTONIC, &start);
+//  flexran_agent_info_t *flexran = RC.flexran[mod_id];
+//  LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
+//
+//  if (ENB_WAIT == flexran->node_ctrl_state) {
+//    /* this is already waiting, just release */
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//    pthread_cond_signal(&flexran->cond_node_ctrl);
+//    return;
+//  }
+//
+//  if (stop_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
+//    return;
+//  }
+//
+//  /* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
+//   * executed by the FlexRAN thread */
+//  if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
+//    LOG_I(ENB_APP, " * MCE %d: Waiting for FlexRAN RTController command *\n", mod_id);
+//    pthread_mutex_lock(&flexran->mutex_node_ctrl);
+//    flexran->node_ctrl_state = ENB_WAIT;
+//
+//    while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
+//      pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
+//
+//    pthread_mutex_unlock(&flexran->mutex_node_ctrl);
+//  }
+//
+//  if (restart_L1L2(mod_id) < 0) {
+//    LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
+//    exit_fun("can not restart L1L2, killing lte-softmodem");
+//    return;
+//  }
+//
+//  clock_gettime(CLOCK_MONOTONIC, &end);
+//  end.tv_sec -= start.tv_sec;
+//
+//  if (end.tv_nsec >= start.tv_nsec) {
+//    end.tv_nsec -= start.tv_nsec;
+//  } else {
+//    end.tv_sec -= 1;
+//    end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
+//  }
+//
+//  LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
+//}
+
+
diff --git a/openair3/MME_APP/mme_app.h b/openair3/MME_APP/mme_app.h
new file mode 100644
index 00000000000..796bfa796c2
--- /dev/null
+++ b/openair3/MME_APP/mme_app.h
@@ -0,0 +1,41 @@
+/*
+ * 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
+ */
+
+/*
+                                mme_app.h
+                             -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MME_APP_H_
+#define MME_APP_H_
+
+#include <stdint.h>
+#include "platform_types.h"
+
+
+void *MME_app_task(void *args_p);
+
+//void handle_reconfiguration(module_id_t mod_id);
+
+#endif /* MME_APP_H_ */
diff --git a/openair3/MME_APP/mme_config.c b/openair3/MME_APP/mme_config.c
new file mode 100644
index 00000000000..04dba675675
--- /dev/null
+++ b/openair3/MME_APP/mme_config.c
@@ -0,0 +1,111 @@
+/*
+ * 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
+ */
+
+/*
+  mme_config.c
+  -------------------
+  AUTHOR  : Javier Morgade
+  COMPANY : VICOMTECH, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "common/utils/LOG/log.h"
+#include "assertions.h"
+#include "mme_config.h"
+#include "UTIL/OTG/otg.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "intertask_interface.h"
+#include "s1ap_eNB.h"
+#include "sctp_eNB_task.h"
+#include "common/ran_context.h"
+#include "sctp_default_values.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "PHY/phy_extern.h"
+#include "PHY/INIT/phy_init.h"
+#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
+#include "nfapi_vnf.h"
+#include "nfapi_pnf.h"
+
+#include "L1_paramdef.h"
+#include "MACRLC_paramdef.h"
+#include "common/config/config_userapi.h"
+#include "RRC_config_tools.h"
+#include "enb_paramdef.h"
+#include "proto_agent.h"
+
+int RCconfig_MME(void ) {
+  //int               num_enbs                      = 0;
+  //char             *enb_interface_name_for_S1U    = NULL;
+  char               *mme_interface_name_for_m3_mce = NULL;
+  //char             *enb_ipv4_address_for_S1U      = NULL;
+  char               *mme_ipv4_address_for_m3c      = NULL;
+  //uint32_t          enb_port_for_S1U              = 0;
+  uint32_t            mme_port_for_m3c              = 0;
+  char             *address                       = NULL;
+  char             *cidr                          = NULL;
+  //char gtpupath[MAX_OPTNAME_SIZE*2 + 8];
+  char mmepath[MAX_OPTNAME_SIZE*2 + 8];
+  //paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
+  //paramdef_t GTPUParams[]  = GTPUPARAMS_DESC;
+
+  paramdef_t   MMEParams[] = MME_NETPARAMS_DESC;
+
+  ///* get number of active eNodeBs */
+  //config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
+  //num_enbs = ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt;
+  //AssertFatal (num_enbs >0,
+  //             "Failed to parse config file no active eNodeBs in %s \n", ENB_CONFIG_STRING_ACTIVE_ENBS);
+  //sprintf(gtpupath,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,0,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  sprintf(mmepath,"%s.[%i].%s","MMEs",0,MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
+  //config_get( GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath);
+  config_get(MMEParams,sizeof(MMEParams)/sizeof(paramdef_t),mmepath);
+  //cidr = enb_ipv4_address_for_S1U;
+  cidr = mme_ipv4_address_for_m3c;
+  address = strtok(cidr, "/");
+
+  //LOG_W(MME_APP,"cidr %s\n",cidr);
+  //LOG_W(MME_APP,"address %s\n",address);
+  //LOG_W(MME_APP,"mme_interface_name_for_m3_mce %s\n",mme_interface_name_for_m3_mce);
+  //LOG_W(MME_APP,"mme_ipv4_address_for_m3c %s\n",mme_ipv4_address_for_m3c);
+  //LOG_W(MME_APP,"mme_port_for_m3c %d\n",mme_port_for_m3c);
+
+  if (address) {
+    MessageDef *message;
+    AssertFatal((message = itti_alloc_new_message(TASK_MME_APP, M3AP_MME_SCTP_REQ))!=NULL,"");
+    M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv6 = 0;
+    M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4 = 1;
+    strcpy( M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4_address, address);
+    LOG_I(MME_APP,"Configuring M3_C address : %s\n",address/*,M3AP_MME_SCTP_REQ(message).mme_m3_ip_address*/);
+    M3AP_MME_SCTP_REQ(message).mme_port_for_M3C = mme_port_for_m3c;
+    itti_send_msg_to_task (TASK_M3AP_MME, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
+  } else
+    LOG_E(MCE_APP,"invalid address for M2AP\n");
+
+
+
+  return 0;
+}
+
diff --git a/openair3/MME_APP/mme_config.h b/openair3/MME_APP/mme_config.h
new file mode 100644
index 00000000000..97b2fae0324
--- /dev/null
+++ b/openair3/MME_APP/mme_config.h
@@ -0,0 +1,52 @@
+/*
+ * 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
+ */
+
+/*
+  mme_config.h
+  AUTHOR  : Javier Morgade
+  COMPANY : Vicomtech, Spain
+  EMAIL   : javier.morgade@ieee.org
+*/
+
+#ifndef MME_CONFIG_H_
+#define MME_CONFIG_H_
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libconfig.h>
+
+#include "commonDef.h"
+#include "platform_types.h"
+#include "platform_constants.h"
+#include "PHY/impl_defs_lte.h"
+#include "PHY/defs_eNB.h"
+#include "s1ap_messages_types.h"
+#include "f1ap_messages_types.h"
+#include "LTE_SystemInformationBlockType2.h"
+#include "rrc_messages_types.h"
+#include "RRC/LTE/rrc_defs.h"
+#include <intertask_interface.h>
+#include "enb_paramdef.h"
+
+int RCconfig_MME(void);
+
+#endif /* MME_CONFIG_H_ */
+/** @} */
-- 
GitLab