diff --git a/openair-cn/COMMON/nas_messages_types.h b/openair-cn/COMMON/nas_messages_types.h
index bebe11d76cdd7a26cdd859d1a2a4d6eb802cfd7c..87fc37dc0d8a4215eb141605ee0751de642b9650 100644
--- a/openair-cn/COMMON/nas_messages_types.h
+++ b/openair-cn/COMMON/nas_messages_types.h
@@ -3,16 +3,16 @@
 #ifndef NAS_MESSAGES_TYPES_H_
 #define NAS_MESSAGES_TYPES_H_
 
-#define NAS_UL_DATA_IND(mSGpTR)                 (mSGpTR)->ittiMsg.nas_ul_data_ind
-#define NAS_DL_DATA_REQ(mSGpTR)                 (mSGpTR)->ittiMsg.nas_dl_data_req
-#define NAS_DL_DATA_CNF(mSGpTR)                 (mSGpTR)->ittiMsg.nas_dl_data_cnf
-#define NAS_CONN_EST_IND(mSGpTR)                (mSGpTR)->ittiMsg.nas_conn_est_ind
-#define NAS_CONN_EST_CNF(mSGpTR)                (mSGpTR)->ittiMsg.nas_conn_est_cnf
-#define NAS_BEARER_PARAM(mSGpTR)                (mSGpTR)->ittiMsg.nas_bearer_param
-#define NAS_AUTHENTICATION_REQ(mSGpTR)          (mSGpTR)->ittiMsg.nas_auth_req
-#define NAS_AUTHENTICATION_PARAM_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_auth_param_req
-#define NAS_AUTHENTICATION_PARAM_RSP(mSGpTR)    (mSGpTR)->ittiMsg.nas_auth_param_rsp
-#define NAS_AUTHENTICATION_PARAM_FAIL(mSGpTR)   (mSGpTR)->ittiMsg.nas_auth_param_fail
+#define NAS_UL_DATA_IND(mSGpTR)                  (mSGpTR)->ittiMsg.nas_ul_data_ind
+#define NAS_DL_DATA_REQ(mSGpTR)                  (mSGpTR)->ittiMsg.nas_dl_data_req
+#define NAS_DL_DATA_CNF(mSGpTR)                  (mSGpTR)->ittiMsg.nas_dl_data_cnf
+#define NAS_CONN_EST_IND(mSGpTR)                 (mSGpTR)->ittiMsg.nas_conn_est_ind
+#define NAS_CONNECTION_ESTABLISHMENT_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_est_cnf
+#define NAS_BEARER_PARAM(mSGpTR)                 (mSGpTR)->ittiMsg.nas_bearer_param
+#define NAS_AUTHENTICATION_REQ(mSGpTR)           (mSGpTR)->ittiMsg.nas_auth_req
+#define NAS_AUTHENTICATION_PARAM_REQ(mSGpTR)     (mSGpTR)->ittiMsg.nas_auth_param_req
+#define NAS_AUTHENTICATION_PARAM_RSP(mSGpTR)     (mSGpTR)->ittiMsg.nas_auth_param_rsp
+#define NAS_AUTHENTICATION_PARAM_FAIL(mSGpTR)    (mSGpTR)->ittiMsg.nas_auth_param_fail
 
 typedef struct nas_paging_ind_s {
     
@@ -29,6 +29,7 @@ typedef struct nas_conn_est_ind_s {
 
 typedef nas_establish_rsp_t nas_conn_est_rej_t;
 
+#if defined(DISABLE_USE_NAS)
 typedef struct nas_conn_est_cnf_s {
     uint32_t ue_id;
 
@@ -36,6 +37,9 @@ typedef struct nas_conn_est_cnf_s {
     /* Transparent message from MME_APP to S1AP */
     s1ap_initial_ctxt_setup_req_t transparent;
 } nas_conn_est_cnf_t;
+#else
+typedef nas_establish_cnf_t nas_conn_est_cnf_t;
+#endif
 
 typedef struct nas_bearer_param_s {
     unsigned eNB_ue_s1ap_id:24;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
index 200e07551c57dcda846a56f2fdf17f30e7c66d8e..b5e4f79bff087ba24c438476c6a0fce49c3ff04f 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
@@ -1117,6 +1117,7 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
         (*emm_ctx)->esm_msg.value = NULL;
         (*emm_ctx)->emm_cause = EMM_CAUSE_SUCCESS;
         (*emm_ctx)->_emm_fsm_status = EMM_INVALID;
+        (*emm_ctx)->ueid = ueid;
 
         emm_fsm_set_status(ueid, *emm_ctx, EMM_DEREGISTERED);
 #if defined(EPC_BUILD)
@@ -1130,7 +1131,6 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
     if (rc != RETURNok) {
         LOG_TRACE(WARNING, "EMM-PROC  - Failed to update EMM context");
         /* Do not accept the UE to attach to the network */
-        (*emm_ctx)->ueid = ueid;
         (*emm_ctx)->emm_cause = EMM_CAUSE_ILLEGAL_UE;
         rc = _emm_attach_reject(*emm_ctx);
     } else {
@@ -1216,12 +1216,13 @@ int emm_proc_attach_reject(unsigned int ueid, int emm_cause)
  ***************************************************************************/
 int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg)
 {
-    LOG_FUNC_IN;
-
+    emm_data_context_t *emm_ctx = NULL;
     int rc = RETURNerror;
     emm_sap_t emm_sap;
     esm_sap_t esm_sap;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO, "EMM-PROC  - EPS attach complete (ueid=%u)", ueid);
 
     /* Stop timer T3450 */
@@ -1238,7 +1239,6 @@ int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg)
     }
 
     /* Get the UE context */
-    emm_data_context_t *emm_ctx = NULL;
 
 #if defined(EPC_BUILD)
     if (ueid > 0) {
@@ -1263,6 +1263,7 @@ int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg)
         esm_sap.is_standalone = FALSE;
         esm_sap.ueid = ueid;
         esm_sap.recv = esm_msg;
+        esm_sap.ctx  = emm_ctx;
         rc = esm_sap_send(&esm_sap);
     } else {
         LOG_TRACE(ERROR, "EMM-PROC  - No EMM context exists");
@@ -1276,6 +1277,7 @@ int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg)
          */
         emm_sap.primitive = EMMREG_ATTACH_CNF;
         emm_sap.u.emm_reg.ueid = ueid;
+        emm_sap.u.emm_reg.ctx  = emm_ctx;
         rc = emm_sap_send(&emm_sap);
     } else if (esm_sap.err != ESM_SAP_DISCARDED) {
         /*
@@ -1283,6 +1285,7 @@ int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg)
          */
         emm_sap.primitive = EMMREG_ATTACH_REJ;
         emm_sap.u.emm_reg.ueid = ueid;
+        emm_sap.u.emm_reg.ctx  = emm_ctx;
         rc = emm_sap_send(&emm_sap);
     } else {
         /*
@@ -1748,14 +1751,17 @@ static int _emm_attach_reject(void *args)
  ***************************************************************************/
 static int _emm_attach_abort(void *args)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
+    emm_data_context_t *ctx = NULL;
+    attach_data_t *data;
 
-    attach_data_t *data = (attach_data_t *)(args);
+    LOG_FUNC_IN;
+
+    data = (attach_data_t *)(args);
 
     if (data) {
         unsigned int ueid = data->ueid;
+        esm_sap_t esm_sap;
 
         LOG_TRACE(WARNING, "EMM-PROC  - Abort the attach procedure (ueid=%u)",
                   ueid);
@@ -1771,15 +1777,22 @@ static int _emm_attach_abort(void *args)
         }
         free(data);
 
+#if defined(EPC_BUILD)
+        ctx = emm_data_context_get(&_emm_data, ueid);
+#else
+        ctx = _emm_data.ctx[ueid];
+#endif
+
         /*
          * Notify ESM that the network locally refused PDN connectivity
          * to the UE
          */
-        esm_sap_t esm_sap;
         esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ;
         esm_sap.ueid = ueid;
+        esm_sap.ctx  = ctx;
         esm_sap.recv = NULL;
         rc = esm_sap_send(&esm_sap);
+
         if (rc != RETURNerror) {
             /*
              * Notify EMM that EPS attach procedure failed
@@ -1787,16 +1800,9 @@ static int _emm_attach_abort(void *args)
             emm_sap_t emm_sap;
             emm_sap.primitive = EMMREG_ATTACH_REJ;
             emm_sap.u.emm_reg.ueid = ueid;
+            emm_sap.u.emm_reg.ctx  = ctx;
             rc = emm_sap_send(&emm_sap);
             if (rc != RETURNerror) {
-                struct emm_data_context_s *ctx = NULL;
-
-#if defined(EPC_BUILD)
-                ctx = emm_data_context_get(&_emm_data, ueid);
-#else
-                ctx = _emm_data.ctx[ueid];
-#endif
-
                 /* Release the UE context */
                 rc = _emm_attach_release(ctx);
             }
@@ -2098,6 +2104,7 @@ static int _emm_attach(void *args)
     esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ;
     esm_sap.is_standalone = FALSE;
     esm_sap.ueid = emm_ctx->ueid;
+    esm_sap.ctx  = emm_ctx;
     esm_sap.recv = &emm_ctx->esm_msg;
     rc = esm_sap_send(&esm_sap);
 
@@ -2214,6 +2221,7 @@ static int _emm_attach_accept(emm_data_context_t *emm_ctx, attach_data_t *data)
      * Notify EMM-AS SAP that Attach Accept message together with an Activate
      * Default EPS Bearer Context Request message has to be sent to the UE
      */
+
     emm_sap.primitive = EMMAS_ESTABLISH_CNF;
     emm_sap.u.emm_as.u.establish.ueid = emm_ctx->ueid;
     if (emm_ctx->guti_is_new && emm_ctx->old_guti) {
@@ -2387,6 +2395,26 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
         } else {
             return (RETURNerror);
         }
+    } else {
+        if (ctx->guti == NULL) {
+            ctx->guti = (GUTI_t *)malloc(sizeof(GUTI_t));
+        }
+        if (ctx->guti != NULL) {
+            /* TODO: FIXME */
+            ctx->guti->gummei.plmn.MCCdigit1 = 2;
+            ctx->guti->gummei.plmn.MCCdigit2 = 0;
+            ctx->guti->gummei.plmn.MCCdigit3 = 8;
+            ctx->guti->gummei.plmn.MNCdigit1 = 9;
+            ctx->guti->gummei.plmn.MNCdigit2 = 2;
+            ctx->guti->gummei.plmn.MNCdigit3 = 15;
+
+            ctx->guti->gummei.MMEcode = 0;
+            ctx->guti->gummei.MMEgid  = 0;
+
+            ctx->guti->m_tmsi = (uint32_t) ctx;
+        } else {
+            return (RETURNerror);
+        }
     }
     /* The IMSI if provided by the UE */
     if (imsi) {
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Detach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Detach.c
index e3f18083888809f0af85c9946e1c5a7648329820..031f659fc9a405ea571c250dce994af497fd8182 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Detach.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Detach.c
@@ -512,6 +512,7 @@ int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
         esm_sap_t esm_sap;
         esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ;
         esm_sap.ueid = ueid;
+        esm_sap.ctx  = emm_ctx;
         esm_sap.data.eps_bearer_context_deactivate.ebi = ESM_SAP_ALL_EBI;
         rc = esm_sap_send(&esm_sap);
 
@@ -522,6 +523,7 @@ int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
              */
             emm_sap.primitive = EMMREG_DETACH_REQ;
             emm_sap.u.emm_reg.ueid = ueid;
+            emm_sap.u.emm_reg.ctx  = emm_ctx;
             rc = emm_sap_send(&emm_sap);
         }
     }
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c b/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
index 43049d4e94f57f5c70075cdb9056956164247872..1da179903c9773194c2e2b800d7ee32e4c137491 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
@@ -202,14 +202,26 @@ int lowerlayer_release(int cause)
  ***************************************************************************/
 int lowerlayer_data_ind(unsigned int ueid, const OctetString *data)
 {
-    LOG_FUNC_IN;
-
     esm_sap_t esm_sap;
     int rc;
+#if defined(NAS_MME)
+    emm_data_context_t *emm_ctx;
+#endif
+
+    LOG_FUNC_IN;
+
+#if defined(NAS_MME)
+    if (ueid > 0) {
+        emm_ctx = emm_data_context_get(&_emm_data, ueid);
+    }
+#endif
 
     esm_sap.primitive = ESM_UNITDATA_IND;
     esm_sap.is_standalone = TRUE;
     esm_sap.ueid = ueid;
+#if defined(NAS_MME)
+    esm_sap.ctx  = emm_ctx;
+#endif
     esm_sap.recv = data;
     rc = esm_sap_send(&esm_sap);
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
index 238e31c516381f9e6d1019794fdabff037a064bb..b2e59fe281613770d004192f519a10157fff3dbd 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
@@ -28,6 +28,8 @@ Description Defines internal private data handled by EPS Mobility
 #include "OctetString.h"
 #include "nas_timer.h"
 
+#include "esmData.h"
+
 #ifdef NAS_MME
 #include "emm_fsm.h"
 #include "mme_api.h"
@@ -348,6 +350,8 @@ typedef struct emm_data_context_s {
     int emm_cause;   /* EMM failure cause code               */
 
     emm_fsm_state_t _emm_fsm_status;
+
+    esm_data_context_t esm_data_ctx;
 } emm_data_context_t;
 
 /*
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
index 33519a2398366dbf8ede4fde169dbae15bc0743f..a108c8705dd01a68d30babaaebef947c0eb9d775 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
@@ -1092,7 +1092,7 @@ static int _emm_as_send(const emm_as_t *msg)
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
-            case AS_NAS_ESTABLISH_RSP: {
+            case AS_NAS_ESTABLISH_CNF: {
                 if (as_msg.msg.nas_establish_rsp.errCode != AS_SUCCESS) {
                     nas_itti_dl_data_req(as_msg.msg.nas_establish_rsp.UEid,
                                          as_msg.msg.nas_establish_rsp.nasMsg.data,
@@ -1100,6 +1100,11 @@ static int _emm_as_send(const emm_as_t *msg)
                     LOG_FUNC_RETURN (RETURNok);
                 } else {
                     /* Handle success case */
+                    nas_itti_establish_cnf(as_msg.msg.nas_establish_rsp.UEid,
+                                           as_msg.msg.nas_establish_rsp.errCode,
+                                           as_msg.msg.nas_establish_rsp.nasMsg.data,
+                                           as_msg.msg.nas_establish_rsp.nasMsg.length);
+                    LOG_FUNC_RETURN (RETURNok);
                 }
             } break;
 
@@ -1670,7 +1675,7 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
 
     LOG_FUNC_IN;
 
-    LOG_TRACE(INFO, "EMMAS-SAP - Send AS connection establish response");
+    LOG_TRACE(INFO, "EMMAS-SAP - Send AS connection establish confirmation");
 
     nas_message_t nas_msg;
     memset(&nas_msg, 0 , sizeof(nas_message_t));
@@ -1678,6 +1683,7 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
     /* Setup the AS message */
     as_msg->UEid = msg->ueid;
     if (msg->UEid.guti == NULL) {
+        LOG_TRACE(WARNING, "EMMAS-SAP - GUTI is NULL...");
         LOG_FUNC_RETURN (0);
     }
     as_msg->s_tmsi.MMEcode = msg->UEid.guti->gummei.MMEcode;
@@ -1703,9 +1709,11 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
         int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
         if (bytes > 0) {
             as_msg->errCode = AS_SUCCESS;
-            LOG_FUNC_RETURN (AS_NAS_ESTABLISH_RSP);
+            LOG_FUNC_RETURN (AS_NAS_ESTABLISH_CNF);
         }
     }
+
+    LOG_TRACE(WARNING, "EMMAS-SAP - Size <= 0");
     LOG_FUNC_RETURN (0);
 }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_esmDef.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_esmDef.h
index e90514d7593dfefd719654ace876ced923ede1e6..db8a80adc7bcf7e489c6daf1b4e4deee9e42f36a 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_esmDef.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_esmDef.h
@@ -24,6 +24,7 @@ Description Defines the EMMESM Service Access Point that provides
 #define __EMM_ESMDEF_H__
 
 #include "OctetString.h"
+#include "emmData.h"
 
 /****************************************************************************/
 /*********************  G L O B A L    C O N S T A N T S  *******************/
@@ -76,6 +77,9 @@ typedef struct {
 typedef struct {
     emm_esm_primitive_t primitive;
     unsigned int ueid;
+#if defined(NAS_MME)
+    emm_data_context_t *ctx;
+#endif
     union {
         emm_esm_establish_t establish;
         emm_esm_data_t data;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
index a6d814c2dcce7ba58ff06c286f84f20b1e923157..b4100f7c6224fa44fe47323f11d8923de64c0c2f 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
@@ -23,6 +23,7 @@ Description Defines the EMM Service Access Points at which the EPS
 #ifndef __EMM_SAP_H__
 #define __EMM_SAP_H__
 
+#include "emmData.h"
 #include "emm_regDef.h"
 #include "emm_esmDef.h"
 #include "emm_asDef.h"
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/DedicatedEpsBearerContextActivation.c b/openair-cn/NAS/EURECOM-NAS/src/esm/DedicatedEpsBearerContextActivation.c
index 920bc851e458deac43cfe15ec39500af5919b5c5..94aa8cc798891941936227c3f592294d5ec25926 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/DedicatedEpsBearerContextActivation.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/DedicatedEpsBearerContextActivation.c
@@ -65,7 +65,7 @@ static void *_dedicated_eps_bearer_activate_t3485_handler(void *);
  * retransmission counter */
 #define DEDICATED_EPS_BEARER_ACTIVATE_COUNTER_MAX   5
 
-static int _dedicated_eps_bearer_activate(unsigned int ueid, int ebi,
+static int _dedicated_eps_bearer_activate(emm_data_context_t *ctx, int ebi,
         const OctetString *msg);
 #endif // NAS_MME
 
@@ -102,7 +102,7 @@ static int _dedicated_eps_bearer_activate(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_dedicated_eps_bearer_context(unsigned int ueid, int pid,
+int esm_proc_dedicated_eps_bearer_context(emm_data_context_t *ctx, int pid,
         unsigned int *ebi,
         unsigned int *default_ebi,
         const esm_proc_qos_t *qos,
@@ -112,14 +112,14 @@ int esm_proc_dedicated_eps_bearer_context(unsigned int ueid, int pid,
     LOG_FUNC_IN;
 
     LOG_TRACE(INFO, "ESM-PROC  - Dedicated EPS bearer context activation "
-              "(ueid=%u, pid=%d)", ueid, pid);
+              "(ueid=%u, pid=%d)", ctx->ueid, pid);
 
     /* Assign new EPS bearer context */
-    *ebi = esm_ebr_assign(ueid, ESM_EBI_UNASSIGNED);
+    *ebi = esm_ebr_assign(ctx, ESM_EBI_UNASSIGNED);
 
     if (*ebi != ESM_EBI_UNASSIGNED) {
         /* Create dedicated EPS bearer context */
-        *default_ebi = esm_ebr_context_create(ueid, pid, *ebi, FALSE, qos, tft);
+        *default_ebi = esm_ebr_context_create(ctx, pid, *ebi, FALSE, qos, tft);
         if (*default_ebi == ESM_EBI_UNASSIGNED) {
             /* No resource available */
             LOG_TRACE(WARNING, "ESM-PROC  - Failed to create dedicated EPS "
@@ -162,7 +162,7 @@ int esm_proc_dedicated_eps_bearer_context(unsigned int ueid, int pid,
  **                                                                        **
  ***************************************************************************/
 int esm_proc_dedicated_eps_bearer_context_request(int is_standalone,
-        unsigned int ueid, int ebi,
+        emm_data_context_t *ctx, int ebi,
         OctetString *msg, int ue_triggered)
 {
     LOG_FUNC_IN;
@@ -170,15 +170,15 @@ int esm_proc_dedicated_eps_bearer_context_request(int is_standalone,
     int rc = RETURNok;
 
     LOG_TRACE(INFO,"ESM-PROC  - Initiate dedicated EPS bearer context "
-              "activation (ueid=%d, ebi=%d)", ueid, ebi);
+              "activation (ueid=%d, ebi=%d)", ctx->ueid, ebi);
 
     /* Send activate dedicated EPS bearer context request message and
      * start timer T3485 */
-    rc = _dedicated_eps_bearer_activate(ueid, ebi, msg);
+    rc = _dedicated_eps_bearer_activate(ctx, ebi, msg);
 
     if (rc != RETURNerror) {
         /* Set the EPS bearer context state to ACTIVE PENDING */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_ACTIVE_PENDING, ue_triggered);
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_ACTIVE_PENDING, ue_triggered);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in ACTIVE PENDING state */
             LOG_TRACE(WARNING, "ESM-PROC  - EBI %d was already ACTIVE PENDING",
@@ -211,7 +211,7 @@ int esm_proc_dedicated_eps_bearer_context_request(int is_standalone,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_dedicated_eps_bearer_context_accept(unsigned int ueid, int ebi,
+int esm_proc_dedicated_eps_bearer_context_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause)
 {
     LOG_FUNC_IN;
@@ -219,13 +219,13 @@ int esm_proc_dedicated_eps_bearer_context_accept(unsigned int ueid, int ebi,
     int rc;
 
     LOG_TRACE(INFO, "ESM-PROC  - Dedicated EPS bearer context activation "
-              "accepted by the UE (ueid=%u, ebi=%d)", ueid, ebi);
+              "accepted by the UE (ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     /* Stop T3485 timer */
-    rc = esm_ebr_stop_timer(ueid, ebi);
+    rc = esm_ebr_stop_timer(ctx, ebi);
     if (rc != RETURNerror) {
         /* Set the EPS bearer context state to ACTIVE */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_ACTIVE, FALSE);
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_ACTIVE, FALSE);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in ACTIVE state */
             LOG_TRACE(WARNING, "ESM-PROC  - EBI %d was already ACTIVE", ebi);
@@ -262,22 +262,22 @@ int esm_proc_dedicated_eps_bearer_context_accept(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_dedicated_eps_bearer_context_reject(unsigned int ueid, int ebi,
+int esm_proc_dedicated_eps_bearer_context_reject(emm_data_context_t *ctx, int ebi,
         int *esm_cause)
 {
-    LOG_FUNC_IN;
-
     int rc;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(WARNING, "ESM-PROC  - Dedicated EPS bearer context activation "
-              "not accepted by the UE (ueid=%u, ebi=%d)", ueid, ebi);
+              "not accepted by the UE (ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     /* Stop T3485 timer if running */
-    rc = esm_ebr_stop_timer(ueid, ebi);
+    rc = esm_ebr_stop_timer(ctx, ebi);
     if (rc != RETURNerror) {
         int pid, bid;
         /* Release the dedicated EPS bearer context and enter state INACTIVE */
-        rc = esm_proc_eps_bearer_context_deactivate(ueid, TRUE, ebi,
+        rc = esm_proc_eps_bearer_context_deactivate(ctx, TRUE, ebi,
                 &pid, &bid, NULL);
         if (rc != RETURNok) {
             /* Failed to release the dedicated EPS bearer context */
@@ -558,7 +558,7 @@ static void *_dedicated_eps_bearer_activate_t3485_handler(void *args)
     if (data->count < DEDICATED_EPS_BEARER_ACTIVATE_COUNTER_MAX) {
         /* Re-send activate dedicated EPS bearer context request message
          * to the UE */
-        rc = _dedicated_eps_bearer_activate(data->ueid, data->ebi, &data->msg);
+        rc = _dedicated_eps_bearer_activate(data->ctx, data->ebi, &data->msg);
     } else {
         /*
          * The maximum number of activate dedicated EPS bearer context request
@@ -566,12 +566,12 @@ static void *_dedicated_eps_bearer_activate_t3485_handler(void *args)
          */
         int pid, bid;
         /* Release the dedicated EPS bearer context and enter state INACTIVE */
-        rc = esm_proc_eps_bearer_context_deactivate(data->ueid, TRUE,
+        rc = esm_proc_eps_bearer_context_deactivate(data->ctx, TRUE,
                 data->ebi, &pid, &bid,
                 NULL);
         if (rc != RETURNerror) {
             /* Stop timer T3485 */
-            rc = esm_ebr_stop_timer(data->ueid, data->ebi);
+            rc = esm_ebr_stop_timer(data->ctx, data->ebi);
         }
     }
 
@@ -601,7 +601,7 @@ static void *_dedicated_eps_bearer_activate_t3485_handler(void *args)
  **      Others:    T3485                                      **
  **                                                                        **
  ***************************************************************************/
-static int _dedicated_eps_bearer_activate(unsigned int ueid, int ebi,
+static int _dedicated_eps_bearer_activate(emm_data_context_t *ctx, int ebi,
         const OctetString *msg)
 {
     LOG_FUNC_IN;
@@ -615,13 +615,14 @@ static int _dedicated_eps_bearer_activate(unsigned int ueid, int ebi,
      */
     emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data;
     emm_sap.primitive = EMMESM_UNITDATA_REQ;
-    emm_sap.u.emm_esm.ueid = ueid;
+    emm_sap.u.emm_esm.ueid = ctx->ueid;
+    emm_sap.u.emm_esm.ctx  = ctx;
     emm_esm->msg = *msg;
     rc = emm_sap_send(&emm_sap);
 
     if (rc != RETURNerror) {
         /* Start T3485 retransmission timer */
-        rc = esm_ebr_start_timer(ueid, ebi, msg, T3485_DEFAULT_VALUE,
+        rc = esm_ebr_start_timer(ctx, ebi, msg, T3485_DEFAULT_VALUE,
                                  _dedicated_eps_bearer_activate_t3485_handler);
     }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/DefaultEpsBearerContextActivation.c b/openair-cn/NAS/EURECOM-NAS/src/esm/DefaultEpsBearerContextActivation.c
index e0d305132bad10d8b03bc491f05931e3e9d53211..0b768da4b5ec760a16fd13a08592cfafea3fcba5 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/DefaultEpsBearerContextActivation.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/DefaultEpsBearerContextActivation.c
@@ -75,7 +75,7 @@ static void *_default_eps_bearer_activate_t3485_handler(void *);
  * retransmission counter */
 #define DEFAULT_EPS_BEARER_ACTIVATE_COUNTER_MAX 5
 
-static int _default_eps_bearer_activate(unsigned int ueid, int ebi,
+static int _default_eps_bearer_activate(emm_data_context_t *ctx, int ebi,
                                         const OctetString *msg);
 #endif // NAS_MME
 
@@ -109,7 +109,7 @@ static int _default_eps_bearer_activate(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_default_eps_bearer_context(unsigned int ueid, int pid,
+int esm_proc_default_eps_bearer_context(emm_data_context_t *ctx, int pid,
                                         unsigned int *ebi,
                                         const esm_proc_qos_t *qos,
                                         int *esm_cause)
@@ -117,14 +117,14 @@ int esm_proc_default_eps_bearer_context(unsigned int ueid, int pid,
     LOG_FUNC_IN;
 
     LOG_TRACE(INFO, "ESM-PROC  - Default EPS bearer context activation "
-              "(ueid=%u, pid=%d)", ueid, pid);
+              "(ueid=%u, pid=%d)", ctx->ueid, pid);
 
     /* Assign new EPS bearer context */
-    *ebi = esm_ebr_assign(ueid, ESM_EBI_UNASSIGNED);
+    *ebi = esm_ebr_assign(ctx, ESM_EBI_UNASSIGNED);
 
     if (*ebi != ESM_EBI_UNASSIGNED) {
         /* Create default EPS bearer context */
-        *ebi = esm_ebr_context_create(ueid, pid, *ebi, TRUE, qos, NULL);
+        *ebi = esm_ebr_context_create(ctx, pid, *ebi, TRUE, qos, NULL);
         if (*ebi == ESM_EBI_UNASSIGNED) {
             /* No resource available */
             LOG_TRACE(WARNING, "ESM-PROC  - Failed to create new default EPS "
@@ -170,25 +170,25 @@ int esm_proc_default_eps_bearer_context(unsigned int ueid, int pid,
  **                                                                        **
  ***************************************************************************/
 int esm_proc_default_eps_bearer_context_request(int is_standalone,
-        unsigned int ueid, int ebi,
+        emm_data_context_t *ctx, int ebi,
         OctetString *msg, int ue_triggered)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNok;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO,"ESM-PROC  - Initiate default EPS bearer context activation "
-              "(ueid=%d, ebi=%d)", ueid, ebi);
+              "(ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     if (is_standalone) {
         /* Send activate default EPS bearer context request message and
          * start timer T3485 */
-        rc = _default_eps_bearer_activate(ueid, ebi, msg);
+        rc = _default_eps_bearer_activate(ctx, ebi, msg);
     }
 
     if (rc != RETURNerror) {
         /* Set the EPS bearer context state to ACTIVE PENDING */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_ACTIVE_PENDING, ue_triggered);
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_ACTIVE_PENDING, ue_triggered);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in ACTIVE PENDING state */
             LOG_TRACE(WARNING, "ESM-PROC  - EBI %d was already ACTIVE PENDING",
@@ -221,7 +221,7 @@ int esm_proc_default_eps_bearer_context_request(int is_standalone,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_default_eps_bearer_context_accept(unsigned int ueid, int ebi,
+int esm_proc_default_eps_bearer_context_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause)
 {
     LOG_FUNC_IN;
@@ -229,13 +229,13 @@ int esm_proc_default_eps_bearer_context_accept(unsigned int ueid, int ebi,
     int rc;
 
     LOG_TRACE(INFO, "ESM-PROC  - Default EPS bearer context activation "
-              "accepted by the UE (ueid=%u, ebi=%d)", ueid, ebi);
+              "accepted by the UE (ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     /* Stop T3485 timer if running */
-    rc = esm_ebr_stop_timer(ueid, ebi);
+    rc = esm_ebr_stop_timer(ctx, ebi);
     if (rc != RETURNerror) {
         /* Set the EPS bearer context state to ACTIVE */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_ACTIVE, FALSE);
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_ACTIVE, FALSE);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in ACTIVE state */
             LOG_TRACE(WARNING, "ESM-PROC  - EBI %d was already ACTIVE", ebi);
@@ -268,7 +268,7 @@ int esm_proc_default_eps_bearer_context_accept(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_default_eps_bearer_context_reject(unsigned int ueid, int ebi,
+int esm_proc_default_eps_bearer_context_reject(emm_data_context_t *ctx, int ebi,
         int *esm_cause)
 {
     LOG_FUNC_IN;
@@ -276,14 +276,14 @@ int esm_proc_default_eps_bearer_context_reject(unsigned int ueid, int ebi,
     int rc;
 
     LOG_TRACE(WARNING, "ESM-PROC  - Default EPS bearer context activation "
-              "not accepted by the UE (ueid=%u, ebi=%d)", ueid, ebi);
+              "not accepted by the UE (ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     /* Stop T3485 timer if running */
-    rc = esm_ebr_stop_timer(ueid, ebi);
+    rc = esm_ebr_stop_timer(ctx, ebi);
     if (rc != RETURNerror) {
         int pid, bid;
         /* Release the default EPS bearer context and enter state INACTIVE */
-        rc = esm_proc_eps_bearer_context_deactivate(ueid, TRUE, ebi,
+        rc = esm_proc_eps_bearer_context_deactivate(ctx, TRUE, ebi,
                 &pid, &bid, NULL);
         if (rc != RETURNok) {
             /* Failed to release the default EPS bearer context */
@@ -318,23 +318,23 @@ int esm_proc_default_eps_bearer_context_reject(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_default_eps_bearer_context_failure(unsigned int ueid)
+int esm_proc_default_eps_bearer_context_failure(emm_data_context_t *ctx)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
     int pid;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(WARNING, "ESM-PROC  - Default EPS bearer context activation "
-              "failure (ueid=%u)", ueid);
+              "failure (ueid=%u)", ctx->ueid);
 
     /* Get the EPS bearer identity of the EPS bearer context which is still
      * pending in the active pending state */
-    int ebi = esm_ebr_get_pending_ebi(ueid, ESM_EBR_ACTIVE_PENDING);
+    int ebi = esm_ebr_get_pending_ebi(ctx, ESM_EBR_ACTIVE_PENDING);
     if (ebi != ESM_EBI_UNASSIGNED) {
         int bid;
         /* Release the default EPS bearer context and enter state INACTIVE */
-        rc = esm_proc_eps_bearer_context_deactivate(ueid, TRUE, ebi,
+        rc = esm_proc_eps_bearer_context_deactivate(ctx, TRUE, ebi,
                 &pid, &bid, NULL);
     }
 
@@ -680,7 +680,7 @@ static void *_default_eps_bearer_activate_t3485_handler(void *args)
     if (data->count < DEFAULT_EPS_BEARER_ACTIVATE_COUNTER_MAX) {
         /* Re-send activate default EPS bearer context request message
          * to the UE */
-        rc = _default_eps_bearer_activate(data->ueid, data->ebi, &data->msg);
+        rc = _default_eps_bearer_activate(data->ctx, data->ebi, &data->msg);
     } else {
         /*
          * The maximum number of activate default EPS bearer context request
@@ -688,12 +688,12 @@ static void *_default_eps_bearer_activate_t3485_handler(void *args)
          */
         int pid, bid;
         /* Release the default EPS bearer context and enter state INACTIVE */
-        rc = esm_proc_eps_bearer_context_deactivate(data->ueid, TRUE,
+        rc = esm_proc_eps_bearer_context_deactivate(data->ctx, TRUE,
                 data->ebi, &pid, &bid,
                 NULL);
         if (rc != RETURNerror) {
             /* Stop timer T3485 */
-            rc = esm_ebr_stop_timer(data->ueid, data->ebi);
+            rc = esm_ebr_stop_timer(data->ctx, data->ebi);
         }
     }
 
@@ -723,7 +723,7 @@ static void *_default_eps_bearer_activate_t3485_handler(void *args)
  **      Others:    T3485                                      **
  **                                                                        **
  ***************************************************************************/
-static int _default_eps_bearer_activate(unsigned int ueid, int ebi,
+static int _default_eps_bearer_activate(emm_data_context_t *ctx, int ebi,
                                         const OctetString *msg)
 {
     LOG_FUNC_IN;
@@ -737,13 +737,14 @@ static int _default_eps_bearer_activate(unsigned int ueid, int ebi,
      */
     emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data;
     emm_sap.primitive = EMMESM_UNITDATA_REQ;
-    emm_sap.u.emm_esm.ueid = ueid;
+    emm_sap.u.emm_esm.ueid = ctx->ueid;
+    emm_sap.u.emm_esm.ctx  = ctx;
     emm_esm->msg = *msg;
     rc = emm_sap_send(&emm_sap);
 
     if (rc != RETURNerror) {
         /* Start T3485 retransmission timer */
-        rc = esm_ebr_start_timer(ueid, ebi, msg, T3485_DEFAULT_VALUE,
+        rc = esm_ebr_start_timer(ctx, ebi, msg, T3485_DEFAULT_VALUE,
                                  _default_eps_bearer_activate_t3485_handler);
     }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/EpsBearerContextDeactivation.c b/openair-cn/NAS/EURECOM-NAS/src/esm/EpsBearerContextDeactivation.c
index 0c9811164ee0bc5306ac16670bfb72f58744190d..45e81ca2881c8e11c71d738357662de1ff78ee17 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/EpsBearerContextDeactivation.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/EpsBearerContextDeactivation.c
@@ -31,6 +31,7 @@ Description Defines the EPS bearer context deactivation ESM procedure
 #include "commonDef.h"
 #include "nas_log.h"
 
+#include "emmData.h"
 #include "esmData.h"
 #include "esm_cause.h"
 #include "esm_ebr.h"
@@ -77,9 +78,9 @@ static void *_eps_bearer_deactivate_t3495_handler(void *);
  * retransmission counter */
 #define EPS_BEARER_DEACTIVATE_COUNTER_MAX   5
 
-static int _eps_bearer_deactivate(unsigned int ueid, int ebi,
+static int _eps_bearer_deactivate(emm_data_context_t *ctx, int ebi,
                                   const OctetString *msg);
-static int _eps_bearer_release(unsigned int ueid, int ebi, int *pid, int *bid);
+static int _eps_bearer_release(emm_data_context_t *ctx, int ebi, int *pid, int *bid);
 
 #endif // NAS_MME
 
@@ -121,24 +122,24 @@ static int _eps_bearer_release(unsigned int ueid, int ebi, int *pid, int *bid);
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_eps_bearer_context_deactivate(unsigned int ueid, int is_local,
+int esm_proc_eps_bearer_context_deactivate(emm_data_context_t *ctx, int is_local,
         int ebi, int *pid, int *bid,
         int *esm_cause)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
 
+    LOG_FUNC_IN;
+
     if (is_local) {
         if (ebi != ESM_SAP_ALL_EBI) {
             /* Locally release the specified EPS bearer context */
-            rc = _eps_bearer_release(ueid, ebi, pid, bid);
-        } else if ( (ueid < ESM_DATA_NB_UE_MAX) && _esm_data.ctx[ueid] ) {
+            rc = _eps_bearer_release(ctx, ebi, pid, bid);
+        } else if (ctx != NULL) {
             /* Locally release all the EPS bearer contexts */
             *bid = 0;
             for (*pid = 0; *pid < ESM_DATA_PDN_MAX; (*pid)++) {
-                if (_esm_data.ctx[ueid]->pdn[*pid].data) {
-                    rc = _eps_bearer_release(ueid, ESM_EBI_UNASSIGNED,
+                if (ctx->esm_data_ctx.pdn[*pid].data) {
+                    rc = _eps_bearer_release(ctx, ESM_EBI_UNASSIGNED,
                                              pid, bid);
                     if (rc != RETURNok) {
                         break;
@@ -150,26 +151,28 @@ int esm_proc_eps_bearer_context_deactivate(unsigned int ueid, int is_local,
     }
 
     LOG_TRACE(INFO, "ESM-PROC  - EPS bearer context deactivation "
-              "(ueid=%u, ebi=%d)", ueid, ebi);
+              "(ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
-    if ( (ueid < ESM_DATA_NB_UE_MAX) && (_esm_data.ctx[ueid] != NULL) &&
+    if ((ctx != NULL) &&
             (*pid < ESM_DATA_PDN_MAX) ) {
-        if (_esm_data.ctx[ueid]->pdn[*pid].pid != *pid) {
+        if (ctx->esm_data_ctx.pdn[*pid].pid != *pid) {
             LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d "
                       "is not valid", *pid);
             *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
-        } else if (_esm_data.ctx[ueid]->pdn[*pid].data == NULL) {
+        } else if (ctx->esm_data_ctx.pdn[*pid].data == NULL) {
             LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                       "allocated", *pid);
             *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
-        } else if (!_esm_data.ctx[ueid]->pdn[*pid].is_active) {
+        } else if (!ctx->esm_data_ctx.pdn[*pid].is_active) {
             LOG_TRACE(WARNING, "ESM-PROC  - PDN connection %d is not active",
                       *pid);
             *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
         } else {
             int i;
+            esm_pdn_t *pdn = ctx->esm_data_ctx.pdn[*pid].data;
+
             *esm_cause = ESM_CAUSE_INVALID_EPS_BEARER_IDENTITY;
-            esm_pdn_t *pdn = _esm_data.ctx[ueid]->pdn[*pid].data;
+
             for (i = 0; i < pdn->n_bearers; i++) {
                 if (pdn->bearer[i]->ebi != ebi) {
                     continue;
@@ -209,7 +212,7 @@ int esm_proc_eps_bearer_context_deactivate(unsigned int ueid, int is_local,
  **                                                                        **
  ***************************************************************************/
 int esm_proc_eps_bearer_context_deactivate_request(int is_standalone,
-        unsigned int ueid, int ebi,
+        emm_data_context_t *ctx, int ebi,
         OctetString *msg, int ue_triggered)
 {
     LOG_FUNC_IN;
@@ -217,15 +220,15 @@ int esm_proc_eps_bearer_context_deactivate_request(int is_standalone,
     int rc;
 
     LOG_TRACE(INFO,"ESM-PROC  - Initiate EPS bearer context deactivation "
-              "(ueid=%d, ebi=%d)", ueid, ebi);
+              "(ueid=%d, ebi=%d)", ctx->ueid, ebi);
 
     /* Send deactivate EPS bearer context request message and
      * start timer T3495 */
-    rc = _eps_bearer_deactivate(ueid, ebi, msg);
+    rc = _eps_bearer_deactivate(ctx, ebi, msg);
 
     if (rc != RETURNerror) {
         /* Set the EPS bearer context state to ACTIVE PENDING */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_INACTIVE_PENDING,
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_INACTIVE_PENDING,
                                 ue_triggered);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in ACTIVE state */
@@ -261,7 +264,7 @@ int esm_proc_eps_bearer_context_deactivate_request(int is_standalone,
  **      Others:    T3495                                      **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_eps_bearer_context_deactivate_accept(unsigned int ueid, int ebi,
+int esm_proc_eps_bearer_context_deactivate_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause)
 {
     LOG_FUNC_IN;
@@ -270,14 +273,14 @@ int esm_proc_eps_bearer_context_deactivate_accept(unsigned int ueid, int ebi,
     int pid = RETURNerror;
 
     LOG_TRACE(INFO, "ESM-PROC  - EPS bearer context deactivation "
-              "accepted by the UE (ueid=%u, ebi=%d)", ueid, ebi);
+              "accepted by the UE (ueid=%u, ebi=%d)", ctx->ueid, ebi);
 
     /* Stop T3495 timer if running */
-    rc = esm_ebr_stop_timer(ueid, ebi);
+    rc = esm_ebr_stop_timer(ctx, ebi);
     if (rc != RETURNerror) {
         int bid;
         /* Release the EPS bearer context */
-        rc = _eps_bearer_release(ueid, ebi, &pid, &bid);
+        rc = _eps_bearer_release(ctx, ebi, &pid, &bid);
         if (rc != RETURNok) {
             /* Failed to release the EPS bearer context */
             *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
@@ -567,7 +570,7 @@ static void *_eps_bearer_deactivate_t3495_handler(void *args)
 
     if (data->count < EPS_BEARER_DEACTIVATE_COUNTER_MAX) {
         /* Re-send deactivate EPS bearer context request message to the UE */
-        rc = _eps_bearer_deactivate(data->ueid, data->ebi, &data->msg);
+        rc = _eps_bearer_deactivate(data->ctx, data->ebi, &data->msg);
     } else {
         /*
          * The maximum number of deactivate EPS bearer context request
@@ -576,10 +579,10 @@ static void *_eps_bearer_deactivate_t3495_handler(void *args)
         int pid, bid;
         /* Deactivate the EPS bearer context locally without peer-to-peer
          * signalling between the UE and the MME */
-        rc = _eps_bearer_release(data->ueid, data->ebi, &pid, &bid);
+        rc = _eps_bearer_release(data->ctx, data->ebi, &pid, &bid);
         if (rc != RETURNerror) {
             /* Stop timer T3495 */
-            rc = esm_ebr_stop_timer(data->ueid, data->ebi);
+            rc = esm_ebr_stop_timer(data->ctx, data->ebi);
         }
     }
 
@@ -611,7 +614,7 @@ static void *_eps_bearer_deactivate_t3495_handler(void *args)
  **      Others:    T3495                                      **
  **                                                                        **
  ***************************************************************************/
-static int _eps_bearer_deactivate(unsigned int ueid, int ebi,
+static int _eps_bearer_deactivate(emm_data_context_t *ctx, int ebi,
                                   const OctetString *msg)
 {
     LOG_FUNC_IN;
@@ -625,13 +628,14 @@ static int _eps_bearer_deactivate(unsigned int ueid, int ebi,
      */
     emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data;
     emm_sap.primitive = EMMESM_UNITDATA_REQ;
-    emm_sap.u.emm_esm.ueid = ueid;
+    emm_sap.u.emm_esm.ueid = ctx->ueid;
+    emm_sap.u.emm_esm.ctx  = ctx;
     emm_esm->msg = *msg;
     rc = emm_sap_send(&emm_sap);
 
     if (rc != RETURNerror) {
         /* Start T3495 retransmission timer */
-        rc = esm_ebr_start_timer(ueid, ebi, msg, T3495_DEFAULT_VALUE,
+        rc = esm_ebr_start_timer(ctx, ebi, msg, T3495_DEFAULT_VALUE,
                                  _eps_bearer_deactivate_t3495_handler);
     }
 
@@ -657,25 +661,25 @@ static int _eps_bearer_deactivate(unsigned int ueid, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _eps_bearer_release(unsigned int ueid, int ebi, int *pid, int *bid)
+static int _eps_bearer_release(emm_data_context_t *ctx, int ebi, int *pid, int *bid)
 {
     LOG_FUNC_IN;
 
     int rc = RETURNerror;
 
     /* Release the EPS bearer context entry */
-    ebi = esm_ebr_context_release(ueid, ebi, pid, bid);
+    ebi = esm_ebr_context_release(ctx, ebi, pid, bid);
     if (ebi == ESM_EBI_UNASSIGNED) {
         LOG_TRACE(WARNING, "ESM-PROC  - Failed to release EPS bearer context");
     } else {
         /* Set the EPS bearer context state to INACTIVE */
-        rc = esm_ebr_set_status(ueid, ebi, ESM_EBR_INACTIVE, FALSE);
+        rc = esm_ebr_set_status(ctx, ebi, ESM_EBR_INACTIVE, FALSE);
         if (rc != RETURNok) {
             /* The EPS bearer context was already in INACTIVE state */
             LOG_TRACE(WARNING, "ESM-PROC  - EBI %d was already INACTIVE", ebi);
         } else {
             /* Release EPS bearer data */
-            rc = esm_ebr_release(ueid, ebi);
+            rc = esm_ebr_release(ctx, ebi);
             if (rc != RETURNok) {
                 LOG_TRACE(WARNING,
                           "ESM-PROC  - Failed to release EPS bearer data");
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/EsmStatusHdl.c b/openair-cn/NAS/EURECOM-NAS/src/esm/EsmStatusHdl.c
index 12e3ecfb3b5c4e2db5799d374504f1d22fd0bf4f..174d7273e2f38c0f95d9a9ba8e43200e510e8e7f 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/EsmStatusHdl.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/EsmStatusHdl.c
@@ -73,7 +73,7 @@ Description Defines the ESM status procedure executed by the Non-Access
  ***************************************************************************/
 int esm_proc_status_ind(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int pti, int ebi, int *esm_cause)
 {
@@ -148,7 +148,7 @@ int esm_proc_status_ind(
  ***************************************************************************/
 int esm_proc_status(int is_standalone,
 #ifdef NAS_MME
-                    unsigned int ueid,
+                    emm_data_context_t *ctx,
 #endif
                     int ebi, OctetString *msg,
                     int ue_triggered)
@@ -168,7 +168,8 @@ int esm_proc_status(int is_standalone,
     emm_sap.u.emm_esm.ueid = 0;
 #endif
 #ifdef NAS_MME
-    emm_sap.u.emm_esm.ueid = ueid;
+    emm_sap.u.emm_esm.ueid = ctx->ueid;
+    emm_sap.u.emm_esm.ctx  = ctx;
 #endif
     emm_sap.u.emm_esm.u.data.msg.length = msg->length;
     emm_sap.u.emm_esm.u.data.msg.value = msg->value;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/PdnConnectivity.c b/openair-cn/NAS/EURECOM-NAS/src/esm/PdnConnectivity.c
index d7690bcdbad9106b4818e406101d75ad33992ca9..7d91863c48bce214aa43e8eec60dc5e33d39788a 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/PdnConnectivity.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/PdnConnectivity.c
@@ -29,6 +29,9 @@ Description Defines the PDN connectivity ESM procedure executed by the
 
 *****************************************************************************/
 
+#include <stdlib.h> // malloc, free
+#include <string.h> // memset, memcpy, memcmp
+
 #include "esm_proc.h"
 #include "commonDef.h"
 #include "nas_log.h"
@@ -38,13 +41,14 @@ Description Defines the PDN connectivity ESM procedure executed by the
 #include "esm_pt.h"
 
 #ifdef NAS_MME
-#include "mme_api.h"
+# include "mme_api.h"
 #endif
 
 #include "emm_sap.h"
 
-#include <stdlib.h> // malloc, free
-#include <string.h> // memset, memcpy, memcmp
+#if defined(ENABLE_ITTI)
+# include "assertions.h"
+#endif
 
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
@@ -93,10 +97,13 @@ static void *_pdn_connectivity_t3482_handler(void *);
 /*
  * PDN connection handlers
  */
-static int _pdn_connectivity_create(unsigned int ueid, int pti,
-                                    const OctetString *apn, esm_proc_pdn_type_t pdn_type,
-                                    const OctetString *pdn_addr, int is_emergency);
-int _pdn_connectivity_delete(unsigned int ueid, int pid);
+static int _pdn_connectivity_create(emm_data_context_t *ctx,
+                                    int pti,
+                                    const OctetString *apn,
+                                    esm_proc_pdn_type_t pdn_type,
+                                    const OctetString *pdn_addr,
+                                    int is_emergency);
+int _pdn_connectivity_delete(emm_data_context_t *ctx, int pid);
 
 #endif // NAS_MME
 
@@ -588,7 +595,7 @@ int esm_proc_pdn_connectivity_failure(int is_pending)
  **      Others:    _esm_data                                  **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_connectivity_request(unsigned int ueid, int pti,
+int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
                                       esm_proc_pdn_request_t request_type,
                                       OctetString *apn,
                                       esm_proc_pdn_type_t pdn_type,
@@ -596,22 +603,24 @@ int esm_proc_pdn_connectivity_request(unsigned int ueid, int pti,
                                       esm_proc_qos_t *esm_qos,
                                       int *esm_cause)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
     int pid = RETURNerror;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO, "ESM-PROC  - PDN connectivity requested by the UE "
-              "(ueid=%u, pti=%d) PDN type = %s, APN = %s", ueid, pti,
+              "(ueid=%u, pti=%d) PDN type = %s, APN = %s", ctx->ueid, pti,
               (pdn_type == ESM_PDN_TYPE_IPV4)? "IPv4" :
               (pdn_type == ESM_PDN_TYPE_IPV6)? "IPv6" : "IPv4v6",
-              (apn)? (char *)(apn->value) : "null");
+              (apn) ? (char *)(apn->value) : "null");
 
+#if !defined(EPC_BUILD)
     /* UE identifier sanity check */
-    if (ueid >= ESM_DATA_NB_UE_MAX) {
+    if (ctx->ueid >= ESM_DATA_NB_UE_MAX) {
         LOG_TRACE(WARNING, "ESM-PROC  - Number of connected UEs exceeded");
         LOG_FUNC_RETURN (RETURNerror);
     }
+#endif
 
     /*
      * Check network IP capabilities
@@ -659,24 +668,17 @@ int esm_proc_pdn_connectivity_request(unsigned int ueid, int pti,
             LOG_FUNC_RETURN (RETURNerror);
         }
 
-        /* Create new ESM context for the UE within the MME */
-        if (_esm_data.ctx[ueid] == NULL) {
-            _esm_data.ctx[ueid] =
-                (esm_data_context_t *)malloc(sizeof(esm_data_context_t));
-            memset(_esm_data.ctx[ueid], 0 , sizeof(esm_data_context_t));
-        }
-        if (_esm_data.ctx[ueid]) {
-            /* Create new PDN connection */
-            pid = _pdn_connectivity_create(ueid, pti, apn, pdn_type,
-                                           pdn_addr, is_emergency);
-            /* Setup ESM QoS parameters */
-            if (esm_qos) {
-                esm_qos->gbrUL = qos.gbr[MME_API_UPLINK];
-                esm_qos->gbrDL = qos.gbr[MME_API_DOWNLINK];
-                esm_qos->mbrUL = qos.mbr[MME_API_UPLINK];
-                esm_qos->mbrDL = qos.mbr[MME_API_DOWNLINK];
-                esm_qos->qci = qos.qci;
-            }
+
+        /* Create new PDN connection */
+        pid = _pdn_connectivity_create(ctx, pti, apn, pdn_type,
+                pdn_addr, is_emergency);
+        /* Setup ESM QoS parameters */
+        if (esm_qos) {
+            esm_qos->gbrUL = qos.gbr[MME_API_UPLINK];
+            esm_qos->gbrDL = qos.gbr[MME_API_DOWNLINK];
+            esm_qos->mbrUL = qos.mbr[MME_API_UPLINK];
+            esm_qos->mbrDL = qos.mbr[MME_API_DOWNLINK];
+            esm_qos->qci = qos.qci;
         }
 
         if (pid < 0) {
@@ -716,7 +718,7 @@ int esm_proc_pdn_connectivity_request(unsigned int ueid, int pti,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_connectivity_reject(int is_standalone, unsigned int ueid,
+int esm_proc_pdn_connectivity_reject(int is_standalone, emm_data_context_t *ctx,
                                      int ebi, OctetString *msg, int ue_triggered)
 {
     LOG_FUNC_IN;
@@ -724,7 +726,7 @@ int esm_proc_pdn_connectivity_reject(int is_standalone, unsigned int ueid,
     int rc = RETURNerror;
 
     LOG_TRACE(WARNING, "ESM-PROC  - PDN connectivity not accepted by the "
-              "network (ueid=%d)", ueid);
+              "network (ueid=%d)", ctx->ueid);
 
     if (is_standalone) {
         emm_sap_t emm_sap;
@@ -732,7 +734,7 @@ int esm_proc_pdn_connectivity_reject(int is_standalone, unsigned int ueid,
          * Notity EMM that ESM PDU has to be forwarded to lower layers
          */
         emm_sap.primitive = EMMESM_UNITDATA_REQ;
-        emm_sap.u.emm_esm.ueid = ueid;
+        emm_sap.u.emm_esm.ctx = ctx;
         emm_sap.u.emm_esm.u.data.msg.length = msg->length;
         emm_sap.u.emm_esm.u.data.msg.value = msg->value;
         rc = emm_sap_send(&emm_sap);
@@ -746,35 +748,37 @@ int esm_proc_pdn_connectivity_reject(int is_standalone, unsigned int ueid,
 
 /****************************************************************************
  **                                                                        **
- ** Name:    esm_proc_pdn_connectivity_failure()                       **
+ ** Name:        esm_proc_pdn_connectivity_failure()                       **
  **                                                                        **
  ** Description: Performs PDN connectivity procedure upon receiving noti-  **
- **      fication from the EPS Mobility Management sublayer that   **
- **      EMM procedure that initiated PDN connectivity activation  **
- **      locally failed.                                           **
+ **              fication from the EPS Mobility Management sublayer that   **
+ **              EMM procedure that initiated PDN connectivity activation  **
+ **              locally failed.                                           **
  **                                                                        **
- **      The MME releases the PDN connection entry allocated when  **
- **      the PDN connectivity procedure was requested by the UE.   **
+ **              The MME releases the PDN connection entry allocated when  **
+ **              the PDN connectivity procedure was requested by the UE.   **
  **                                                                        **
- ** Inputs:  ueid:      UE local identifier                        **
- **      pid:       Identifier of the PDN connection to be     **
- **             released                                   **
- **      Others:    None                                       **
+ **         Inputs:  ueid:      UE local identifier                        **
+ **                  pid:       Identifier of the PDN connection to be     **
+ **                             released                                   **
+ **                  Others:    None                                       **
  **                                                                        **
  ** Outputs:     None                                                      **
- **      Return:    RETURNok, RETURNerror                      **
- **      Others:    None                                       **
+ **                  Return:    RETURNok, RETURNerror                      **
+ **                  Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_connectivity_failure(unsigned int ueid, int pid)
+int esm_proc_pdn_connectivity_failure(emm_data_context_t *ctx, int pid)
 {
+    int pti;
+
     LOG_FUNC_IN;
 
     LOG_TRACE(WARNING, "ESM-PROC  - PDN connectivity failure (ueid=%u, pid=%d)",
-              ueid, pid);
+            ctx->ueid, pid);
 
     /* Delete the PDN connection entry */
-    int pti = _pdn_connectivity_delete(ueid, pid);
+    pti = _pdn_connectivity_delete(ctx, pid);
     if (pti != ESM_PT_UNASSIGNED) {
         LOG_FUNC_RETURN (RETURNok);
     }
@@ -1229,26 +1233,28 @@ static int _pdn_connectivity_find_pdn(const OctetString *apn,
  */
 /****************************************************************************
  **                                                                        **
- ** Name:    _pdn_connectivity_create()                                **
+ ** Name:        _pdn_connectivity_create()                                **
  **                                                                        **
  ** Description: Creates a new PDN connection entry for the specified UE   **
  **                                                                        **
- ** Inputs:  ueid:      UE local identifier                        **
- **      pti:       Procedure transaction identity             **
- **      apn:       Access Point Name of the PDN connection    **
- **      pdn_type:  PDN type (IPv4, IPv6, IPv4v6)              **
- **      pdn_addr:  Network allocated PDN IPv4 or IPv6 address **
- **      is_emergency:  TRUE if the PDN connection has to be esta- **
- **             blished for emergency bearer services      **
- **      Others:    _esm_data                                  **
+ ** Inputs:          ueid:      UE local identifier                        **
+ **                  ctx:       UE context                                 **
+ **                  pti:       Procedure transaction identity             **
+ **                  apn:       Access Point Name of the PDN connection    **
+ **                  pdn_type:  PDN type (IPv4, IPv6, IPv4v6)              **
+ **                  pdn_addr:  Network allocated PDN IPv4 or IPv6 address **
+ **              is_emergency:  TRUE if the PDN connection has to be esta- **
+ **                             blished for emergency bearer services      **
+ **                  Others:    _esm_data                                  **
  **                                                                        **
  ** Outputs:     None                                                      **
- **      Return:    The identifier of the PDN connection if    **
- **             successfully created; -1 otherwise.        **
- **      Others:    _esm_data                                  **
+ **                  Return:    The identifier of the PDN connection if    **
+ **                             successfully created; -1 otherwise.        **
+ **                  Others:    _esm_data                                  **
  **                                                                        **
  ***************************************************************************/
-static int _pdn_connectivity_create(unsigned int ueid, int pti,
+static int _pdn_connectivity_create(emm_data_context_t *ctx,
+                                    int pti,
                                     const OctetString *apn,
                                     esm_proc_pdn_type_t pdn_type,
                                     const OctetString *pdn_addr,
@@ -1260,25 +1266,14 @@ static int _pdn_connectivity_create(unsigned int ueid, int pti,
               "(pti=%d) APN = %s, IP address = %s (ueid=%u)", pti, apn->value,
               (pdn_type == ESM_PDN_TYPE_IPV4)? esm_data_get_ipv4_addr(pdn_addr) :
               (pdn_type == ESM_PDN_TYPE_IPV6)? esm_data_get_ipv6_addr(pdn_addr) :
-              esm_data_get_ipv4v6_addr(pdn_addr), ueid);
-
-    if (ueid < ESM_DATA_NB_UE_MAX) {
-        if (_esm_data.ctx[ueid] == NULL) {
-            LOG_TRACE(ERROR, "ESM-PROC  - ESM context has not been allocated");
-        } else if (_esm_data.ctx[ueid]->n_pdns > ESM_DATA_PDN_MAX) {
-            LOG_TRACE(WARNING, "ESM-PROC  - Number of PDN connection exceeded");
-        } else if (_esm_data.ctx[ueid]->emergency && is_emergency) {
-            LOG_TRACE(WARNING, "ESM-PROC  - PDN connection for emergency bearer "
-                      "services already established");
-        } else {
-            /* Search for an available PDN connection entry */
-            for (pid = 0; pid < ESM_DATA_PDN_MAX; pid++) {
-                if (_esm_data.ctx[ueid]->pdn[pid].data != NULL) {
-                    continue;
-                }
-                break;
-            }
+              esm_data_get_ipv4v6_addr(pdn_addr), ctx->ueid);
+
+    /* Search for an available PDN connection entry */
+    for (pid = 0; pid < ESM_DATA_PDN_MAX; pid++) {
+        if (ctx->esm_data_ctx.pdn[pid].data != NULL) {
+            continue;
         }
+        break;
     }
 
     if (pid < ESM_DATA_PDN_MAX) {
@@ -1287,13 +1282,13 @@ static int _pdn_connectivity_create(unsigned int ueid, int pti,
         if (pdn != NULL) {
             memset(pdn, 0, sizeof(esm_pdn_t));
             /* Increment the number of PDN connections */
-            _esm_data.ctx[ueid]->n_pdns += 1;
+            ctx->esm_data_ctx.n_pdns += 1;
             /* Set the PDN connection identifier */
-            _esm_data.ctx[ueid]->pdn[pid].pid = pid;
+            ctx->esm_data_ctx.pdn[pid].pid = pid;
             /* Reset the PDN connection active indicator */
-            _esm_data.ctx[ueid]->pdn[pid].is_active = FALSE;
+            ctx->esm_data_ctx.pdn[pid].is_active = FALSE;
             /* Setup the PDN connection data */
-            _esm_data.ctx[ueid]->pdn[pid].data = pdn;
+            ctx->esm_data_ctx.pdn[pid].data = pdn;
 
             /* Set the procedure transaction identity */
             pdn->pti = pti;
@@ -1317,7 +1312,7 @@ static int _pdn_connectivity_create(unsigned int ueid, int pti,
                 pdn->type = pdn_type;
             }
             /* Return the identifier of the new PDN connection */
-            return (_esm_data.ctx[ueid]->pdn[pid].pid);
+            return (ctx->esm_data_ctx.pdn[pid].pid);
         }
         LOG_TRACE(WARNING, "ESM-PROC  - Failed to create new PDN connection "
                   "(pid=%d)", pid);
@@ -1328,59 +1323,59 @@ static int _pdn_connectivity_create(unsigned int ueid, int pti,
 
 /****************************************************************************
  **                                                                        **
- ** Name:    _pdn_connectivity_delete()                                **
+ ** Name:        _pdn_connectivity_delete()                                **
  **                                                                        **
  ** Description: Deletes PDN connection to the specified UE associated to  **
- **      PDN connection entry with given identifier                **
+ **              PDN connection entry with given identifier                **
  **                                                                        **
- ** Inputs:  ueid:      UE local identifier                        **
- **      pid:       Identifier of the PDN connection to be     **
- **             released                                   **
- **      Others:    _esm_data                                  **
+ ** Inputs:          ueid:      UE local identifier                        **
+ **                  pid:       Identifier of the PDN connection to be     **
+ **                             released                                   **
+ **                  Others:    _esm_data                                  **
  **                                                                        **
  ** Outputs:     None                                                      **
- **      Return:    The identity of the procedure transaction  **
- **             assigned to the PDN connection when suc-   **
- **             cessfully released;                        **
- **             UNASSIGNED value otherwise.                **
- **      Others:    _esm_data                                  **
+ **                  Return:    The identity of the procedure transaction  **
+ **                             assigned to the PDN connection when suc-   **
+ **                             cessfully released;                        **
+ **                             UNASSIGNED value otherwise.                **
+ **                  Others:    _esm_data                                  **
  **                                                                        **
  ***************************************************************************/
-int _pdn_connectivity_delete(unsigned int ueid, int pid)
+int _pdn_connectivity_delete(emm_data_context_t *ctx, int pid)
 {
     int pti = ESM_PT_UNASSIGNED;
 
-    if (ueid < ESM_DATA_NB_UE_MAX) {
-        if (_esm_data.ctx[ueid] == NULL) {
-            LOG_TRACE(ERROR, "ESM-PROC  - ESM context has not been allocated");
-        } else if (pid < ESM_DATA_PDN_MAX) {
-            if (pid != _esm_data.ctx[ueid]->pdn[pid].pid) {
-                LOG_TRACE(ERROR,
-                          "ESM-PROC  - PDN connection identifier is not valid");
-            } else if (_esm_data.ctx[ueid]->pdn[pid].data == NULL) {
-                LOG_TRACE(ERROR,
-                          "ESM-PROC  - PDN connection has not been allocated");
-            } else if (_esm_data.ctx[ueid]->pdn[pid].is_active) {
-                LOG_TRACE(ERROR, "ESM-PROC  - PDN connection is active");
-            } else {
-                /* Get the identity of the procedure transaction that created
-                 * the PDN connection */
-                pti = _esm_data.ctx[ueid]->pdn[pid].data->pti;
-            }
+    if (ctx == NULL) {
+        return pti;
+    }
+
+    if (pid < ESM_DATA_PDN_MAX) {
+        if (pid != ctx->esm_data_ctx.pdn[pid].pid) {
+            LOG_TRACE(ERROR,
+                    "ESM-PROC  - PDN connection identifier is not valid");
+        } else if (ctx->esm_data_ctx.pdn[pid].data == NULL) {
+            LOG_TRACE(ERROR,
+                    "ESM-PROC  - PDN connection has not been allocated");
+        } else if (ctx->esm_data_ctx.pdn[pid].is_active) {
+            LOG_TRACE(ERROR, "ESM-PROC  - PDN connection is active");
+        } else {
+            /* Get the identity of the procedure transaction that created
+             * the PDN connection */
+            pti = ctx->esm_data_ctx.pdn[pid].data->pti;
         }
     }
 
     if (pti != ESM_PT_UNASSIGNED) {
         /* Decrement the number of PDN connections */
-        _esm_data.ctx[ueid]->n_pdns -= 1;
+        ctx->esm_data_ctx.n_pdns -= 1;
         /* Set the PDN connection as available */
-        _esm_data.ctx[ueid]->pdn[pid].pid = -1;
+        ctx->esm_data_ctx.pdn[pid].pid = -1;
         /* Release allocated PDN connection data */
-        if (_esm_data.ctx[ueid]->pdn[pid].data->apn.length > 0) {
-            free(_esm_data.ctx[ueid]->pdn[pid].data->apn.value);
+        if (ctx->esm_data_ctx.pdn[pid].data->apn.length > 0) {
+            free(ctx->esm_data_ctx.pdn[pid].data->apn.value);
         }
-        free(_esm_data.ctx[ueid]->pdn[pid].data);
-        _esm_data.ctx[ueid]->pdn[pid].data = NULL;
+        free(ctx->esm_data_ctx.pdn[pid].data);
+        ctx->esm_data_ctx.pdn[pid].data = NULL;
         LOG_TRACE(WARNING, "ESM-PROC  - PDN connection %d released", pid);
     }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/PdnDisconnect.c b/openair-cn/NAS/EURECOM-NAS/src/esm/PdnDisconnect.c
index 73fe6a0a0946cebb7bdc193b248b21a58923dc57..b5818f3935ddcbc545353699b718ddb5a102746d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/PdnDisconnect.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/PdnDisconnect.c
@@ -44,7 +44,7 @@ Description Defines the PDN disconnect ESM procedure executed by the
 /****************************************************************************/
 
 #ifdef NAS_MME
-extern int _pdn_connectivity_delete(unsigned int ueid, int pid);
+extern int _pdn_connectivity_delete(emm_data_context_t *ctx, int pid);
 #endif
 
 /****************************************************************************/
@@ -81,7 +81,7 @@ static void *_pdn_disconnect_t3492_handler(void *);
 /*
  * PDN disconnection handlers
  */
-static int _pdn_disconnect_get_pid(unsigned int ueid, int pti);
+static int _pdn_disconnect_get_pid(esm_data_context_t *ctx, int pti);
 
 #endif // NAS_MME
 
@@ -368,36 +368,30 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_disconnect_request(unsigned int ueid, int pti, int *esm_cause)
+int esm_proc_pdn_disconnect_request(emm_data_context_t *ctx, int pti, int *esm_cause)
 {
-    LOG_FUNC_IN;
-
     int pid = RETURNerror;
 
-    LOG_TRACE(INFO, "ESM-PROC  - PDN disconnect requested by the UE "
-              "(ueid=%d, pti=%d)", ueid, pti);
+    LOG_FUNC_IN;
 
-    if (ueid < ESM_DATA_NB_UE_MAX) {
-        /* Get UE's ESM context */
-        esm_data_context_t *ctx = _esm_data.ctx[ueid];
-        if (_esm_data.ctx[ueid] == NULL) {
-            LOG_TRACE(ERROR, "ESM-PROC  - No ESM context exists");
+    LOG_TRACE(INFO, "ESM-PROC  - PDN disconnect requested by the UE "
+              "(ueid=%d, pti=%d)", ctx->ueid, pti);
+
+    /* Get UE's ESM context */
+    if (ctx->esm_data_ctx.n_pdns > 1) {
+        /* Get the identifier of the PDN connection entry assigned to the
+         * procedure transaction identity */
+        pid = _pdn_disconnect_get_pid(&ctx->esm_data_ctx, pti);
+        if (pid < 0) {
+            LOG_TRACE(ERROR, "ESM-PROC  - No PDN connection found (pti=%d)",
+                    pti);
             *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
-        } else if (ctx->n_pdns > 1) {
-            /* Get the identifier of the PDN connection entry assigned to the
-             * procedure transaction identity */
-            pid = _pdn_disconnect_get_pid(ueid, pti);
-            if (pid < 0) {
-                LOG_TRACE(ERROR, "ESM-PROC  - No PDN connection found (pti=%d)",
-                          pti);
-                *esm_cause = ESM_CAUSE_PROTOCOL_ERROR;
-                LOG_FUNC_RETURN (RETURNerror);
-            }
-        } else {
-            /* Attempt to disconnect from the last PDN disconnection
-             * is not allowed */
-            *esm_cause = ESM_CAUSE_LAST_PDN_DISCONNECTION_NOT_ALLOWED;
+            LOG_FUNC_RETURN (RETURNerror);
         }
+    } else {
+        /* Attempt to disconnect from the last PDN disconnection
+         * is not allowed */
+        *esm_cause = ESM_CAUSE_LAST_PDN_DISCONNECTION_NOT_ALLOWED;
     }
 
     LOG_FUNC_RETURN(pid);
@@ -425,18 +419,18 @@ int esm_proc_pdn_disconnect_request(unsigned int ueid, int pti, int *esm_cause)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_disconnect_accept(unsigned int ueid, int pid, int *esm_cause)
+int esm_proc_pdn_disconnect_accept(emm_data_context_t *ctx, int pid, int *esm_cause)
 {
     LOG_FUNC_IN;
 
     LOG_TRACE(INFO, "ESM-PROC  - PDN disconnect accepted by the UE "
-              "(ueid=%d, pid=%d)", ueid, pid);
+              "(ueid=%d, pid=%d)", ctx->ueid, pid);
 
     /* Release the connectivity with the requested PDN */
     int rc = mme_api_unsubscribe(NULL);
     if (rc != RETURNerror) {
         /* Delete the PDN connection entry */
-        int pti = _pdn_connectivity_delete(ueid, pid);
+        int pti = _pdn_connectivity_delete(ctx, pid);
         if (pti != ESM_PT_UNASSIGNED) {
             LOG_FUNC_RETURN (RETURNok);
         }
@@ -470,7 +464,7 @@ int esm_proc_pdn_disconnect_accept(unsigned int ueid, int pid, int *esm_cause)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_proc_pdn_disconnect_reject(int is_standalone, unsigned int ueid,
+int esm_proc_pdn_disconnect_reject(int is_standalone, emm_data_context_t *ctx,
                                    int ebi, OctetString *msg, int ue_triggered)
 {
     LOG_FUNC_IN;
@@ -479,13 +473,14 @@ int esm_proc_pdn_disconnect_reject(int is_standalone, unsigned int ueid,
     emm_sap_t emm_sap;
 
     LOG_TRACE(WARNING, "ESM-PROC  - PDN disconnect not accepted by the network "
-              "(ueid=%d)", ueid);
+              "(ueid=%d)", ctx->ueid);
 
     /*
      * Notity EMM that ESM PDU has to be forwarded to lower layers
      */
     emm_sap.primitive = EMMESM_UNITDATA_REQ;
-    emm_sap.u.emm_esm.ueid = ueid;
+    emm_sap.u.emm_esm.ueid = ctx->ueid;
+    emm_sap.u.emm_esm.ctx  = ctx;
     emm_sap.u.emm_esm.u.data.msg.length = msg->length;
     emm_sap.u.emm_esm.u.data.msg.value = msg->value;
     rc = emm_sap_send(&emm_sap);
@@ -670,15 +665,15 @@ static int _pdn_disconnect_get_default_ebi(int pti)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _pdn_disconnect_get_pid(unsigned int ueid, int pti)
+static int _pdn_disconnect_get_pid(esm_data_context_t *ctx, int pti)
 {
     int i = ESM_DATA_PDN_MAX;
 
-    if ( (ueid < ESM_DATA_NB_UE_MAX) && (_esm_data.ctx[ueid] != NULL) ) {
+    if (ctx != NULL) {
         for (i = 0; i < ESM_DATA_PDN_MAX; i++) {
-            if ( (_esm_data.ctx[ueid]->pdn[i].pid != -1) &&
-                    (_esm_data.ctx[ueid]->pdn[i].data != NULL) ) {
-                if (_esm_data.ctx[ueid]->pdn[i].data->pti != pti) {
+            if ( (ctx->pdn[i].pid != -1) &&
+                    (ctx->pdn[i].data != NULL) ) {
+                if (ctx->pdn[i].data->pti != pti) {
                     continue;
                 }
                 /* PDN entry found */
@@ -688,6 +683,6 @@ static int _pdn_disconnect_get_pid(unsigned int ueid, int pti)
     }
 
     /* Return the identifier of the PDN connection */
-    return (_esm_data.ctx[ueid]->pdn[i].pid);
+    return (ctx->pdn[i].pid);
 }
 #endif // NAS_MME
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h
index 37739334957d54f23218dae5f60e1a3c37bb22df..38ac0542fec70a2df627024fb5b73eadbe653934 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h
@@ -18,17 +18,22 @@ Description Defines internal private data handled by EPS Session
         Management sublayer.
 
 *****************************************************************************/
-#ifndef __ESMDATA_H__
-#define __ESMDATA_H__
+#include <stdio.h>  // sprintf
 
 #include "networkDef.h"
 #include "OctetString.h"
+#include "EpsBearerIdentity.h"
 
 #ifdef NAS_MME
 #include "mme_api.h"
 #endif
 
-#include <stdio.h>  // sprintf
+#if defined(EPC_BUILD)
+# include "tree.h"
+#endif
+
+#ifndef __ESMDATA_H__
+#define __ESMDATA_H__
 
 /****************************************************************************/
 /*********************  G L O B A L    C O N S T A N T S  *******************/
@@ -41,6 +46,67 @@ Description Defines internal private data handled by EPS Session
 /************************  G L O B A L    T Y P E S  ************************/
 /****************************************************************************/
 
+/*
+ * Minimal and maximal value of an EPS bearer identity:
+ * The EPS Bearer Identity (EBI) identifies a message flow
+ */
+#define ESM_EBI_MIN     (EPS_BEARER_IDENTITY_FIRST)
+#define ESM_EBI_MAX     (EPS_BEARER_IDENTITY_LAST)
+
+/* EPS bearer context states */
+typedef enum {
+    ESM_EBR_INACTIVE,       /* No EPS bearer context exists     */
+    ESM_EBR_ACTIVE,     /* The EPS bearer context is active,
+                 * in the UE, in the network        */
+#ifdef NAS_MME
+    ESM_EBR_INACTIVE_PENDING,   /* The network has initiated an EPS bearer
+                 * context deactivation towards the UE  */
+    ESM_EBR_MODIFY_PENDING, /* The network has initiated an EPS bearer
+                 * context modification towards the UE  */
+    ESM_EBR_ACTIVE_PENDING, /* The network has initiated an EPS bearer
+                 * context activation towards the UE    */
+#endif
+    ESM_EBR_STATE_MAX
+} esm_ebr_state;
+
+#ifdef NAS_MME
+/* ESM message timer retransmission data */
+typedef struct {
+    void        *ctx;
+    unsigned int ueid;      /* Lower layers UE identifier       */
+    unsigned int ebi;       /* EPS bearer identity          */
+    unsigned int count;     /* Retransmission counter       */
+    OctetString  msg;        /* Encoded ESM message to re-transmit   */
+} esm_ebr_timer_data_t;
+#endif
+
+/*
+ * -----------------------
+ * EPS bearer context data
+ * -----------------------
+ */
+typedef struct {
+    unsigned char ebi;      /* EPS bearer identity          */
+    esm_ebr_state status;   /* EPS bearer context status        */
+#ifdef NAS_UE
+    int is_default_ebr;     /* TRUE if the bearer context is associated
+                 * to a default EPS bearer      */
+    char cid;           /* Identifier of the PDN context the EPS
+                 * bearer context has been assigned to  */
+#endif
+#ifdef NAS_MME
+    struct nas_timer_t timer;   /* Retransmission timer         */
+    esm_ebr_timer_data_t *args; /* Retransmission timer parameters data */
+#endif
+} esm_ebr_context_t;
+
+typedef struct {
+    unsigned char index;    /* Index of the next EPS bearer context
+                 * identity to be used */
+#define ESM_EBR_DATA_SIZE (ESM_EBI_MAX - ESM_EBI_MIN + 1)
+    esm_ebr_context_t *context[ESM_EBR_DATA_SIZE + 1];
+} esm_ebr_data_t;
+
 /*
  * --------------------------------------------------------------------------
  * Structure of data handled by EPS Session Management sublayer in the UE
@@ -101,7 +167,9 @@ typedef struct {
  * fault EPS bearer. Several dedicated EPS bearers may exist within
  * a PDN connection.
  */
-typedef struct {
+typedef struct esm_data_context_s {
+    unsigned int ue_id;
+
     int n_ebrs;     /* Total number of active EPS bearer contexts   */
     int n_pdns;     /* Number of active PDN connections     */
     int emergency;  /* Indicates whether a PDN connection for emergency
@@ -114,6 +182,8 @@ typedef struct {
               * connection is in progress           */
         esm_pdn_t *data; /* Active PDN connection data          */
     } pdn[ESM_DATA_PDN_MAX+1];
+
+    esm_ebr_data_t ebr;
 } esm_data_context_t;
 
 /*
@@ -149,11 +219,26 @@ typedef struct {
      * ESM contexts
      * ------------
      */
-#define ESM_DATA_NB_UE_MAX  (MME_API_NB_UE_MAX + 1)
+# if defined(EPC_BUILD)
+    /* Use a tree for ue data context within MME */
+    RB_HEAD(esm_data_context_map, esm_data_context_s) ctx_map;
+# else
+#   define ESM_DATA_NB_UE_MAX  (MME_API_NB_UE_MAX + 1)
     esm_data_context_t *ctx[ESM_DATA_NB_UE_MAX];
-
+# endif
 } esm_data_t;
 
+# if defined(EPC_BUILD)
+struct esm_data_context_s *esm_data_context_get(
+    esm_data_t *esm_data, unsigned int _ueid);
+
+struct esm_data_context_s *esm_data_context_remove(
+    esm_data_t *esm_data, struct esm_data_context_s *elm);
+
+void esm_data_context_add(esm_data_t *esm_data, struct esm_data_context_s *elm);
+
+# endif
+
 #endif //NAS_MME
 
 /****************************************************************************/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.c b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.c
index dfb25e745bb699e238777d91adac2f5514969144..b4ef3ba503e8e17736fa63bfb30d9f897aa388a4 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.c
@@ -19,26 +19,20 @@ Description Defines functions used to handle state of EPS bearer contexts
 
 *****************************************************************************/
 
+#include <stdlib.h> // malloc, free
+#include <string.h> // memcpy
+
+#include "emmData.h"
 #include "esm_ebr.h"
 #include "commonDef.h"
 #include "nas_log.h"
 
 #include "mme_api.h"
 
-#include <stdlib.h> // malloc, free
-#include <string.h> // memcpy
-
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
 /****************************************************************************/
 
-/*
- * Minimal and maximal value of an EPS bearer identity:
- * The EPS Bearer Identity (EBI) identifies a message flow
- */
-#define ESM_EBI_MIN     (EPS_BEARER_IDENTITY_FIRST)
-#define ESM_EBI_MAX     (EPS_BEARER_IDENTITY_LAST)
-
 #ifdef NAS_UE
 #define ESM_EBR_NB_UE_MAX   1
 #endif
@@ -61,37 +55,15 @@ static const char *_esm_ebr_state_str[ESM_EBR_STATE_MAX] = {
 #endif
 };
 
-/*
- * -----------------------
- * EPS bearer context data
- * -----------------------
- */
-typedef struct {
-    unsigned char ebi;      /* EPS bearer identity          */
-    esm_ebr_state status;   /* EPS bearer context status        */
-#ifdef NAS_UE
-    int is_default_ebr;     /* TRUE if the bearer context is associated
-                 * to a default EPS bearer      */
-    char cid;           /* Identifier of the PDN context the EPS
-                 * bearer context has been assigned to  */
-#endif
-#ifdef NAS_MME
-    struct nas_timer_t timer;   /* Retransmission timer         */
-    esm_ebr_timer_data_t *args; /* Retransmission timer parameters data */
-#endif
-} esm_ebr_context_t;
-
 /*
  * ----------------------------------
  * List of EPS bearer contexts per UE
  * ----------------------------------
  */
-static struct {
-    unsigned char index;    /* Index of the next EPS bearer context
-                 * identity to be used */
-#define ESM_EBR_DATA_SIZE (ESM_EBI_MAX - ESM_EBI_MIN + 1)
-    esm_ebr_context_t *context[ESM_EBR_DATA_SIZE + 1];
-} _esm_ebr_data[ESM_EBR_NB_UE_MAX];
+
+#if !defined(EPC_BUILD)
+static esm_ebr_data_t _esm_ebr_data[ESM_EBR_NB_UE_MAX];
+#endif
 
 /*
  * ----------------------
@@ -123,7 +95,12 @@ static const network_pdn_state_t _esm_ebr_pdn_state[2][2][2] = {
 
 /* Returns the index of the next available entry in the list of EPS bearer
  * context data */
+#ifdef NAS_MME
+static int _esm_ebr_get_available_entry(emm_data_context_t *ctx);
+#endif
+#ifdef NAS_UE
 static int _esm_ebr_get_available_entry(unsigned int ueid);
+#endif
 
 /****************************************************************************/
 /******************  E X P O R T E D    F U N C T I O N S  ******************/
@@ -149,7 +126,9 @@ void esm_ebr_initialize(
 #endif
 )
 {
+#if !defined(EPC_BUILD)
     int ueid, i;
+
     LOG_FUNC_IN;
 
     for (ueid = 0; ueid < ESM_EBR_NB_UE_MAX; ueid++) {
@@ -159,12 +138,13 @@ void esm_ebr_initialize(
             _esm_ebr_data[ueid].context[i] = NULL;
         }
     }
-#ifdef NAS_UE
+# ifdef NAS_UE
     /* Initialize the user notification callback */
     _esm_ebr_callback = *cb;
-#endif
+# endif
 
     LOG_FUNC_OUT;
+#endif
 }
 
 /****************************************************************************
@@ -192,10 +172,10 @@ void esm_ebr_initialize(
 int esm_ebr_assign(int ebi, int cid, int default_ebr)
 #endif
 #ifdef NAS_MME
-int esm_ebr_assign(unsigned int ueid, int ebi)
+int esm_ebr_assign(emm_data_context_t *ctx, int ebi)
 #endif
 {
-    LOG_FUNC_IN;
+    esm_ebr_context_t *ebr_ctx;
 
 #ifdef NAS_UE
     unsigned int ueid = 0;
@@ -203,14 +183,18 @@ int esm_ebr_assign(unsigned int ueid, int ebi)
 
     int i;
 
-    if (ueid >= ESM_EBR_NB_UE_MAX) {
-        LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
-    }
+    LOG_FUNC_IN;
+
+#if defined(NAS_UE)
+    ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
+#else
+    ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
+#endif
 
     if (ebi != ESM_EBI_UNASSIGNED) {
         if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
             LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
-        } else if (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] != NULL) {
+        } else if (ebr_ctx != NULL) {
             LOG_TRACE(WARNING, "ESM-FSM   - EPS bearer context already "
                       "assigned (ebi=%d)", ebi);
             LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
@@ -219,7 +203,11 @@ int esm_ebr_assign(unsigned int ueid, int ebi)
         i = ebi - ESM_EBI_MIN;
     } else {
         /* Search for an available EPS bearer identity */
+#ifdef NAS_UE
         i = _esm_ebr_get_available_entry(ueid);
+#else
+        i = _esm_ebr_get_available_entry(ctx);
+#endif
         if (i < 0) {
             LOG_FUNC_RETURN(ESM_EBI_UNASSIGNED);
         }
@@ -228,33 +216,44 @@ int esm_ebr_assign(unsigned int ueid, int ebi)
     }
 
     /* Assign new EPS bearer context */
-    _esm_ebr_data[ueid].context[i] =
+    ebr_ctx =
         (esm_ebr_context_t *)malloc(sizeof(esm_ebr_context_t));
-    if (_esm_ebr_data[ueid].context[i] == NULL) {
+    if (ebr_ctx == NULL) {
         LOG_FUNC_RETURN(ESM_EBI_UNASSIGNED);
     }
+
+#if defined(EPC_BUILD)
+    ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN] = ebr_ctx;
+#else
+    _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] = ebr_ctx;
+#endif
+
     /* Store the index of the next available EPS bearer identity */
+#ifdef NAS_MME
+    ctx->esm_data_ctx.ebr.index = i + 1;
+#else
     _esm_ebr_data[ueid].index = i + 1;
+#endif
 
     /* Set the EPS bearer identity */
-    _esm_ebr_data[ueid].context[i]->ebi = ebi;
+    ebr_ctx->ebi = ebi;
     /* Set the EPS bearer context status to INACTIVE */
-    _esm_ebr_data[ueid].context[i]->status = ESM_EBR_INACTIVE;
+    ebr_ctx->status = ESM_EBR_INACTIVE;
 #ifdef NAS_UE
     /* Set the default EPS bearer indicator */
-    _esm_ebr_data[ueid].context[i]->is_default_ebr = default_ebr;
+    ebr_ctx->is_default_ebr = default_ebr;
     /* Set the identifier of the PDN context the EPS bearer is assigned to */
-    _esm_ebr_data[ueid].context[i]->cid = cid;
+    ebr_ctx->cid = cid;
 #endif
 #ifdef NAS_MME
     /* Disable the retransmission timer */
-    _esm_ebr_data[ueid].context[i]->timer.id = NAS_TIMER_INACTIVE_ID;
+    ebr_ctx->timer.id = NAS_TIMER_INACTIVE_ID;
     /* Setup retransmission timer parameters */
-    _esm_ebr_data[ueid].context[i]->args = NULL;
+    ebr_ctx->args = NULL;
 #endif
 
     LOG_TRACE(INFO, "ESM-FSM   - EPS bearer context %d assigned", ebi);
-    LOG_FUNC_RETURN(_esm_ebr_data[ueid].context[i]->ebi);
+    LOG_FUNC_RETURN(ebr_ctx->ebi);
 }
 
 /****************************************************************************
@@ -277,55 +276,57 @@ int esm_ebr_assign(unsigned int ueid, int ebi)
  ***************************************************************************/
 int esm_ebr_release(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int ebi)
 {
-    LOG_FUNC_IN;
-
 #ifdef NAS_UE
     unsigned int ueid = 0;
 #endif
+    esm_ebr_context_t *ebr_ctx;
+
+    LOG_FUNC_IN;
 
-    if (ueid >= ESM_EBR_NB_UE_MAX) {
-        LOG_FUNC_RETURN (RETURNerror);
-    }
     if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
         LOG_FUNC_RETURN (RETURNerror);
     }
 
     /* Get EPS bearer context data */
-    esm_ebr_context_t *ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
-    if ( (ctx == NULL) || (ctx->ebi != ebi) ) {
+#if defined(NAS_MME)
+    ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
+#else
+    ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
+#endif
+    if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) {
         /* EPS bearer context not assigned */
         LOG_FUNC_RETURN (RETURNerror);
     }
     /* Do not release active EPS bearer context */
-    if (ctx->status != ESM_EBR_INACTIVE) {
+    if (ebr_ctx->status != ESM_EBR_INACTIVE) {
         LOG_TRACE(ERROR, "ESM-FSM   - EPS bearer context is not INACTIVE");
         LOG_FUNC_RETURN (RETURNerror);
     }
 
 #ifdef NAS_MME
     /* Stop the retransmission timer if still running */
-    if (ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
+    if (ebr_ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
         LOG_TRACE(INFO, "ESM-FSM   - Stop retransmission timer %d",
-                  ctx->timer.id);
-        ctx->timer.id = nas_timer_stop(ctx->timer.id);
+                  ebr_ctx->timer.id);
+        ebr_ctx->timer.id = nas_timer_stop(ebr_ctx->timer.id);
     }
     /* Release the retransmisison timer parameters */
-    if (ctx->args) {
-        if (ctx->args->msg.length > 0) {
-            free(ctx->args->msg.value);
+    if (ebr_ctx->args) {
+        if (ebr_ctx->args->msg.length > 0) {
+            free(ebr_ctx->args->msg.value);
         }
-        free(ctx->args);
-        ctx->args = NULL;
+        free(ebr_ctx->args);
+        ebr_ctx->args = NULL;
     }
 #endif
 
     /* Release EPS bearer context data */
-    free(_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]);
-    _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] = NULL;
+    free(ebr_ctx);
+    ebr_ctx = NULL;
 
     LOG_TRACE(INFO, "ESM-FSM   - EPS bearer context %d released", ebi);
     LOG_FUNC_RETURN (RETURNok);
@@ -353,57 +354,56 @@ int esm_ebr_release(
  **      Others:    _esm_ebr_data                              **
  **                                                                        **
  ***************************************************************************/
-int esm_ebr_start_timer( unsigned int ueid, int ebi, const OctetString *msg,
-                         long sec, nas_timer_callback_t cb)
+int esm_ebr_start_timer(emm_data_context_t *ctx, int ebi, const OctetString *msg,
+                        long sec, nas_timer_callback_t cb)
 {
+    esm_ebr_context_t *ebr_ctx;
+
     LOG_FUNC_IN;
 
-    if (ueid >= ESM_EBR_NB_UE_MAX) {
-        LOG_FUNC_RETURN (RETURNerror);
-    }
     if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
         LOG_FUNC_RETURN (RETURNerror);
     }
 
     /* Get EPS bearer context data */
-    esm_ebr_context_t *ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
-    if ( (ctx == NULL) || (ctx->ebi != ebi) ) {
+    ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
+    if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) {
         /* EPS bearer context not assigned */
         LOG_FUNC_RETURN (RETURNerror);
     }
 
-    if (ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
-        if (ctx->args) {
+    if (ebr_ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
+        if (ebr_ctx->args) {
             /* Re-start the retransmission timer */
-            ctx->timer.id = nas_timer_restart(ctx->timer.id);
+            ebr_ctx->timer.id = nas_timer_restart(ebr_ctx->timer.id);
         }
     } else {
         /* Setup the retransmission timer parameters */
-        ctx->args = (esm_ebr_timer_data_t *)malloc(sizeof(esm_ebr_timer_data_t));
-        if (ctx->args) {
+        ebr_ctx->args = (esm_ebr_timer_data_t *)malloc(sizeof(esm_ebr_timer_data_t));
+        if (ebr_ctx->args) {
             /* Set the UE identifier */
-            ctx->args->ueid = ueid;
+            ebr_ctx->args->ueid = ctx->ueid;
             /* Set the EPS bearer identity */
-            ctx->args->ebi = ebi;
+            ebr_ctx->args->ebi = ebi;
             /* Reset the retransmission counter */
-            ctx->args->count = 0;
+            ebr_ctx->args->count = 0;
             /* Set the ESM message to be re-transmited */
-            ctx->args->msg.value = (uint8_t *)malloc(msg->length);
-            ctx->args->msg.length = 0;
-            if (ctx->args->msg.value) {
-                memcpy(ctx->args->msg.value, msg->value, msg->length);
-                ctx->args->msg.length = msg->length;
+            ebr_ctx->args->msg.value = (uint8_t *)malloc(msg->length);
+            ebr_ctx->args->msg.length = 0;
+            if (ebr_ctx->args->msg.value) {
+                memcpy(ebr_ctx->args->msg.value, msg->value, msg->length);
+                ebr_ctx->args->msg.length = msg->length;
             }
             /* Setup the retransmission timer to expire at the given
              * time interval */
-            ctx->timer.id = nas_timer_start(sec, cb, ctx->args);
-            ctx->timer.sec = sec;
+            ebr_ctx->timer.id = nas_timer_start(sec, cb, ebr_ctx->args);
+            ebr_ctx->timer.sec = sec;
         }
     }
 
-    if ( (ctx->args != NULL) && (ctx->timer.id != NAS_TIMER_INACTIVE_ID) ) {
+    if ( (ebr_ctx->args != NULL) && (ebr_ctx->timer.id != NAS_TIMER_INACTIVE_ID) ) {
         LOG_TRACE(INFO, "ESM-FSM   - Retransmission timer %d expires in "
-                  "%ld seconds", ctx->timer.id, ctx->timer.sec);
+                  "%ld seconds", ebr_ctx->timer.id, ebr_ctx->timer.sec);
         LOG_FUNC_RETURN (RETURNok);
     }
     LOG_FUNC_RETURN (RETURNerror);
@@ -425,38 +425,37 @@ int esm_ebr_start_timer( unsigned int ueid, int ebi, const OctetString *msg,
  **      Others:    _esm_ebr_data                              **
  **                                                                        **
  ***************************************************************************/
-int esm_ebr_stop_timer( unsigned int ueid, int ebi)
+int esm_ebr_stop_timer(emm_data_context_t *ctx, int ebi)
 {
+    esm_ebr_context_t *ebr_ctx ;
+
     LOG_FUNC_IN;
 
-    if (ueid >= ESM_EBR_NB_UE_MAX) {
-        LOG_FUNC_RETURN (RETURNerror);
-    }
     if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
         LOG_FUNC_RETURN (RETURNerror);
     }
 
     /* Get EPS bearer context data */
-    esm_ebr_context_t *ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
-    if ( (ctx == NULL) || (ctx->ebi != ebi) ) {
+    ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
+    if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) {
         /* EPS bearer context not assigned */
         LOG_FUNC_RETURN (RETURNerror);
     }
 
     /* Stop the retransmission timer if still running */
-    if (ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
+    if (ebr_ctx->timer.id != NAS_TIMER_INACTIVE_ID) {
         LOG_TRACE(INFO, "ESM-FSM   - Stop retransmission timer %d",
-                  ctx->timer.id);
-        ctx->timer.id = nas_timer_stop(ctx->timer.id);
+                ebr_ctx->timer.id);
+        ebr_ctx->timer.id = nas_timer_stop(ebr_ctx->timer.id);
     }
 
     /* Release the retransmisison timer parameters */
-    if (ctx->args) {
-        if (ctx->args->msg.length > 0) {
-            free(ctx->args->msg.value);
+    if (ebr_ctx->args) {
+        if (ebr_ctx->args->msg.length > 0) {
+            free(ebr_ctx->args->msg.value);
         }
-        free(ctx->args);
-        ctx->args = NULL;
+        free(ebr_ctx->args);
+        ebr_ctx->args = NULL;
     }
 
     LOG_FUNC_RETURN (RETURNok);
@@ -480,16 +479,17 @@ int esm_ebr_stop_timer( unsigned int ueid, int ebi)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_ebr_get_pending_ebi(unsigned int ueid, esm_ebr_state status)
+int esm_ebr_get_pending_ebi(emm_data_context_t *ctx, esm_ebr_state status)
 {
+    int i;
+
     LOG_FUNC_IN;
 
-    int i;
     for (i = 0; i < ESM_EBR_DATA_SIZE; i++) {
-        if (_esm_ebr_data[ueid].context[i] == NULL) {
+        if (ctx->esm_data_ctx.ebr.context[i] == NULL) {
             continue;
         }
-        if (_esm_ebr_data[ueid].context[i]->status != status) {
+        if (ctx->esm_data_ctx.ebr.context[i]->status != status) {
             continue;
         }
         /* EPS bearer context entry found */
@@ -497,7 +497,7 @@ int esm_ebr_get_pending_ebi(unsigned int ueid, esm_ebr_state status)
     }
 
     if (i < ESM_EBR_DATA_SIZE) {
-        LOG_FUNC_RETURN (_esm_ebr_data[ueid].context[i]->ebi);
+        LOG_FUNC_RETURN (ctx->esm_data_ctx.ebr.context[i]->ebi);
     }
     /* EPS bearer context entry not found */
     LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
@@ -526,47 +526,56 @@ int esm_ebr_get_pending_ebi(unsigned int ueid, esm_ebr_state status)
  ***************************************************************************/
 int esm_ebr_set_status(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int ebi, esm_ebr_state status, int ue_requested)
 {
-    LOG_FUNC_IN;
-
+    esm_ebr_context_t *ebr_ctx;
     esm_ebr_state old_status;
 
+    LOG_FUNC_IN;
+
 #ifdef NAS_UE
     unsigned int ueid = 0;
-#endif
 
     if (ueid >= ESM_EBR_NB_UE_MAX) {
         LOG_FUNC_RETURN (RETURNerror);
     }
+#else
+    if (ctx == NULL) {
+        LOG_FUNC_RETURN (RETURNerror);
+    }
+#endif
     if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
         LOG_FUNC_RETURN (RETURNerror);
     }
 
     /* Get EPS bearer context data */
-    esm_ebr_context_t *ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
-    if ( (ctx == NULL) || (ctx->ebi != ebi) ) {
+#ifdef NAS_UE
+    ebr_ctx = _esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN];
+#else
+    ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
+#endif
+    if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) {
         /* EPS bearer context not assigned */
         LOG_TRACE(ERROR, "ESM-FSM   - EPS bearer context not assigned "
                   "(ebi=%d)", ebi);
         LOG_FUNC_RETURN (RETURNerror);
     }
 
-    old_status = ctx->status;
+    old_status = ebr_ctx->status;
     if (status < ESM_EBR_STATE_MAX) {
         LOG_TRACE(INFO, "ESM-FSM   - Status of EPS bearer context %d changed:"
                   " %s ===> %s", ebi,
                   _esm_ebr_state_str[old_status], _esm_ebr_state_str[status]);
         if (status != old_status) {
-            ctx->status = status;
+            ebr_ctx->status = status;
 #ifdef NAS_UE
             /*
              * Notify the user that the state of the EPS bearer has changed
              */
-            (*_esm_ebr_callback)(ctx->cid,
-                                 _esm_ebr_pdn_state[ue_requested][ctx->is_default_ebr][status]);
+            (*_esm_ebr_callback)(ebr_ctx->cid,
+                                 _esm_ebr_pdn_state[ue_requested][ebr_ctx->is_default_ebr][status]);
 #endif
             LOG_FUNC_RETURN (RETURNok);
         }
@@ -592,15 +601,31 @@ int esm_ebr_set_status(
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-esm_ebr_state esm_ebr_get_status(
 #ifdef NAS_MME
-    unsigned int ueid,
-#endif
+esm_ebr_state esm_ebr_get_status(
+    emm_data_context_t *ctx,
     int ebi)
 {
+    if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
+        return (ESM_EBR_INACTIVE);
+    }
+    if (ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN] == NULL) {
+        /* EPS bearer context not allocated */
+        return (ESM_EBR_INACTIVE);
+    }
+    if (ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN]->ebi != ebi) {
+        /* EPS bearer context not assigned */
+        return (ESM_EBR_INACTIVE);
+    }
+    return (ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN]->status);
+}
+#endif
+
 #ifdef NAS_UE
+esm_ebr_state esm_ebr_get_status(
+    int ebi)
+{
     unsigned int ueid = 0;
-#endif
 
     if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
         return (ESM_EBR_INACTIVE);
@@ -615,6 +640,7 @@ esm_ebr_state esm_ebr_get_status(
     }
     return (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]->status);
 }
+#endif
 
 /****************************************************************************
  **                                                                        **
@@ -654,17 +680,21 @@ int esm_ebr_is_reserved(int ebi)
  ***************************************************************************/
 int esm_ebr_is_not_in_use(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int ebi)
 {
 #ifdef NAS_UE
     unsigned int ueid = 0;
-#endif
 
     return ( (ebi == ESM_EBI_UNASSIGNED) ||
              (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN] == NULL) ||
              (_esm_ebr_data[ueid].context[ebi - ESM_EBI_MIN]->ebi) != ebi);
+#else
+    return ( (ebi == ESM_EBI_UNASSIGNED) ||
+             (ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN] == NULL) ||
+             (ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN]->ebi) != ebi);
+#endif
 }
 
 /****************************************************************************/
@@ -688,6 +718,27 @@ int esm_ebr_is_not_in_use(
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
+#ifdef NAS_MME
+static int _esm_ebr_get_available_entry(emm_data_context_t *ctx)
+{
+    int i;
+    for (i = ctx->esm_data_ctx.ebr.index; i < ESM_EBR_DATA_SIZE; i++) {
+        if (ctx->esm_data_ctx.ebr.context[i] != NULL) {
+            continue;
+        }
+        return i;
+    }
+    for (i = 0; i < ctx->esm_data_ctx.ebr.index; i++) {
+        if (ctx->esm_data_ctx.ebr.context[i] != NULL) {
+            continue;
+        }
+        return i;
+    }
+    /* No available EBI entry found */
+    return (-1);
+}
+#endif
+#ifdef NAS_UE
 static int _esm_ebr_get_available_entry(unsigned int ueid)
 {
     int i;
@@ -706,3 +757,4 @@ static int _esm_ebr_get_available_entry(unsigned int ueid)
     /* No available EBI entry found */
     return (-1);
 }
+#endif
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.h
index 2a17ad035a3343a42621a3b42dec5e0cbd515182..c6805f05aa1635f44950c3789d9e661c2bf556a7 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr.h
@@ -28,7 +28,6 @@ Description Defines functions used to handle state of EPS bearer contexts
 #endif
 
 #include "nas_timer.h"
-#include "EpsBearerIdentity.h"
 
 /****************************************************************************/
 /*********************  G L O B A L    C O N S T A N T S  *******************/
@@ -41,32 +40,6 @@ Description Defines functions used to handle state of EPS bearer contexts
 /************************  G L O B A L    T Y P E S  ************************/
 /****************************************************************************/
 
-/* EPS bearer context states */
-typedef enum {
-    ESM_EBR_INACTIVE,       /* No EPS bearer context exists     */
-    ESM_EBR_ACTIVE,     /* The EPS bearer context is active,
-                 * in the UE, in the network        */
-#ifdef NAS_MME
-    ESM_EBR_INACTIVE_PENDING,   /* The network has initiated an EPS bearer
-                 * context deactivation towards the UE  */
-    ESM_EBR_MODIFY_PENDING, /* The network has initiated an EPS bearer
-                 * context modification towards the UE  */
-    ESM_EBR_ACTIVE_PENDING, /* The network has initiated an EPS bearer
-                 * context activation towards the UE    */
-#endif
-    ESM_EBR_STATE_MAX
-} esm_ebr_state;
-
-#ifdef NAS_MME
-/* ESM message timer retransmission data */
-typedef struct {
-    unsigned int ueid;      /* Lower layers UE identifier       */
-    unsigned int ebi;       /* EPS bearer identity          */
-    unsigned int count;     /* Retransmission counter       */
-    OctetString msg;        /* Encoded ESM message to re-transmit   */
-} esm_ebr_timer_data_t;
-#endif
-
 /****************************************************************************/
 /********************  G L O B A L    V A R I A B L E S  ********************/
 /****************************************************************************/
@@ -90,20 +63,20 @@ int esm_ebr_is_not_in_use(int ebi);
 
 #ifdef NAS_MME
 void esm_ebr_initialize(void);
-int esm_ebr_assign(unsigned int ueid, int ebi);
-int esm_ebr_release(unsigned int ueid, int ebi);
+int esm_ebr_assign(emm_data_context_t *ctx, int ebi);
+int esm_ebr_release(emm_data_context_t *ctx, int ebi);
 
-int esm_ebr_start_timer(unsigned int ueid, int ebi, const OctetString *msg,
+int esm_ebr_start_timer(emm_data_context_t *ctx, int ebi, const OctetString *msg,
                         long sec, nas_timer_callback_t cb);
-int esm_ebr_stop_timer(unsigned int ueid, int ebi);
+int esm_ebr_stop_timer(emm_data_context_t *ctx, int ebi);
 
-int esm_ebr_get_pending_ebi(unsigned int ueid, esm_ebr_state status);
+int esm_ebr_get_pending_ebi(emm_data_context_t *ctx, esm_ebr_state status);
 
-int esm_ebr_set_status(unsigned int ueid, int ebi, esm_ebr_state status,
+int esm_ebr_set_status(emm_data_context_t *ctx, int ebi, esm_ebr_state status,
                        int ue_requested);
-esm_ebr_state esm_ebr_get_status(unsigned int ueid, int ebi);
+esm_ebr_state esm_ebr_get_status(emm_data_context_t *ctx, int ebi);
 
-int esm_ebr_is_not_in_use(unsigned int ueid, int ebi);
+int esm_ebr_is_not_in_use(emm_data_context_t *ctx, int ebi);
 #endif
 
 #endif /* __ESM_EBR_H__*/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.c b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.c
index 7addde5d5b8e8a5761afda976e83f1fc79a1bebb..bd77766070f103c9c4a93ed624c1301b3ca73761 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.c
@@ -17,18 +17,22 @@ Author      Frederic Maurel
 Description Defines functions used to handle EPS bearer contexts.
 
 *****************************************************************************/
+#include <stdlib.h> // malloc, free
+#include <string.h> // memset
 
-#include "esm_ebr_context.h"
 #include "commonDef.h"
 #include "nas_log.h"
 
-#include "esmData.h"
+#include "emmData.h"
 #include "esm_ebr.h"
 
+#include "esm_ebr_context.h"
+
 #include "emm_sap.h"
 
-#include <stdlib.h> // malloc, free
-#include <string.h> // memset
+#if defined(ENABLE_ITTI)
+# include "assertions.h"
+#endif
 
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
@@ -75,48 +79,53 @@ static int _esm_ebr_context_check_precedence(const network_tft_t *,
  ***************************************************************************/
 int esm_ebr_context_create(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int pid, int ebi, int is_default,
     const network_qos_t *qos, const network_tft_t *tft)
 {
-    LOG_FUNC_IN;
+    int bid;
+    esm_data_context_t *esm_ctx;
+    esm_pdn_t *pdn = NULL;
 
-    esm_data_context_t *ctx;
+    LOG_FUNC_IN;
 
 #ifdef NAS_UE
-    ctx = &_esm_data;
+    esm_ctx = &_esm_data;
 #endif
 #ifdef NAS_MME
+# if defined(EPC_BUILD)
+    esm_ctx = &ctx->esm_data_ctx;
+# else
     if (ueid < ESM_DATA_NB_UE_MAX) {
         ctx = _esm_data.ctx[ueid];
     } else {
         LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
     }
+# endif
 #endif
 
-    int bid = ESM_DATA_EPS_BEARER_MAX;
-    esm_pdn_t *pdn = NULL;
+    bid = ESM_DATA_EPS_BEARER_MAX;
 
     LOG_TRACE(INFO, "ESM-PROC  - Create new %s EPS bearer context (ebi=%d) "
               "for PDN connection (pid=%d)",
               (is_default)? "default" : "dedicated", ebi, pid);
 
     if (pid < ESM_DATA_PDN_MAX) {
-        if (pid != ctx->pdn[pid].pid) {
+        if (pid != esm_ctx->pdn[pid].pid) {
             LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d is "
                       "not valid", pid);
-        } else if (ctx->pdn[pid].data == NULL) {
+        } else if (esm_ctx->pdn[pid].data == NULL) {
             LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                       "allocated", pid);
         }
         /* Check the total number of active EPS bearers */
-        else if (ctx->n_ebrs > ESM_DATA_EPS_BEARER_TOTAL) {
+        else if (esm_ctx->n_ebrs > ESM_DATA_EPS_BEARER_TOTAL) {
             LOG_TRACE(WARNING, "ESM-PROC  - The total number of active EPS"
                       "bearers is exeeded");
         } else {
             /* Get the PDN connection entry */
-            pdn = ctx->pdn[pid].data;
+            pdn = esm_ctx->pdn[pid].data;
             if (is_default) {
                 /* Default EPS bearer entry is defined at index 0 */
                 bid = 0;
@@ -143,7 +152,7 @@ int esm_ebr_context_create(
         if (ebr != NULL) {
             memset(ebr, 0 , sizeof(esm_bearer_t));
             /* Increment the total number of active EPS bearers */
-            ctx->n_ebrs += 1;
+            esm_ctx->n_ebrs += 1;
             /* Increment the number of EPS bearer for this PDN connection */
             pdn->n_bearers += 1;
             /* Setup the EPS bearer data */
@@ -169,10 +178,10 @@ int esm_ebr_context_create(
 
             if (is_default) {
                 /* Set the PDN connection activation indicator */
-                ctx->pdn[pid].is_active = TRUE;
+                esm_ctx->pdn[pid].is_active = TRUE;
                 /* Update the emergency bearer services indicator */
                 if (pdn->is_emergency) {
-                    ctx->emergency = TRUE;
+                    esm_ctx->emergency = TRUE;
                 }
             }
 
@@ -210,28 +219,32 @@ int esm_ebr_context_create(
  ***************************************************************************/
 int esm_ebr_context_release(
 #ifdef NAS_MME
-    unsigned int ueid,
+    emm_data_context_t *ctx,
 #endif
     int ebi, int *pid, int *bid)
 {
-    LOG_FUNC_IN;
+    int found = FALSE;
+    esm_pdn_t *pdn = NULL;
+    esm_data_context_t *esm_ctx;
 
-    esm_data_context_t *ctx;
+    LOG_FUNC_IN;
 
 #ifdef NAS_UE
-    ctx = &_esm_data;
+    esm_ctx = &_esm_data;
 #endif
+
 #ifdef NAS_MME
+# if defined(EPC_BUILD)
+    esm_ctx = &ctx->esm_data_ctx;
+# else
     if (ueid < ESM_DATA_NB_UE_MAX) {
-        ctx = _esm_data.ctx[ueid];
+        ctx = &_esm_data.ctx[ueid];
     } else {
         LOG_FUNC_RETURN (ESM_EBI_UNASSIGNED);
     }
+# endif
 #endif
 
-    int found = FALSE;
-    esm_pdn_t *pdn = NULL;
-
     if (ebi != ESM_EBI_UNASSIGNED) {
         /*
          * The identity of the EPS bearer to released is given;
@@ -241,12 +254,12 @@ int esm_ebr_context_release(
 
         /* Search for active PDN connection */
         for (*pid = 0; *pid < ESM_DATA_PDN_MAX; (*pid)++) {
-            if ( !ctx->pdn[*pid].is_active ) {
+            if ( !esm_ctx->pdn[*pid].is_active ) {
                 continue;
             }
             /* An active PDN connection is found */
-            if (ctx->pdn[*pid].data != NULL) {
-                pdn = ctx->pdn[*pid].data;
+            if (esm_ctx->pdn[*pid].data != NULL) {
+                pdn = esm_ctx->pdn[*pid].data;
                 /* Search for the specified EPS bearer context entry */
                 for (*bid = 0; *bid < pdn->n_bearers; (*bid)++) {
                     if (pdn->bearer[*bid] != NULL) {
@@ -273,17 +286,17 @@ int esm_ebr_context_release(
          * first EPS bearer context entry at index bid = 0
          */
         if (*pid < ESM_DATA_PDN_MAX) {
-            if (*pid != ctx->pdn[*pid].pid) {
+            if (*pid != esm_ctx->pdn[*pid].pid) {
                 LOG_TRACE(ERROR, "ESM-PROC  - PDN connection identifier %d "
                           "is not valid", *pid);
-            } else if (!ctx->pdn[*pid].is_active) {
+            } else if (!esm_ctx->pdn[*pid].is_active) {
                 LOG_TRACE(WARNING,"ESM-PROC  - PDN connection %d is not active",
                           *pid);
-            } else if (ctx->pdn[*pid].data == NULL) {
+            } else if (esm_ctx->pdn[*pid].data == NULL) {
                 LOG_TRACE(ERROR, "ESM-PROC  - PDN connection %d has not been "
                           "allocated", *pid);
             } else {
-                pdn = ctx->pdn[*pid].data;
+                pdn = esm_ctx->pdn[*pid].data;
                 if (pdn->bearer[*bid] != NULL) {
                     ebi = pdn->bearer[*bid]->ebi;
                     found = TRUE;
@@ -317,7 +330,7 @@ int esm_ebr_context_release(
          * to the PDN connection */
         pdn->n_bearers -= 1;
         /* Decrement the total number of active EPS bearers */
-        ctx->n_ebrs -= 1;
+        esm_ctx->n_ebrs -= 1;
 
         if (*bid == 0) {
             /* 3GPP TS 24.301, section 6.4.4.3, 6.4.4.6
@@ -341,7 +354,7 @@ int esm_ebr_context_release(
                                               ESM_EBR_INACTIVE, TRUE);
 #endif
 #ifdef NAS_MME
-                    (void) esm_ebr_set_status(ueid, pdn->bearer[i]->ebi,
+                    (void) esm_ebr_set_status(ctx, pdn->bearer[i]->ebi,
                                               ESM_EBR_INACTIVE, TRUE);
 #endif
                     /* Release EPS bearer data */
@@ -349,7 +362,7 @@ int esm_ebr_context_release(
                     (void) esm_ebr_release(pdn->bearer[i]->ebi);
 #endif
 #ifdef NAS_MME
-                    (void) esm_ebr_release(ueid, pdn->bearer[i]->ebi);
+                    (void) esm_ebr_release(ctx, pdn->bearer[i]->ebi);
 #endif
                     // esm_ebr_release()
                     /* Release dedicated EPS bearer data */
@@ -359,14 +372,14 @@ int esm_ebr_context_release(
                      * to the PDN connection */
                     pdn->n_bearers -= 1;
                     /* Decrement the total number of active EPS bearers */
-                    ctx->n_ebrs -= 1;
+                    esm_ctx->n_ebrs -= 1;
                 }
             }
             /* Reset the PDN connection activation indicator */
-            ctx->pdn[*pid].is_active = FALSE;
+            esm_ctx->pdn[*pid].is_active = FALSE;
             /* Update the emergency bearer services indicator */
             if (pdn->is_emergency) {
-                ctx->emergency = FALSE;
+                esm_ctx->emergency = FALSE;
             }
         }
 
@@ -375,7 +388,7 @@ int esm_ebr_context_release(
          * If the UE locally deactivated all EPS bearer contexts, the UE
          * shall perform a local detach and enter state EMM-DEREGISTERED.
          */
-        if (ctx->n_ebrs == 0) {
+        if (esm_ctx->n_ebrs == 0) {
             emm_sap_t emm_sap;
             emm_sap.primitive = EMMESM_ESTABLISH_CNF;
             emm_sap.u.emm_esm.u.establish.is_attached = FALSE;
@@ -387,7 +400,7 @@ int esm_ebr_context_release(
          * the UE shall consider itself attached for emergency bearer
          * services only.
          */
-        else if ( ctx->emergency && (ctx->n_ebrs == 1) ) {
+        else if (esm_ctx->emergency && (esm_ctx->n_ebrs == 1) ) {
             emm_sap_t emm_sap;
             emm_sap.primitive = EMMESM_ESTABLISH_CNF;
             emm_sap.u.emm_esm.u.establish.is_attached = TRUE;
@@ -396,7 +409,7 @@ int esm_ebr_context_release(
         }
 #endif // NAS_UE
 #ifdef NAS_MME
-        if (ctx->n_ebrs == 0) {
+        if (esm_ctx->n_ebrs == 0) {
             /* TODO: Release the PDN connection and marked the UE as inactive
              * in the network for EPS services (is_attached = FALSE) */
         }
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.h
index d35ab470cda2e833f1c70401e0745c995e0a53dc..362f4a20f137bc29a0ddc2d06e9e10b1e490a00a 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ebr_context.h
@@ -62,10 +62,10 @@ int esm_ebr_context_check_tft(int pid, int ebi, const network_tft_t *tft,
 #endif
 
 #ifdef NAS_MME
-int esm_ebr_context_create(unsigned int ueid, int pid, int ebi, int is_default,
+int esm_ebr_context_create(emm_data_context_t *ctx, int pid, int ebi, int is_default,
                            const network_qos_t *qos, const network_tft_t *tft);
 
-int esm_ebr_context_release(unsigned int ueid, int ebi, int *pid, int *bid);
+int esm_ebr_context_release(emm_data_context_t *ctx, int ebi, int *pid, int *bid);
 #endif
 
 #endif /* __ESM_EBR_CONTEXT_H__ */
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ip.c b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ip.c
index 420d1c291c841e500455b197e737ef0470b0a4e5..a4f1e53447e702550f51f273176836e17edc25cc 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ip.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_ip.c
@@ -1,4 +1,4 @@
-
+#include "emmData.h"
 #include "esmData.h"
 
 char ip_addr_str[100];
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_main.c b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_main.c
index 571574131e4df336ffa1d3861dc38704c7727112..424baed61b5c50710e8aa23cfddd311b863b469d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_main.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_main.c
@@ -23,6 +23,7 @@ Description Defines the EPS Session Management procedure call manager,
 #include "commonDef.h"
 #include "nas_log.h"
 
+#include "emmData.h"
 #include "esmData.h"
 #include "esm_pt.h"
 #include "esm_ebr.h"
@@ -106,11 +107,12 @@ void esm_main_initialize(void)
     if (mme_api_get_esm_config(&_esm_data.conf) != RETURNok) {
         LOG_TRACE(ERROR, "ESM-MAIN  - Failed to get MME configuration data");
     }
-
+# if !defined(EPC_BUILD)
     /* Initialize ESM contexts */
     for (i = 0; i < ESM_DATA_NB_UE_MAX; i++) {
         _esm_data.ctx[i] = NULL;
     }
+# endif
 
     /* Initialize the EPS bearer context manager */
     esm_ebr_initialize();
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h
index 0865c1dc3f19db649926536febdf4abc25e72db0..8e8adafa194fbfed843e48220bffe33905f63c9d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h
@@ -23,6 +23,7 @@ Description Defines the EPS Session Management procedures executed at
 
 #include "networkDef.h"
 #include "OctetString.h"
+#include "emmData.h"
 
 /****************************************************************************/
 /*********************  G L O B A L    C O N S T A N T S  *******************/
@@ -68,7 +69,7 @@ typedef enum {
 typedef int (*esm_proc_procedure_t) (int, int, OctetString *, int);
 #endif
 #ifdef NAS_MME
-typedef int (*esm_proc_procedure_t) (int, unsigned int, int, OctetString *, int);
+typedef int (*esm_proc_procedure_t) (int, emm_data_context_t *, int, OctetString *, int);
 #endif
 
 /* EPS bearer level QoS parameters */
@@ -106,8 +107,8 @@ int esm_proc_status(int is_standalone, int pti, OctetString *msg,
 #endif
 
 #ifdef NAS_MME
-int esm_proc_status_ind(unsigned int ueid, int pti, int ebi, int *esm_cause);
-int esm_proc_status(int is_standalone, unsigned int ueid, int pti,
+int esm_proc_status_ind(emm_data_context_t *ctx, int pti, int ebi, int *esm_cause);
+int esm_proc_status(int is_standalone, emm_data_context_t *ctx, int pti,
                     OctetString *msg, int sent_by_ue);
 #endif
 
@@ -131,14 +132,14 @@ int esm_proc_pdn_connectivity_failure(int is_pending);
 #endif
 
 #ifdef NAS_MME
-int esm_proc_pdn_connectivity_request(unsigned int ueid, int pti,
+int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
                                       esm_proc_pdn_request_t request_type, OctetString *apn,
                                       esm_proc_pdn_type_t pdn_type, OctetString *pdn_addr, esm_proc_qos_t *esm_qos,
                                       int *esm_cause);
 
-int esm_proc_pdn_connectivity_reject(int is_standalone, unsigned int ueid,
+int esm_proc_pdn_connectivity_reject(int is_standalone, emm_data_context_t *ctx,
                                      int ebi, OctetString *msg, int ue_triggered);
-int esm_proc_pdn_connectivity_failure(unsigned int ueid, int pid);
+int esm_proc_pdn_connectivity_failure(emm_data_context_t *ctx, int pid);
 #endif
 
 /*
@@ -156,10 +157,10 @@ int esm_proc_pdn_disconnect_reject(int pti, int *esm_cause);
 #endif
 
 #ifdef NAS_MME
-int esm_proc_pdn_disconnect_request(unsigned int ueid, int pti, int *esm_cause);
+int esm_proc_pdn_disconnect_request(emm_data_context_t *ctx, int pti, int *esm_cause);
 
-int esm_proc_pdn_disconnect_accept(unsigned int ueid, int pid, int *esm_cause);
-int esm_proc_pdn_disconnect_reject(int is_standalone, unsigned int ueid,
+int esm_proc_pdn_disconnect_accept(emm_data_context_t *ctx, int pid, int *esm_cause);
+int esm_proc_pdn_disconnect_reject(int is_standalone, emm_data_context_t *ctx,
                                    int ebi, OctetString *msg, int ue_triggered);
 #endif
 
@@ -169,15 +170,15 @@ int esm_proc_pdn_disconnect_reject(int is_standalone, unsigned int ueid,
  * --------------------------------------------------------------------------
  */
 #ifdef NAS_MME
-int esm_proc_default_eps_bearer_context(unsigned int ueid, int pid,
+int esm_proc_default_eps_bearer_context(emm_data_context_t *ctx, int pid,
                                         unsigned int *ebi, const esm_proc_qos_t *esm_qos, int *esm_cause);
 int esm_proc_default_eps_bearer_context_request(int is_standalone,
-        unsigned int ueid, int ebi, OctetString *msg, int ue_triggered);
-int esm_proc_default_eps_bearer_context_failure(unsigned int ueid);
+        emm_data_context_t *ctx, int ebi, OctetString *msg, int ue_triggered);
+int esm_proc_default_eps_bearer_context_failure(emm_data_context_t *ctx);
 
-int esm_proc_default_eps_bearer_context_accept(unsigned int ueid, int ebi,
+int esm_proc_default_eps_bearer_context_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause);
-int esm_proc_default_eps_bearer_context_reject(unsigned int ueid, int ebi,
+int esm_proc_default_eps_bearer_context_reject(emm_data_context_t *ctx, int ebi,
         int *esm_cause);
 #endif
 
@@ -199,15 +200,15 @@ int esm_proc_default_eps_bearer_context_reject(int is_standalone, int ebi,
  * --------------------------------------------------------------------------
  */
 #ifdef NAS_MME
-int esm_proc_dedicated_eps_bearer_context(unsigned int ueid, int pid,
+int esm_proc_dedicated_eps_bearer_context(emm_data_context_t *ctx, int pid,
         unsigned int *ebi, unsigned int *default_ebi, const esm_proc_qos_t *qos,
         const esm_proc_tft_t *tft, int *esm_cause);
 int esm_proc_dedicated_eps_bearer_context_request(int is_standalone,
-        unsigned int ueid, int ebi, OctetString *msg, int ue_triggered);
+        emm_data_context_t *ctx, int ebi, OctetString *msg, int ue_triggered);
 
-int esm_proc_dedicated_eps_bearer_context_accept(unsigned int ueid, int ebi,
+int esm_proc_dedicated_eps_bearer_context_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause);
-int esm_proc_dedicated_eps_bearer_context_reject(unsigned int ueid, int ebi,
+int esm_proc_dedicated_eps_bearer_context_reject(emm_data_context_t *ctx, int ebi,
         int *esm_cause);
 #endif
 
@@ -227,12 +228,12 @@ int esm_proc_dedicated_eps_bearer_context_reject(int is_standalone, int ebi,
  * --------------------------------------------------------------------------
  */
 #ifdef NAS_MME
-int esm_proc_eps_bearer_context_deactivate(unsigned int ueid, int is_local,
-        int ebi, int *pid, int *bid, int *esm_cause);
+int esm_proc_eps_bearer_context_deactivate(emm_data_context_t *ctx, int is_local,
+        int ebi, int *pid, int *bid,
+        int *esm_cause);
 int esm_proc_eps_bearer_context_deactivate_request(int is_standalone,
-        unsigned int ueid, int ebi, OctetString *msg, int ue_triggered);
-
-int esm_proc_eps_bearer_context_deactivate_accept(unsigned int ueid, int ebi,
+        emm_data_context_t *ctx, int ebi, OctetString *msg, int ue_triggered);
+int esm_proc_eps_bearer_context_deactivate_accept(emm_data_context_t *ctx, int ebi,
         int *esm_cause);
 #endif
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c
index 19b9af2ab2e302f091e740d6525bc2bc9445bece..a9258de8b764448a472f23bf4a20a6a8ed559041 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c
@@ -74,15 +74,15 @@ Description Defines functions executed at the ESM Service Access
 int esm_recv_status(int pti, int ebi, const esm_status_msg *msg)
 #endif
 #ifdef NAS_MME
-int esm_recv_status(unsigned int ueid, int pti, int ebi,
+int esm_recv_status(emm_data_context_t *ctx, int pti, int ebi,
                     const esm_status_msg *msg)
 #endif
 {
-    LOG_FUNC_IN;
-
     int esm_cause;
     int rc;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO, "ESM-SAP   - Received ESM status message (pti=%d, ebi=%d)",
               pti, ebi);
 
@@ -97,7 +97,7 @@ int esm_recv_status(unsigned int ueid, int pti, int ebi,
     rc = esm_proc_status_ind(pti, ebi, &esm_cause);
 #endif
 #ifdef NAS_MME
-    rc = esm_proc_status_ind(ueid, pti, ebi, &esm_cause);
+    rc = esm_proc_status_ind(ctx, pti, ebi, &esm_cause);
 #endif
     if (rc != RETURNerror) {
         esm_cause = ESM_CAUSE_SUCCESS;
@@ -678,16 +678,16 @@ int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_pdn_connectivity_request(unsigned int ueid, int pti, int ebi,
+int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
                                       const pdn_connectivity_request_msg *msg,
                                       unsigned int *new_ebi, void *data)
 {
-    LOG_FUNC_IN;
-
     int esm_cause = ESM_CAUSE_SUCCESS;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO, "ESM-SAP   - Received PDN Connectivity Request message "
-              "(ueid=%d, pti=%d, ebi=%d)", ueid, pti, ebi);
+              "(ueid=%u, pti=%d, ebi=%d)", ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -767,7 +767,7 @@ int esm_recv_pdn_connectivity_request(unsigned int ueid, int pti, int ebi,
     }
 
     /* Execute the PDN connectivity procedure requested by the UE */
-    int pid = esm_proc_pdn_connectivity_request(ueid, pti, request_type,
+    int pid = esm_proc_pdn_connectivity_request(ctx, pti, request_type,
               &esm_data->apn,
               esm_data->pdn_type,
               &esm_data->pdn_addr,
@@ -775,7 +775,7 @@ int esm_recv_pdn_connectivity_request(unsigned int ueid, int pti, int ebi,
               &esm_cause);
     if (pid != RETURNerror) {
         /* Create local default EPS bearer context */
-        int rc = esm_proc_default_eps_bearer_context(ueid, pid, new_ebi,
+        int rc = esm_proc_default_eps_bearer_context(ctx, pid, new_ebi,
                  &esm_data->qos, &esm_cause);
         if (rc != RETURNerror) {
             esm_cause = ESM_CAUSE_SUCCESS;
@@ -806,7 +806,7 @@ int esm_recv_pdn_connectivity_request(unsigned int ueid, int pti, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_pdn_disconnect_request(unsigned int ueid, int pti, int ebi,
+int esm_recv_pdn_disconnect_request(emm_data_context_t *ctx, int pti, int ebi,
                                     const pdn_disconnect_request_msg *msg,
                                     unsigned int *linked_ebi)
 {
@@ -815,7 +815,7 @@ int esm_recv_pdn_disconnect_request(unsigned int ueid, int pti, int ebi,
     int esm_cause = ESM_CAUSE_SUCCESS;
 
     LOG_TRACE(INFO, "ESM-SAP   - Received PDN Disconnect Request message "
-              "(ueid=%d, pti=%d, ebi=%d)", ueid, pti, ebi);
+              "(ueid=%d, pti=%d, ebi=%d)", ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -842,14 +842,14 @@ int esm_recv_pdn_disconnect_request(unsigned int ueid, int pti, int ebi,
      * Message processing
      */
     /* Execute the PDN disconnect procedure requested by the UE */
-    int pid = esm_proc_pdn_disconnect_request(ueid, pti, &esm_cause);
+    int pid = esm_proc_pdn_disconnect_request(ctx, pti, &esm_cause);
     if (pid != RETURNerror) {
         /* Get the identity of the default EPS bearer context assigned to
          * the PDN connection to disconnect from */
         *linked_ebi = msg->linkedepsbeareridentity;
         /* Release the associated default EPS bearer context */
         int bid = 0;
-        int rc = esm_proc_eps_bearer_context_deactivate(ueid, FALSE,
+        int rc = esm_proc_eps_bearer_context_deactivate(ctx, FALSE,
                  *linked_ebi,
                  &pid, &bid, &esm_cause);
         if (rc != RETURNerror) {
@@ -880,7 +880,7 @@ int esm_recv_pdn_disconnect_request(unsigned int ueid, int pti, int ebi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
+int esm_recv_activate_default_eps_bearer_context_accept(emm_data_context_t *ctx,
         int pti, int ebi,
         const activate_default_eps_bearer_context_accept_msg *msg)
 {
@@ -889,7 +889,7 @@ int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
     int esm_cause = ESM_CAUSE_SUCCESS;
 
     LOG_TRACE(INFO, "ESM-SAP   - Received Activate Default EPS Bearer Context "
-              "Accept message (ueid=%d, pti=%d, ebi=%d)", ueid, pti, ebi);
+              "Accept message (ueid=%d, pti=%d, ebi=%d)", ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -904,7 +904,7 @@ int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
     /*
      * EPS bearer identity checking
      */
-    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ueid, ebi) ) {
+    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ctx, ebi) ) {
         /* 3GPP TS 24.301, section 7.3.2, case f
          * Reserved or assigned value that does not match an existing EPS
          * bearer context
@@ -918,7 +918,7 @@ int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
      */
     /* Execute the default EPS bearer context activation procedure accepted
      * by the UE */
-    int rc = esm_proc_default_eps_bearer_context_accept(ueid, ebi, &esm_cause);
+    int rc = esm_proc_default_eps_bearer_context_accept(ctx, ebi, &esm_cause);
     if (rc != RETURNerror) {
         esm_cause = ESM_CAUSE_SUCCESS;
     }
@@ -946,7 +946,7 @@ int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
+int esm_recv_activate_default_eps_bearer_context_reject(emm_data_context_t *ctx,
         int pti, int ebi,
         const activate_default_eps_bearer_context_reject_msg *msg)
 {
@@ -955,7 +955,7 @@ int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
     int esm_cause = ESM_CAUSE_SUCCESS;
 
     LOG_TRACE(INFO, "ESM-SAP   - Received Activate Default EPS Bearer Context "
-              "Reject message (ueid=%d, pti=%d, ebi=%d)", ueid, pti, ebi);
+              "Reject message (ueid=%d, pti=%d, ebi=%d)", ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -970,7 +970,7 @@ int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
     /*
      * EPS bearer identity checking
      */
-    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ueid, ebi) ) {
+    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ctx, ebi) ) {
         /* 3GPP TS 24.301, section 7.3.2, case f
          * Reserved or assigned value that does not match an existing EPS
          * bearer context
@@ -984,7 +984,7 @@ int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
      */
     /* Execute the default EPS bearer context activation procedure not accepted
      * by the UE */
-    int rc = esm_proc_default_eps_bearer_context_reject(ueid, ebi, &esm_cause);
+    int rc = esm_proc_default_eps_bearer_context_reject(ctx, ebi, &esm_cause);
     if (rc != RETURNerror) {
         esm_cause = ESM_CAUSE_SUCCESS;
     }
@@ -1012,7 +1012,7 @@ int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
+int esm_recv_activate_dedicated_eps_bearer_context_accept(emm_data_context_t *ctx,
         int pti, int ebi,
         const activate_dedicated_eps_bearer_context_accept_msg *msg)
 {
@@ -1022,7 +1022,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
 
     LOG_TRACE(INFO, "ESM-SAP   - Received Activate Dedicated EPS Bearer "
               "Context Accept message (ueid=%d, pti=%d, ebi=%d)",
-              ueid, pti, ebi);
+              ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -1037,7 +1037,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
     /*
      * EPS bearer identity checking
      */
-    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ueid, ebi) ) {
+    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ctx, ebi) ) {
         /* 3GPP TS 24.301, section 7.3.2, case f
          * Reserved or assigned value that does not match an existing EPS
          * bearer context
@@ -1051,7 +1051,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
      */
     /* Execute the dedicated EPS bearer context activation procedure accepted
      * by the UE */
-    int rc = esm_proc_dedicated_eps_bearer_context_accept(ueid, ebi,
+    int rc = esm_proc_dedicated_eps_bearer_context_accept(ctx, ebi,
              &esm_cause);
     if (rc != RETURNerror) {
         esm_cause = ESM_CAUSE_SUCCESS;
@@ -1080,7 +1080,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
+int esm_recv_activate_dedicated_eps_bearer_context_reject(emm_data_context_t *ctx,
         int pti, int ebi,
         const activate_dedicated_eps_bearer_context_reject_msg *msg)
 {
@@ -1090,7 +1090,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
 
     LOG_TRACE(INFO, "ESM-SAP   - Received Activate Dedicated EPS Bearer "
               "Context Reject message (ueid=%d, pti=%d, ebi=%d)",
-              ueid, pti, ebi);
+              ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -1105,7 +1105,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
     /*
      * EPS bearer identity checking
      */
-    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ueid, ebi) ) {
+    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ctx, ebi) ) {
         /* 3GPP TS 24.301, section 7.3.2, case f
          * Reserved or assigned value that does not match an existing EPS
          * bearer context
@@ -1119,7 +1119,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
      */
     /* Execute the dedicated EPS bearer context activation procedure not
      *  accepted by the UE */
-    int rc = esm_proc_dedicated_eps_bearer_context_reject(ueid, ebi,
+    int rc = esm_proc_dedicated_eps_bearer_context_reject(ctx, ebi,
              &esm_cause);
     if (rc != RETURNerror) {
         esm_cause = ESM_CAUSE_SUCCESS;
@@ -1147,7 +1147,7 @@ int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int esm_recv_deactivate_eps_bearer_context_accept(unsigned int ueid,
+int esm_recv_deactivate_eps_bearer_context_accept(emm_data_context_t *ctx,
         int pti, int ebi,
         const deactivate_eps_bearer_context_accept_msg *msg)
 {
@@ -1156,7 +1156,7 @@ int esm_recv_deactivate_eps_bearer_context_accept(unsigned int ueid,
     int esm_cause = ESM_CAUSE_SUCCESS;
 
     LOG_TRACE(INFO, "ESM-SAP   - Received Deactivate EPS Bearer Context "
-              "Accept message (ueid=%d, pti=%d, ebi=%d)", ueid, pti, ebi);
+              "Accept message (ueid=%d, pti=%d, ebi=%d)", ctx->ueid, pti, ebi);
 
     /*
      * Procedure transaction identity checking
@@ -1171,7 +1171,7 @@ int esm_recv_deactivate_eps_bearer_context_accept(unsigned int ueid,
     /*
      * EPS bearer identity checking
      */
-    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ueid, ebi) ) {
+    else if ( esm_ebr_is_reserved(ebi) || esm_ebr_is_not_in_use(ctx, ebi) ) {
         /* 3GPP TS 24.301, section 7.3.2, case f
          * Reserved or assigned value that does not match an existing EPS
          * bearer context
@@ -1185,11 +1185,11 @@ int esm_recv_deactivate_eps_bearer_context_accept(unsigned int ueid,
      */
     /* Execute the default EPS bearer context activation procedure accepted
      * by the UE */
-    int pid = esm_proc_eps_bearer_context_deactivate_accept(ueid, ebi,
+    int pid = esm_proc_eps_bearer_context_deactivate_accept(ctx, ebi,
               &esm_cause);
     if (pid != RETURNerror) {
         /* Release all the resources reserved for the PDN */
-        int rc = esm_proc_pdn_disconnect_accept(ueid, pid, &esm_cause);
+        int rc = esm_proc_pdn_disconnect_accept(ctx, pid, &esm_cause);
 
         if (rc != RETURNerror) {
             esm_cause = ESM_CAUSE_SUCCESS;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.h b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.h
index cd471f0136d118b9096dda145f88773961469e5e..681619d5ab8d3818263fc56e21ba9875c7bbc2fe 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.h
@@ -23,6 +23,7 @@ Description Defines functions executed at the ESM Service Access
 #define __ESM_RECV_H__
 
 #include "EsmStatus.h"
+#include "emmData.h"
 
 #ifdef NAS_UE
 #include "PdnConnectivityReject.h"
@@ -80,7 +81,7 @@ Description Defines functions executed at the ESM Service Access
 int esm_recv_status(int pti, int ebi, const esm_status_msg *msg);
 #endif
 #ifdef NAS_MME
-int esm_recv_status(unsigned int ueid, int pti, int ebi,
+int esm_recv_status(emm_data_context_t *ctx, int pti, int ebi,
                     const esm_status_msg *msg);
 #endif
 
@@ -124,29 +125,30 @@ int esm_recv_deactivate_eps_bearer_context_request(int pti, int ebi,
  * Transaction related messages
  * ----------------------------
  */
-int esm_recv_pdn_connectivity_request(unsigned int ueid, int pti, int ebi,
+int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
                                       const pdn_connectivity_request_msg *msg, unsigned int *new_ebi, void *data);
 
-int esm_recv_pdn_disconnect_request(unsigned int ueid, int pti, int ebi,
-                                    const pdn_disconnect_request_msg *msg, unsigned int *linked_ebi);
+int esm_recv_pdn_disconnect_request(emm_data_context_t *ctx, int pti, int ebi,
+                                    const pdn_disconnect_request_msg *msg,
+                                    unsigned int *linked_ebi);
 
 /*
  * Messages related to EPS bearer contexts
  * ---------------------------------------
  */
-int esm_recv_activate_default_eps_bearer_context_accept(unsigned int ueid,
+int esm_recv_activate_default_eps_bearer_context_accept(emm_data_context_t *ctx,
         int pti, int ebi, const activate_default_eps_bearer_context_accept_msg *msg);
 
-int esm_recv_activate_default_eps_bearer_context_reject(unsigned int ueid,
+int esm_recv_activate_default_eps_bearer_context_reject(emm_data_context_t *ctx,
         int pti, int ebi, const activate_default_eps_bearer_context_reject_msg *msg);
 
-int esm_recv_activate_dedicated_eps_bearer_context_accept(unsigned int ueid,
+int esm_recv_activate_dedicated_eps_bearer_context_accept(emm_data_context_t *ctx,
         int pti, int ebi, const activate_dedicated_eps_bearer_context_accept_msg *msg);
 
-int esm_recv_activate_dedicated_eps_bearer_context_reject(unsigned int ueid,
+int esm_recv_activate_dedicated_eps_bearer_context_reject(emm_data_context_t *ctx,
         int pti, int ebi, const activate_dedicated_eps_bearer_context_reject_msg *msg);
 
-int esm_recv_deactivate_eps_bearer_context_accept(unsigned int ueid, int pti,
+int esm_recv_deactivate_eps_bearer_context_accept(emm_data_context_t *ctx, int pti,
         int ebi, const deactivate_eps_bearer_context_accept_msg *msg);
 #endif
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sap.c b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sap.c
index 440cdc3978c47e0abbc04996d80f8b157e88aa87..f235873eb439fc71861212b8cda4141b851b50ec 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sap.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sap.c
@@ -53,9 +53,9 @@ static int _esm_sap_send(int msg_type, int is_standalone, int pti, int ebi,
 #endif
 
 #ifdef NAS_MME
-static int _esm_sap_recv(int msg_type, int is_standalone, unsigned int ueid,
+static int _esm_sap_recv(int msg_type, int is_standalone, emm_data_context_t *ctx,
                          const OctetString *req, OctetString *rsp, esm_sap_error_t *err);
-static int _esm_sap_send(int msg_type, int is_standalone, unsigned int ueid,
+static int _esm_sap_send(int msg_type, int is_standalone, emm_data_context_t *ctx,
                          int pti, int ebi, const esm_sap_data_t *data, OctetString *rsp);
 #endif
 
@@ -186,16 +186,16 @@ int esm_sap_send(esm_sap_t *msg)
 #ifdef NAS_MME
             /* The MME received a PDN connectivity request message */
             rc = _esm_sap_recv(PDN_CONNECTIVITY_REQUEST, msg->is_standalone,
-                               msg->ueid, msg->recv, &msg->send, &msg->err);
+                               msg->ctx, msg->recv, &msg->send, &msg->err);
 #endif
             break;
 
         case ESM_PDN_CONNECTIVITY_REJ:
 #ifdef NAS_MME
             /* PDN connectivity locally failed */
-            pid = esm_proc_default_eps_bearer_context_failure(msg->ueid);
+            pid = esm_proc_default_eps_bearer_context_failure(msg->ctx);
             if (pid != RETURNerror) {
-                rc = esm_proc_pdn_connectivity_failure(msg->ueid, pid);
+                rc = esm_proc_pdn_connectivity_failure(msg->ctx, pid);
             }
 #endif
 #ifdef NAS_UE
@@ -264,7 +264,7 @@ int esm_sap_send(esm_sap_t *msg)
 #ifdef NAS_MME
             /* The MME received activate default ESP bearer context accept */
             rc = _esm_sap_recv(ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT,
-                               msg->is_standalone, msg->ueid,
+                               msg->is_standalone, msg->ctx,
                                msg->recv, &msg->send, &msg->err);
 #endif
 #ifdef NAS_UE
@@ -283,7 +283,7 @@ int esm_sap_send(esm_sap_t *msg)
 #ifdef NAS_MME
             /* The MME received activate default ESP bearer context reject */
             rc = _esm_sap_recv(ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT,
-                               msg->is_standalone, msg->ueid,
+                               msg->is_standalone, msg->ctx,
                                msg->recv, &msg->send, &msg->err);
 #endif
 #ifdef NAS_UE
@@ -325,7 +325,7 @@ int esm_sap_send(esm_sap_t *msg)
                     msg->data.eps_bearer_context_deactivate.ebi, &pid, &bid);
 #endif
 #ifdef NAS_MME
-            rc = esm_proc_eps_bearer_context_deactivate(msg->ueid, TRUE,
+            rc = esm_proc_eps_bearer_context_deactivate(msg->ctx, TRUE,
                     msg->data.eps_bearer_context_deactivate.ebi,
                     &pid, &bid, NULL);
 #endif
@@ -341,7 +341,7 @@ int esm_sap_send(esm_sap_t *msg)
                                &msg->send, &msg->err);
 #endif
 #ifdef NAS_MME
-            rc = _esm_sap_recv(-1, msg->is_standalone, msg->ueid,
+            rc = _esm_sap_recv(-1, msg->is_standalone, msg->ctx,
                                msg->recv, &msg->send, &msg->err);
 #endif
             break;
@@ -396,7 +396,7 @@ int esm_sap_send(esm_sap_t *msg)
  ***************************************************************************/
 static int _esm_sap_recv(int msg_type, int is_standalone,
 #ifdef NAS_MME
-                         unsigned int ueid,
+                         emm_data_context_t *ctx,
 #endif
                          const OctetString *req, OctetString *rsp,
                          esm_sap_error_t *err)
@@ -647,7 +647,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                  * received from the UE
                  */
                 esm_cause = esm_recv_activate_default_eps_bearer_context_accept(
-                                ueid, pti, ebi,
+                                ctx, pti, ebi,
                                 &esm_msg.activate_default_eps_bearer_context_accept);
 
                 if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) ||
@@ -668,7 +668,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                  * received from the UE
                  */
                 esm_cause = esm_recv_activate_default_eps_bearer_context_reject(
-                                ueid, pti, ebi,
+                                ctx, pti, ebi,
                                 &esm_msg.activate_default_eps_bearer_context_reject);
 
                 if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) ||
@@ -689,7 +689,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                  * received from the UE
                  */
                 esm_cause = esm_recv_deactivate_eps_bearer_context_accept(
-                                ueid, pti, ebi,
+                                ctx, pti, ebi,
                                 &esm_msg.deactivate_eps_bearer_context_accept);
 
                 if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) ||
@@ -710,7 +710,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                  * received from the UE
                  */
                 esm_cause = esm_recv_activate_dedicated_eps_bearer_context_accept(
-                                ueid, pti, ebi,
+                                ctx, pti, ebi,
                                 &esm_msg.activate_dedicated_eps_bearer_context_accept);
 
                 if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) ||
@@ -731,7 +731,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                  * received from the UE
                  */
                 esm_cause = esm_recv_activate_dedicated_eps_bearer_context_reject(
-                                ueid, pti, ebi,
+                                ctx, pti, ebi,
                                 &esm_msg.activate_dedicated_eps_bearer_context_reject);
 
                 if ( (esm_cause == ESM_CAUSE_INVALID_PTI_VALUE) ||
@@ -759,7 +759,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                 /*
                  * Process PDN connectivity request message received from the UE
                  */
-                esm_cause = esm_recv_pdn_connectivity_request(ueid, pti, ebi,
+                esm_cause = esm_recv_pdn_connectivity_request(ctx, pti, ebi,
                             &esm_msg.pdn_connectivity_request,
                             &ebi, &data);
 
@@ -854,7 +854,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                 /*
                  * Process PDN disconnect request message received from the UE
                  */
-                esm_cause = esm_recv_pdn_disconnect_request(ueid, pti, ebi,
+                esm_cause = esm_recv_pdn_disconnect_request(ctx, pti, ebi,
                             &esm_msg.pdn_disconnect_request, &ebi);
 
                 if (esm_cause != ESM_CAUSE_SUCCESS) {
@@ -890,7 +890,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
                 /*
                  * Process received ESM status message
                  */
-                esm_cause = esm_recv_status(ueid, pti, ebi, &esm_msg.esm_status);
+                esm_cause = esm_recv_status(ctx, pti, ebi, &esm_msg.esm_status);
                 break;
 #endif
 
@@ -935,7 +935,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
         rc = (*esm_procedure)(is_standalone, ebi, rsp, triggered_by_ue);
 #endif
 #ifdef NAS_MME
-        rc = (*esm_procedure)(is_standalone, ueid, ebi, rsp, triggered_by_ue);
+        rc = (*esm_procedure)(is_standalone, ctx, ebi, rsp, triggered_by_ue);
 #endif
         if (is_discarded) {
             /* Return indication that received message has been discarded */
@@ -980,10 +980,10 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
  ***************************************************************************/
 static int _esm_sap_send(int msg_type, int is_standalone,
 #ifdef NAS_MME
-                         unsigned int ueid,
+        emm_data_context_t *ctx,
 #endif
-                         int pti, int ebi, const esm_sap_data_t *data,
-                         OctetString *rsp)
+        int pti, int ebi, const esm_sap_data_t *data,
+        OctetString *rsp)
 {
     LOG_FUNC_IN;
 
@@ -1103,7 +1103,7 @@ static int _esm_sap_send(int msg_type, int is_standalone,
             rc = (*esm_procedure)(is_standalone, pti, rsp, sent_by_ue);
 #endif
 #ifdef NAS_MME
-            rc = (*esm_procedure)(is_standalone, ueid, pti, rsp, sent_by_ue);
+            rc = (*esm_procedure)(is_standalone, ctx, pti, rsp, sent_by_ue);
 #endif
         }
     }
diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h
index 8615db810ae0463df52e09bd022e91697ed85c96..9ead56dcd9af7b97994687276d46034a2b91dd0c 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h
@@ -18,6 +18,9 @@ Description Defines the ESM Service Access Point that provides EPS
         bearer context handling and resources allocation procedures.
 
 *****************************************************************************/
+
+#include "emmData.h"
+
 #ifndef __ESM_SAPDEF_H__
 #define __ESM_SAPDEF_H__
 
@@ -132,11 +135,14 @@ typedef struct {
                  * within this primitive has to be sent/received
                  * standalone or together within an EMM related
                  * message              */
-    unsigned int ueid;      /* Local UE identifier          */
-    esm_sap_error_t err;    /* ESM-SAP error code           */
-    const OctetString *recv;    /* Encoded ESM message received     */
-    OctetString send;       /* Encoded ESM message to be sent   */
-    esm_sap_data_t data;    /* ESM message data parameters      */
+#if defined(NAS_MME)
+    emm_data_context_t *ctx;   /* UE context                       */
+#endif
+    unsigned int ueid;         /* Local UE identifier              */
+    esm_sap_error_t err;       /* ESM-SAP error code               */
+    const OctetString *recv;   /* Encoded ESM message received     */
+    OctetString send;          /* Encoded ESM message to be sent   */
+    esm_sap_data_t data;       /* ESM message data parameters      */
 } esm_sap_t;
 
 /****************************************************************************/
diff --git a/openair-cn/NAS/nas_itti_messaging.c b/openair-cn/NAS/nas_itti_messaging.c
index cd155c5e1ff87078e71ae4e6156387630f387232..772bea21f6cadce53ca5a62a8e148ccd6b3c0170 100644
--- a/openair-cn/NAS/nas_itti_messaging.c
+++ b/openair-cn/NAS/nas_itti_messaging.c
@@ -47,20 +47,6 @@ int nas_itti_dl_data_req(const uint32_t ue_id, void *const data,
 
     return itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
 }
-
-void nas_itti_establish_cnf(const nas_error_code_t error_code, void *const data,
-                            const uint32_t length)
-{
-    MessageDef *message_p;
-
-    message_p = itti_alloc_new_message(TASK_NAS, NAS_CONNECTION_ESTABLISHMENT_CNF);
-
-    NAS_CONN_EST_CNF(message_p).nas_establish_cnf.nasMsg.data   = data;
-    NAS_CONN_EST_CNF(message_p).nas_establish_cnf.nasMsg.length = length;
-    NAS_CONN_EST_CNF(message_p).nas_establish_cnf.errCode       = error_code;
-
-    itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
-}
 #endif
 
 #if defined(UE_BUILD) && defined(NAS_UE)
diff --git a/openair-cn/NAS/nas_itti_messaging.h b/openair-cn/NAS/nas_itti_messaging.h
index 00276211396b65320cb64ebed336c05f5dbab339..6c5c0b374152599feb83c5f8c78ee7775766f395 100644
--- a/openair-cn/NAS/nas_itti_messaging.h
+++ b/openair-cn/NAS/nas_itti_messaging.h
@@ -43,8 +43,21 @@
 int nas_itti_dl_data_req(const uint32_t ue_id, void *const data,
                          const uint32_t length);
 
-void nas_itti_establish_cnf(const nas_error_code_t error_code, void *const data,
-                            const uint32_t length);
+static inline void nas_itti_establish_cnf(const uint32_t ue_id,
+        const nas_error_code_t error_code, void *const data,
+        const uint32_t length)
+{
+    MessageDef *message_p;
+
+    message_p = itti_alloc_new_message(TASK_NAS, NAS_CONNECTION_ESTABLISHMENT_CNF);
+
+    NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).UEid            = ue_id;
+    NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).errCode         = error_code;
+    NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.data     = data;
+    NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.length   = length;
+
+    itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
+}
 
 static inline void nas_itti_auth_info_req(const uint32_t ue_id,
         const imsi_t *const imsi, uint8_t initial_req, const uint8_t *auts)
diff --git a/openair-cn/S1AP/s1ap_eNB_handlers.c b/openair-cn/S1AP/s1ap_eNB_handlers.c
index 72f7e88d1b24255154768f23bcd73368ede3d395..571a96552f6eb61d881ac7ecc94b6b2b7942e26c 100644
--- a/openair-cn/S1AP/s1ap_eNB_handlers.c
+++ b/openair-cn/S1AP/s1ap_eNB_handlers.c
@@ -470,7 +470,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t               assoc_id,
             S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer =
             malloc(sizeof(uint8_t) * item_p->nAS_PDU->size);
 
-            memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer,
+            memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer,
                    item_p->nAS_PDU->buf, item_p->nAS_PDU->size);
         } else {
             S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = 0;
diff --git a/openair-cn/S1AP/s1ap_mme.c b/openair-cn/S1AP/s1ap_mme.c
index e78ce7b5009a8a463bae24518cbab2c7a7505f47..5db35b062007bd1296c21c2df0ef77780feee96a 100644
--- a/openair-cn/S1AP/s1ap_mme.c
+++ b/openair-cn/S1AP/s1ap_mme.c
@@ -151,16 +151,7 @@ void *s1ap_mme_thread(void *args)
             } break;
 #else
             case NAS_CONNECTION_ESTABLISHMENT_CNF: {
-                if (AS_TERMINATED_NAS == NAS_CONN_EST_CNF(received_message_p).nas_establish_cnf.errCode) {
-                    /* Attach rejected by NAS -> send result via
-                     * DL info transfer message
-                     */
-                    s1ap_generate_downlink_nas_transport(NAS_CONN_EST_CNF(received_message_p).ue_id,
-                                                         NAS_CONN_EST_CNF(received_message_p).nas_establish_cnf.nasMsg.data,
-                                                         NAS_CONN_EST_CNF(received_message_p).nas_establish_cnf.nasMsg.length);
-                } else {
-                    s1ap_handle_conn_est_cnf(&NAS_CONN_EST_CNF(received_message_p));
-                }
+                s1ap_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
             } break;
 #endif
 
diff --git a/openair-cn/S1AP/s1ap_mme_nas_procedures.c b/openair-cn/S1AP/s1ap_mme_nas_procedures.c
index 00186f3763983806118aa5d000573b48424527e0..51a16b146b291224ef163b1e9ccac2ee4df949f6 100644
--- a/openair-cn/S1AP/s1ap_mme_nas_procedures.c
+++ b/openair-cn/S1AP/s1ap_mme_nas_procedures.c
@@ -28,6 +28,7 @@
 
 *******************************************************************************/
 
+#include <stdio.h>
 #include <stdint.h>
 
 #include "s1ap_common.h"
@@ -226,7 +227,6 @@ int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data
         s1ap_mme_itti_send_sctp_request(buffer_p, length,
                                         ue_ref->eNB->sctp_assoc_id,
                                         ue_ref->sctp_stream_send);
-        //s1ap_mme_itti_nas_downlink_cnf(ue_ref->mme_ue_s1ap_id, AS_SUCCESS);
     }
     return 0;
 }
@@ -365,26 +365,24 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
      * At least one bearer has been established. We can now send s1ap initial context setup request
      * message to eNB.
      */
-    uint8_t supportedAlgorithms[] = { 0x00, 0x02 };
+    uint8_t supportedAlgorithms[] = { 0x00, 0x00 };
     uint8_t offset = 0;
     uint8_t *buffer_p;
-    uint32_t length;
+    uint32_t length, teid = 12;
 
     ue_description_t *ue_ref = NULL;
     s1ap_message message;
-    s1ap_initial_ctxt_setup_req_t *initial_p;
 
     S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
     S1ap_E_RABToBeSetupItemCtxtSUReq_t    e_RABToBeSetup;
+    S1ap_NAS_PDU_t                        nas_pdu;
 
     DevAssert(nas_conn_est_cnf_p != NULL);
 
-    initial_p = &nas_conn_est_cnf_p->transparent;
-
-    if ((ue_ref = s1ap_is_ue_mme_id_in_list(initial_p->mme_ue_s1ap_id)) == NULL) {
+    if ((ue_ref = s1ap_is_ue_mme_id_in_list(nas_conn_est_cnf_p->UEid)) == NULL) {
         S1AP_DEBUG("This mme ue s1ap id (%08x) is not attached to any UE context\n",
-                   initial_p->mme_ue_s1ap_id);
-        DevParam(initial_p->mme_ue_s1ap_id, 0, 0);
+                nas_conn_est_cnf_p->UEid);
+        DevParam(nas_conn_est_cnf_p->UEid, 0, 0);
     }
 
     /* Start the outcome response timer.
@@ -409,53 +407,72 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
     initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
 
     /* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
-    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
-    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
-
-    e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
-    e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
-    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
-    = initial_p->prio_level; //No priority
-    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
-    = initial_p->pre_emp_capability;
-    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
-    = initial_p->pre_emp_vulnerability;
+//    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
+//    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
+
+    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 1024 * 1024;
+    initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 512 * 1024;
+
+//    e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
+    e_RABToBeSetup.e_RAB_ID = 5;
+//    e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
+    e_RABToBeSetup.e_RABlevelQoSParameters.qCI = 0;
+
+    memset(&nas_pdu, 0, sizeof(nas_pdu));
+
+    nas_pdu.size = nas_conn_est_cnf_p->nasMsg.length;
+    nas_pdu.buf  = nas_conn_est_cnf_p->nasMsg.data;
+
+    e_RABToBeSetup.nAS_PDU = &nas_pdu;
+    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
+            S1ap_PriorityLevel_lowest;
+    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
+            S1ap_Pre_emptionCapability_shall_not_trigger_pre_emption;
+    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
+            S1ap_Pre_emptionVulnerability_not_pre_emptable;
+    INT32_TO_OCTET_STRING(teid, &e_RABToBeSetup.gTP_TEID);
+//    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
+//    = initial_p->prio_level; //No priority
+//    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
+//    = initial_p->pre_emp_capability;
+//    e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
+//    = initial_p->pre_emp_vulnerability;
 
     /* Set the GTP-TEID. This is the S1-U S-GW TEID */
-    INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
+//    INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
 
     /* S-GW IP address(es) for user-plane */
-    if ((initial_p->s_gw_address.pdn_type == IPv4) ||
-        (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
-    {
-        e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
-        /* Only IPv4 supported */
-        memcpy(e_RABToBeSetup.transportLayerAddress.buf,
-               initial_p->s_gw_address.address.ipv4_address,
-               4);
-        offset += 4;
-        e_RABToBeSetup.transportLayerAddress.size = 4;
-        e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
-    }
-    if ((initial_p->s_gw_address.pdn_type == IPv6) ||
-        (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
-    {
-        if (offset == 0) {
-            /* Both IPv4 and IPv6 provided */
-            /* TODO: check memory allocation */
-            e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
-        } else {
-            /* Only IPv6 supported */
-            /* TODO: check memory allocation */
-            e_RABToBeSetup.transportLayerAddress.buf
-            = realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
-        }
-        memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
-               initial_p->s_gw_address.address.ipv6_address,
-               16);
-        e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
-        e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
-    }
+//    if ((initial_p->s_gw_address.pdn_type == IPv4) ||
+//        (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
+//    {
+//        e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
+//        /* Only IPv4 supported */
+//        memcpy(e_RABToBeSetup.transportLayerAddress.buf,
+//               initial_p->s_gw_address.address.ipv4_address,
+//               4);
+//        offset += 4;
+//        e_RABToBeSetup.transportLayerAddress.size = 4;
+//        e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
+//    }
+//    if ((initial_p->s_gw_address.pdn_type == IPv6) ||
+//        (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
+//    {
+//        if (offset == 0) {
+//            /* Both IPv4 and IPv6 provided */
+//            /* TODO: check memory allocation */
+//            e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
+//        } else {
+//            /* Only IPv6 supported */
+//            /* TODO: check memory allocation */
+//            e_RABToBeSetup.transportLayerAddress.buf
+//            = realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
+//        }
+//        memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
+//               initial_p->s_gw_address.address.ipv6_address,
+//               16);
+//        e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
+//        e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
+//    }
 
     ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
                      &e_RABToBeSetup);
@@ -473,7 +490,11 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
     initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
         = 0;
 
-    initialContextSetupRequest_p->securityKey.buf  = initial_p->keNB; /* 256 bits length */
+//    initialContextSetupRequest_p->securityKey.buf  = initial_p->keNB; /* 256 bits length */
+    uint8_t keNB[32];
+    memset(keNB, 0, sizeof(keNB));
+
+    initialContextSetupRequest_p->securityKey.buf = keNB;
     initialContextSetupRequest_p->securityKey.size = 32;
     initialContextSetupRequest_p->securityKey.bits_unused = 0;
 
@@ -482,6 +503,8 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
         DevMessage("Failed to encode initial context setup request message\n");
     }
 
+    free(nas_conn_est_cnf_p->nasMsg.data);
+
     s1ap_mme_itti_send_sctp_request(buffer_p, length, ue_ref->eNB->sctp_assoc_id,
                                     ue_ref->sctp_stream_send);
 }
diff --git a/openair-cn/S1AP/s1ap_mme_nas_procedures.h b/openair-cn/S1AP/s1ap_mme_nas_procedures.h
index cc1a58d8570dc8be4d1273126c43345c2c4bbcd7..d088513f84f537d5b0a3c3994adfce1e609416dd 100644
--- a/openair-cn/S1AP/s1ap_mme_nas_procedures.h
+++ b/openair-cn/S1AP/s1ap_mme_nas_procedures.h
@@ -67,7 +67,7 @@ int s1ap_mme_handle_nas_non_delivery(uint32_t assocId, uint32_t stream,
 #if defined(DISABLE_USE_NAS)
 int s1ap_handle_attach_accepted(nas_attach_accept_t *attach_accept_p);
 #else
-void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p);
+void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf);
 #endif
 
 int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data,