diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c
index 90490e327f24e67ca52b6fb14123ce1e0fb72187..832f785551b08fb37208621f1c3a544b06ec1997 100644
--- a/executables/nr-cuup.c
+++ b/executables/nr-cuup.c
@@ -111,7 +111,7 @@ f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP)
   return NULL;
 }
 
-void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
+void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid)
 {
   abort();
 }
diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h
index 87426eff98416de4c9e568fcbd39026d34517b80..2f9f56e23aad23e8645bda42879db9032a1f9c92 100644
--- a/openair2/COMMON/ngap_messages_types.h
+++ b/openair2/COMMON/ngap_messages_types.h
@@ -263,17 +263,6 @@ typedef enum pdu_session_type_e {
   PDUSessionType_unstructured = 4
 }pdu_session_type_t;
 
-typedef struct ngap_transport_layer_addr_s {
-  /* Length of the transport layer address buffer in bits. NGAP layer received a
-   * bit string<1..160> containing one of the following addresses: ipv4,
-   * ipv6, or ipv4 and ipv6. The layer doesn't interpret the buffer but
-   * silently forward it to NG-U.
-   */
-  uint8_t pdu_session_type;
-  uint8_t length;
-  uint8_t buffer[20]; // in network byte order
-} ngap_transport_layer_addr_t;
-
 typedef struct pdusession_s {
   /* Unique pdusession_id for the UE. */
   int pdusession_id;
@@ -283,11 +272,16 @@ typedef struct pdusession_s {
   /* Quality of service for this pdusession */
   pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
   /* The transport layer address for the IP packets */
-  ngap_transport_layer_addr_t upf_addr;
+  pdu_session_type_t pdu_session_type;
+  transport_layer_addr_t upf_addr;
   /* S-GW Tunnel endpoint identifier */
   uint32_t gtp_teid;
   /* Stores the DRB ID of the DRBs used by this PDU Session */
   uint8_t used_drbs[NGAP_MAX_DRBS_PER_UE];
+  uint32_t gNB_teid_N3;
+  transport_layer_addr_t gNB_addr_N3;
+  uint32_t UPF_teid_N3;
+  transport_layer_addr_t UPF_addr_N3;
 } pdusession_t;
 
 typedef enum pdusession_qosflow_mapping_ind_e{
@@ -306,7 +300,8 @@ typedef struct pdusession_setup_s {
   uint8_t pdusession_id;
 
   /* The transport layer address for the IP packets */
-  ngap_transport_layer_addr_t gNB_addr;
+  uint8_t pdu_session_type;
+  transport_layer_addr_t gNB_addr;
 
   /* UPF Tunnel endpoint identifier */
   uint32_t gtp_teid;
@@ -323,7 +318,8 @@ typedef struct pdusession_tobeswitched_s {
   uint8_t pdusession_id;
 
   /* The transport layer address for the IP packets */
-  ngap_transport_layer_addr_t upf_addr;
+  uint8_t pdu_session_type;
+  transport_layer_addr_t upf_addr;
 
   /* S-GW Tunnel endpoint identifier */
   uint32_t gtp_teid;
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
index fd3f420466c1c9690798a61b621e8e27bcc6ba77..9128b0f50e509bd320ca592a79c42842709f7e89 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
@@ -3808,7 +3808,6 @@ do_RRCConnectionReestablishment(
   LTE_DL_CCCH_Message_t dl_ccch_msg;
   LTE_RRCConnectionReestablishment_t *rrcConnectionReestablishment = NULL;
   int i = 0;
-  ue_context_pP->ue_context.reestablishment_xid = Transaction_id;
   LTE_SRB_ToAddModList_t **SRB_configList2 = NULL;
   SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id];
 
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 1f14eae9f6e82458b349e4069a1e697473cf497c..01ba86bc98c1cac014873f00f3c2520d95b427eb 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -1139,7 +1139,6 @@ int do_RRCReestablishment(const protocol_ctxt_t *const ctxt_pP,
   struct NR_SRB_ToAddMod *SRB2_config = NULL;
   NR_DL_DCCH_Message_t dl_dcch_msg = {0};
   NR_RRCReestablishment_t *rrcReestablishment = NULL;
-  ue_context_pP->ue_context.reestablishment_xid = Transaction_id;
   NR_SRB_ToAddModList_t **SRB_configList2 = NULL;
   SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id];
 
diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c
index 05ec9a837b558085ff5985578836ee00a595c30f..d0d4365e70a8cdc30386f010d197d0cad8ec4548 100644
--- a/openair2/RRC/NR/cucp_cuup_direct.c
+++ b/openair2/RRC/NR/cucp_cuup_direct.c
@@ -179,13 +179,14 @@ static NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, NR_SRB_To
 
   return SRB_configList2;
 }
-static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) {
+static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid)
+{
   rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti);
   gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
   protocol_ctxt_t ctxt = {0};
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
 
-  fill_DRB_configList(&ctxt, ue_context_p);
+  fill_DRB_configList(&ctxt, ue_context_p, xid);
 
   gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
   // Fixme: xid not random, but almost!
@@ -208,7 +209,7 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
   }
 }
 
-static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) {
+static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) {
   instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
   CU_update_UP_DL_tunnel(req, gtpInst, req->rnti);
 }
diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c
index a3311b2ee14681bccca0b814a24853613297c3b2..eeea7ed3a9642bba9401c46a32dee1f985ac5f4a 100644
--- a/openair2/RRC/NR/cucp_cuup_e1ap.c
+++ b/openair2/RRC/NR/cucp_cuup_e1ap.c
@@ -35,12 +35,13 @@
 
 extern RAN_CONTEXT_t RC;
 
-static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) {
+static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid)
+{
   rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti);
   protocol_ctxt_t ctxt = {0};
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0);
 
-  fill_DRB_configList(&ctxt, ue_context_p);
+  fill_DRB_configList(&ctxt, ue_context_p, xid);
   MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ);
   e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p);
   memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t));
@@ -48,7 +49,8 @@ static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const r
   itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p);
 }
 
-static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) {
+static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid)
+{
   MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
   e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg);
   memcpy(req_msg, req, sizeof(*req));
diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h
index 079a32e8506eaf56c3f682d2b9c269cd7527983d..ed4702b4b28659435494f504acc19e9da90a5532 100644
--- a/openair2/RRC/NR/cucp_cuup_if.h
+++ b/openair2/RRC/NR/cucp_cuup_if.h
@@ -27,7 +27,7 @@
 
 struct e1ap_bearer_setup_req_s;
 struct e1ap_bearer_setup_resp_s;
-typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance);
+typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance, uint8_t xid);
 
 struct gNB_RRC_INST_s;
 void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc);
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 942e9ffb1f1889c9e05b3eb5301c20b63942bfb4..9887d8936740f8c5324950dcef60dbefc5bae18f 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -128,7 +128,7 @@ typedef enum UE_STATE_NR_e {
 #define NO_SECURITY_MODE                              0x20
 
 /* TS 36.331: RRC-TransactionIdentifier ::= INTEGER (0..3) */
-#define NR_RRC_TRANSACTION_IDENTIFIER_NUMBER             3
+#define NR_RRC_TRANSACTION_IDENTIFIER_NUMBER 4
 
 typedef struct {
   unsigned short                                      transport_block_size;      /*!< \brief Minimum PDU size in bytes provided by RLC to MAC layer interface */
@@ -258,14 +258,15 @@ typedef enum pdu_session_satus_e {
   PDU_SESSION_STATUS_DONE,
   PDU_SESSION_STATUS_ESTABLISHED,
   PDU_SESSION_STATUS_REESTABLISHED, // after HO
-  PDU_SESSION_STATUS_TOMODIFY,      // ENDC NSA
+  PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA
   PDU_SESSION_STATUS_FAILED,
-  PDU_SESSION_STATUS_TORELEASE  // to release DRB between eNB and UE
+  PDU_SESSION_STATUS_TORELEASE, // to release DRB between eNB and UE
+  PDU_SESSION_STATUS_RELEASED
 } pdu_session_status_t;
 
 typedef struct pdu_session_param_s {
   pdusession_t param;
-  uint8_t status;
+  pdu_session_status_t status;
   uint8_t xid; // transaction_id
   ngap_Cause_t cause;
   uint8_t cause_value;
@@ -305,6 +306,19 @@ typedef struct drb_s {
   } pdcp_config;
 } drb_t;
 
+typedef enum {
+  RRC_FIRST_RECONF,
+  RRC_SETUP,
+  RRC_SETUP_FOR_REESTABLISHMENT,
+  RRC_REESTABLISH,
+  RRC_REESTABLISH_COMPLETE,
+  RRC_DEFAULT_RECONF,
+  RRC_DEDICATED_RECONF,
+  RRC_PDUSESSION_ESTABLISH,
+  RRC_PDUSESSION_MODIFY,
+  RRC_PDUSESSION_RELEASE
+} rrc_action_t;
+
 typedef struct gNB_RRC_UE_s {
   uint8_t                            primaryCC_id;
   NR_SRB_ToAddModList_t             *SRB_configList;
@@ -369,38 +383,20 @@ typedef struct gNB_RRC_UE_s {
   nr_rrc_guami_t                     ue_guami;
 
   ngap_security_capabilities_t       security_capabilities;
-
-  /* Total number of e_rab already setup in the list */
-  uint8_t                           setup_e_rabs;
-  /* Number of e_rab to be setup in the list */
+  //NSA block
+  /* Number of NSA e_rab */
   uint8_t                            nb_of_e_rabs;
-  /* Number of e_rab to be modified in the list */
-  uint8_t                            nb_of_modify_e_rabs;
-  uint8_t                            nb_of_failed_e_rabs;
-  nr_e_rab_param_t                   modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
-  /* Number of pdu session managed for the ue */
-  uint8_t                            nb_of_pdusessions;
-  /* Number of e_rab to be modified in the list */
-  uint8_t                            nb_of_modify_pdusessions;
-  uint8_t                            nb_of_failed_pdusessions;
-  rrc_pdu_session_param_t modify_pdusession[NR_NB_RB_MAX];
-  /* list of e_rab to be setup by RRC layers */
   /* list of pdu session to be setup by RRC layers */
   nr_e_rab_param_t                   e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
-  rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION];
-  //release e_rabs
-  uint8_t                            nb_release_of_e_rabs;
-  e_rab_failed_t                     e_rabs_release_failed[S1AP_MAX_E_RAB];
-  uint8_t                            nb_release_of_pdusessions;
-  pdusession_failed_t                pdusessions_release_failed[NGAP_MAX_PDUSESSION];
-  // LG: For GTPV1 TUNNELS
-  uint32_t                           gnb_gtp_teid[S1AP_MAX_E_RAB];
-  transport_layer_addr_t             gnb_gtp_addrs[S1AP_MAX_E_RAB];
-  rb_id_t                            gnb_gtp_ebi[S1AP_MAX_E_RAB];
-  rb_id_t                            gnb_gtp_psi[S1AP_MAX_E_RAB];
-  //GTPV1 F1-U TUNNELS
-  uint32_t                           incoming_teid[S1AP_MAX_E_RAB];
+  uint32_t                           nsa_gtp_teid[S1AP_MAX_E_RAB];
+  transport_layer_addr_t             nsa_gtp_addrs[S1AP_MAX_E_RAB];
+  rb_id_t                            nsa_gtp_ebi[S1AP_MAX_E_RAB];
+  rb_id_t                            nsa_gtp_psi[S1AP_MAX_E_RAB];
 
+  //SA block
+  int nb_of_pdusessions;
+  rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION];
+  rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
   uint32_t                           ul_failure_timer;
   uint32_t                           ue_release_timer;
   uint32_t                           ue_release_timer_thres;
@@ -412,11 +408,8 @@ typedef struct gNB_RRC_UE_s {
   uint32_t                           ue_release_timer_thres_rrc;
   uint32_t                           ue_reestablishment_timer;
   uint32_t                           ue_reestablishment_timer_thres;
-  uint8_t                            e_rab_release_command_flag;
-  uint8_t                            pdu_session_release_command_flag;
-  uint8_t                            established_pdu_sessions_flag;
-  uint32_t                           ue_rrc_inactivity_timer;
-  int8_t                             reestablishment_xid;
+  uint8_t e_rab_release_command_flag;
+  uint32_t ue_rrc_inactivity_timer;
   uint32_t                           ue_reestablishment_counter;
   uint32_t                           ue_reconfiguration_after_reestablishment_counter;
   NR_CellGroupId_t                                      cellGroupId;
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 87d786b773791127ad4193c5a37f58b3acfd439a..ee236e14084fd57e9bcf88e8d758c2af16f0b7b8 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -164,8 +164,7 @@ void ue_cxt_mod_send_e1ap(MessageDef *msg,
 void ue_cxt_mod_direct(MessageDef *msg,
                        instance_t instance);
 
-void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP,
-                         rrc_gNB_ue_context_t *ue_context_pP);
+void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid);
 
 void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
                                                  e1ap_bearer_setup_resp_t *e1ap_resp);
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 81a17afab1fcf81ec396838a66ab216790e9a90b..9c7a58c08161094e934f8477d06e1a35c8ec0639 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -106,8 +106,7 @@ extern RAN_CONTEXT_t RC;
 
 static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn);
 
-mui_t                               rrc_gNB_mui = 0;
-uint8_t first_rrcreconfiguration = 0;
+mui_t rrc_gNB_mui = 0;
 
 ///---------------------------------------------------------------------------------------------------------------///
 ///---------------------------------------------------------------------------------------------------------------///
@@ -349,7 +348,9 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance,
   gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
   gNB_RRC_INST *rrc = RC.nrrrc[instance];
   unsigned char buf[1024];
-  int size = do_RRCSetup(ue_context_pP, buf, rrc_gNB_get_next_transaction_identifier(instance), masterCellGroup, masterCellGroup_len, &rrc->configuration);
+  uint8_t xid = rrc_gNB_get_next_transaction_identifier(instance);
+  ue_p->xids[xid] = RRC_SETUP;
+  int size = do_RRCSetup(ue_context_pP, buf, xid, masterCellGroup, masterCellGroup_len, &rrc->configuration);
   AssertFatal(size > 0, "do_RRCSetup failed\n");
   AssertFatal(size <= 1024, "memory corruption\n");
 
@@ -376,7 +377,7 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance,
 }
 
 //-----------------------------------------------------------------------------
-static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t module_id, rnti_t rnti, const int CC_id)
+static int rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t module_id, rnti_t rnti, const int CC_id)
 //-----------------------------------------------------------------------------
 {
   LOG_I(NR_RRC, "generate RRCSetup for RRCReestablishmentRequest \n");
@@ -387,7 +388,9 @@ static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t
 
   gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
   unsigned char buf[1024];
-  int size = do_RRCSetup(ue_context_pP, buf, rrc_gNB_get_next_transaction_identifier(module_id), NULL, 0, &rrc_instance_p->configuration);
+  uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id);
+  ue_p->xids[xid] = RRC_SETUP_FOR_REESTABLISHMENT;
+  int size = do_RRCSetup(ue_context_pP, buf, xid, NULL, 0, &rrc_instance_p->configuration);
   AssertFatal(size > 0, "do_RRCSetup failed\n");
   AssertFatal(size <= 1024, "memory corruption\n");
 
@@ -433,6 +436,7 @@ static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t
     .srb_id = CCCH
   };
   rrc_instance_p->mac_rrc.dl_rrc_message_transfer(module_id, &dl_rrc);
+  return xid;
 }
 
 static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context_t *const ue_context_pP)
@@ -492,11 +496,10 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
 //-----------------------------------------------------------------------------
 {
   gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
-  uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
-
-  /******************** Radio Bearer Config ********************/
   gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
   AssertFatal(ue_p->nb_of_pdusessions == 0, "logic bug: PDU sessions present before RRC Connection established\n");
+  uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
+  ue_p->xids[xid] = RRC_DEFAULT_RECONF;
 
   struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList));
 
@@ -583,9 +586,8 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co
   }
 }
 
-void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP,
-                         rrc_gNB_ue_context_t *ue_context_pP) {
-
+void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, uint8_t xid)
+{
   gNB_RRC_INST                  *rrc = RC.nrrrc[ctxt_pP->module_id];
   gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
   int qos_flow_index = 0;
@@ -594,8 +596,6 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP,
   uint8_t nb_drb_to_setup = rrc->configuration.drbs;
   long drb_priority[NGAP_MAX_DRBS_PER_UE];
 
-  int xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
-
   if (!ue_p->DRB_configList)
     ue_p->DRB_configList = CALLOC(1, sizeof(*ue_p->DRB_configList));
   else
@@ -780,58 +780,53 @@ rrc_gNB_modify_dedicatedRRCReconfiguration(
   rrc_gNB_ue_context_t      *ue_context_pP)
 //-----------------------------------------------------------------------------
 {
-  NR_DRB_ToAddMod_t             *DRB_config           = NULL;
-  NR_DRB_ToAddModList_t        **DRB_configList  = NULL;
+  NR_DRB_ToAddMod_t *DRB_config = NULL;
   NR_DRB_ToAddModList_t         *DRB_configList2 = NULL;
   struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList
                                 *dedicatedNAS_MessageList = NULL;
-  NR_DedicatedNAS_Message_t     *dedicatedNAS_Message = NULL;
-  int                            qos_flow_index = 0;
-  int i, j;
-
+  int qos_flow_index = 0;
   uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
   gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
-  DRB_configList = &ue_p->DRB_configList;
+  ue_p->xids[xid] = RRC_DEDICATED_RECONF;
 
   DRB_configList2 = CALLOC(1, sizeof(NR_DRB_ToAddModList_t));
   memset(DRB_configList2, 0, sizeof(NR_DRB_ToAddModList_t));
 
   dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList));
 
-  for (i = 0; i < ue_p->nb_of_modify_pdusessions; i++) {
+  for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
     // bypass the new and already configured pdu sessions
-    if (ue_p->modify_pdusession[i].status >= PDU_SESSION_STATUS_DONE) {
-      ue_p->modify_pdusession[i].xid = xid;
+    if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) {
+      ue_p->pduSession[i].xid = xid;
       continue;
     }
 
-    if (ue_p->modify_pdusession[i].cause != NGAP_CAUSE_NOTHING) {
+    if (ue_p->pduSession[i].cause != NGAP_CAUSE_NOTHING) {
       // set xid of failure pdu session
-      ue_p->modify_pdusession[i].xid = xid;
-      ue_p->modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
+      ue_p->pduSession[i].xid = xid;
+      ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
       continue;
     }
 
     // search exist DRB_config
-    for (j = 0; j < (*DRB_configList)->list.count; j++) {
-      if ((*DRB_configList)->list.array[j]->cnAssociation->choice.sdap_Config->pdu_Session == ue_p->modify_pdusession[i].param.pdusession_id) {
-        DRB_config = (*DRB_configList)->list.array[j];
+    int j;
+    for (j = 0; i < NGAP_MAX_DRBS_PER_UE; j++) {
+      if (ue_p->established_drbs[j].status != DRB_INACTIVE
+          && ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == ue_p->pduSession[i].param.pdusession_id)
         break;
-      }
     }
 
-    if (DRB_config == NULL) {
-      ue_p->modify_pdusession[i].xid = xid;
-      ue_p->modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
-      ue_p->modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
-      ue_p->modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_unspecified;
-      ue_p->nb_of_failed_pdusessions++;
+    if (j == NGAP_MAX_DRBS_PER_UE) {
+      ue_p->pduSession[i].xid = xid;
+      ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
+      ue_p->pduSession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
+      ue_p->pduSession[i].cause_value = NGAP_CauseRadioNetwork_unspecified;
       continue;
     }
 
     // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
-    for (qos_flow_index = 0; qos_flow_index < ue_p->modify_pdusession[i].param.nb_qos; qos_flow_index++) {
-      switch (ue_p->modify_pdusession[i].param.qos[qos_flow_index].fiveQI) {
+    for (qos_flow_index = 0; qos_flow_index < ue_p->pduSession[i].param.nb_qos; qos_flow_index++) {
+      switch (ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI) {
         case 1: //100ms
         case 2: //150ms
         case 3: //50ms
@@ -845,12 +840,11 @@ rrc_gNB_modify_dedicatedRRCReconfiguration(
           break;
 
         default:
-          LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->modify_pdusession[i].param.qos[qos_flow_index].fiveQI);
-          ue_p->modify_pdusession[i].status = PDU_SESSION_STATUS_FAILED;
-          ue_p->modify_pdusession[i].xid = xid;
-          ue_p->modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
-          ue_p->modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_not_supported_5QI_value;
-          ue_p->nb_of_failed_pdusessions++;
+          LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
+          ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
+          ue_p->pduSession[i].xid = xid;
+          ue_p->pduSession[i].cause = NGAP_CAUSE_RADIO_NETWORK;
+          ue_p->pduSession[i].cause_value = NGAP_CauseRadioNetwork_not_supported_5QI_value;
           continue;
       }
 
@@ -860,24 +854,20 @@ rrc_gNB_modify_dedicatedRRCReconfiguration(
             DRB_config->drb_Identity,
             i,
             qos_flow_index,
-            ue_p->modify_pdusession[i].param.qos[qos_flow_index].fiveQI);
+            ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
     }
 
     asn1cSeqAdd(&DRB_configList2->list, DRB_config);
 
-    ue_p->modify_pdusession[i].status = PDU_SESSION_STATUS_DONE;
-    ue_p->modify_pdusession[i].xid = xid;
-
-    if (ue_p->modify_pdusession[i].param.nas_pdu.buffer != NULL) {
-      dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t));
-      memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t));
-      OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_p->modify_pdusession[i].param.nas_pdu.buffer, ue_p->modify_pdusession[i].param.nas_pdu.length);
-      asn1cSeqAdd(&dedicatedNAS_MessageList->list, dedicatedNAS_Message);
+    ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
+    ue_p->pduSession[i].xid = xid;
 
-      LOG_I(NR_RRC, "add NAS info with size %d (pdusession id %d)\n", ue_p->pduSession[i].param.nas_pdu.length, ue_p->modify_pdusession[i].param.pdusession_id);
+    if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
+      asn1cSequenceAdd(dedicatedNAS_MessageList->list,NR_DedicatedNAS_Message_t, dedicatedNAS_Message);
+      OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_p->pduSession[i].param.nas_pdu.buffer, ue_p->pduSession[i].param.nas_pdu.length);
+      LOG_I(NR_RRC, "add NAS info with size %d (pdusession id %d)\n", ue_p->pduSession[i].param.nas_pdu.length, ue_p->pduSession[i].param.pdusession_id);
     } else {
-      // TODO
-      LOG_E(NR_RRC, "no NAS info (pdusession id %d)\n", ue_p->modify_pdusession[i].param.pdusession_id);
+      LOG_W(NR_RRC, "no NAS info (pdusession id %d)\n", ue_p->pduSession[i].param.pdusession_id);
     }
   }
 
@@ -907,11 +897,11 @@ rrc_gNB_modify_dedicatedRRCReconfiguration(
   LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n");
 
   /* Free all NAS PDUs */
-  for (i = 0; i < ue_p->nb_of_modify_pdusessions; i++) {
-    if (ue_p->modify_pdusession[i].param.nas_pdu.buffer != NULL) {
+  for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
+    if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
       /* Free the NAS PDU buffer and invalidate it */
-      free(ue_p->modify_pdusession[i].param.nas_pdu.buffer);
-      ue_p->modify_pdusession[i].param.nas_pdu.buffer = NULL;
+      free(ue_p->pduSession[i].param.nas_pdu.buffer);
+      ue_p->pduSession[i].param.nas_pdu.buffer = NULL;
     }
   }
 
@@ -986,14 +976,24 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
   }
 
   uint8_t buffer[RRC_BUF_SIZE] = {0};
-  int size = do_RRCReconfiguration(ctxt_pP, buffer, RRC_BUF_SIZE, xid, NULL, NULL, *DRB_Release_configList2, NULL, NULL, NULL, dedicatedNAS_MessageList, NULL, NULL, NULL, NULL, NULL);
-
-  ue_p->pdu_session_release_command_flag = 1;
-
+  int size = do_RRCReconfiguration(ctxt_pP,
+                                   buffer,
+                                   RRC_BUF_SIZE,
+                                   xid,
+                                   NULL,
+                                   NULL,
+                                   *DRB_Release_configList2,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   dedicatedNAS_MessageList,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   NULL);
   LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n");
 
-  ue_p->pdu_session_release_command_flag = 1;
-
   /* Free all NAS PDUs */
   if (nas_length > 0) {
     /* Free the NAS PDU buffer and invalidate it */
@@ -1207,16 +1207,18 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP,
   SRB_configList = &(ue_p->SRB_configList);
 
   uint8_t buffer[RRC_BUF_SIZE] = {0};
+  uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id);
+  ue_p->xids[xid] = RRC_REESTABLISH;
   int size = do_RRCReestablishment(ctxt_pP,
-                                       ue_context_pP,
-                                       CC_id,
-                                       buffer,
-                                       RRC_BUF_SIZE,
-                                       rrc_gNB_get_next_transaction_identifier(module_id),
-                                       SRB_configList,
-                                       masterCellGroup_from_DU,
-                                       scc,
-                                       &rrc->carrier);
+                                   ue_context_pP,
+                                   CC_id,
+                                   buffer,
+                                   RRC_BUF_SIZE,
+                                   xid,
+                                   SRB_configList,
+                                   masterCellGroup_from_DU,
+                                   scc,
+                                   &rrc->carrier);
 
   LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size);
 
@@ -1462,10 +1464,9 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx
   int i = 0;
 
   uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
+  ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE;
   ue_p->StatusRrc = NR_RRC_CONNECTED;
   ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED
-  ue_p->reestablishment_xid = new_xid;
-
   RRCReestablishmentComplete_fill_SRB2_configList(ctxt_pP, ue_context_pP, xid, new_xid);
   RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid);
   RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti);
@@ -1751,14 +1752,14 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
               ((cause == NR_ReestablishmentCause_otherFailure)      ? "Other Failure"
                : (cause == NR_ReestablishmentCause_handoverFailure) ? "Handover Failure"
                                                                     : "reconfigurationFailure"));
-
+        uint8_t xid = -1;
         if (physCellId != gnb_rrc_inst->carrier.physCellId) {
           /* UE was moving from previous cell so quickly that RRCReestablishment for previous cell was received in this cell */
           LOG_E(NR_RRC,
                 " NR_RRCReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), fallback to RRC establishment\n",
                 physCellId,
                 gnb_rrc_inst->carrier.physCellId);
-          rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, rnti, 0);
+          xid = rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, rnti, 0);
           break;
         }
 
@@ -1772,7 +1773,7 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
         if (rrcReestablishmentRequest.ue_Identity.c_RNTI < 0x1 || rrcReestablishmentRequest.ue_Identity.c_RNTI > 0xffef) {
           /* c_RNTI range error should not happen */
           LOG_E(NR_RRC, "NR_RRCReestablishmentRequest c_RNTI range error, fallback to RRC establishment\n");
-          rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, rnti, 0);
+          xid = rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, rnti, 0);
           break;
         }
 
@@ -1782,7 +1783,7 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
         gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
         if (ue_context_p == NULL) {
           LOG_E(NR_RRC, "NR_RRCReestablishmentRequest without UE context, fallback to RRC establishment\n");
-          rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, c_rnti, 0);
+          xid = rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id, c_rnti, 0);
           break;
         }
         // c-plane not end
@@ -1797,7 +1798,7 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
           UE->StatusRrc = NR_RRC_RECONFIGURED;
           protocol_ctxt_t ctxt_old_p;
           PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, module_id, GNB_FLAG_YES, c_rnti, 0, 0);
-          rrc_gNB_process_RRCReconfigurationComplete(&ctxt_old_p, ue_context_p, UE->reestablishment_xid);
+          rrc_gNB_process_RRCReconfigurationComplete(&ctxt_old_p, ue_context_p, xid);
 
           for (uint8_t pdusessionid = 0; pdusessionid < UE->nb_of_pdusessions; pdusessionid++) {
             if (UE->pduSession[pdusessionid].status == PDU_SESSION_STATUS_DONE) {
@@ -1814,8 +1815,6 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
         UE->ue_reestablishment_timer = 0;
         // UE->ue_release_timer_s1 = 0;
         UE->ue_release_timer_rrc = 0;
-        UE->reestablishment_xid = -1;
-
         // Insert C-RNTI to map
         for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
           nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &gnb_rrc_inst->nr_reestablish_rnti_map[i];
@@ -1899,21 +1898,259 @@ static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context,
   asn1cCallocOne(ue_ctxt->measResults, measurementReport->criticalExtensions.choice.measurementReport->measResults);
 }
 
+static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
+                                             const NR_RRCReestablishmentComplete_t *reestablishment_complete)
+{
+  rnti_t reestablish_rnti = 0;
+  gNB_RRC_INST *gnb_rrc_inst = RC.nrrrc[ctxt_pP->module_id];
+  rrc_gNB_ue_context_t *ue_context_p = NULL;
+  gNB_RRC_UE_t *UE = NULL;
+  //  Select C-RNTI from map
+  for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
+    nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &gnb_rrc_inst->nr_reestablish_rnti_map[i];
+    LOG_I(NR_RRC,
+          "nr_reestablish_rnti_map[%d] UEid %lx, RNTI %04x, ctxt_pP->rntiMaybeUEid: %lx\n",
+          i,
+          nr_reestablish_rnti_map->ue_id,
+          nr_reestablish_rnti_map->c_rnti,
+          ctxt_pP->rntiMaybeUEid);
+    if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
+      LOG_I(NR_RRC,
+            "Removing nr_reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n",
+            i,
+            nr_reestablish_rnti_map->ue_id,
+            nr_reestablish_rnti_map->c_rnti);
+      reestablish_rnti = nr_reestablish_rnti_map->c_rnti;
+      ue_context_p = rrc_gNB_get_ue_context_by_rnti(gnb_rrc_inst, reestablish_rnti);
+      UE = &ue_context_p->ue_context;
+      break;
+    }
+  }
+
+  if (ue_context_p == NULL || UE == NULL) {
+    LOG_E(RRC, "no UE found for reestablishment. ERROR: should send reply\n");
+    return -1;
+  }
+
+  DevAssert(reestablishment_complete->criticalExtensions.present
+            == NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete);
+  rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP,
+                                             reestablish_rnti,
+                                             ue_context_p,
+                                             reestablishment_complete->rrc_TransactionIdentifier);
+
+  nr_rrc_mac_remove_ue(reestablish_rnti);
+
+  UE->ue_reestablishment_counter++;
+
+  // UE->ue_release_timer = 0;
+  UE->ue_reestablishment_timer = 1;
+  // remove UE after 100 frames after NR_RRCReestablishmentRelease is triggered
+  UE->ue_reestablishment_timer_thres = 1000;
+  return 0;
+}
+
+static int handle_ueCapabilityInformation(const protocol_ctxt_t *const ctxt_pP,
+                                          rrc_gNB_ue_context_t *ue_context_p,
+                                          const NR_UECapabilityInformation_t *ue_cap_info)
+{
+  AssertFatal(ue_context_p != NULL, "Processing %s() for UE %lx, ue_context_p is NULL\n", __func__, ctxt_pP->rntiMaybeUEid);
+  gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
+
+  LOG_I(NR_RRC, "got UE capabilities for UE %lx\n", ctxt_pP->rntiMaybeUEid);
+  int eutra_index = -1;
+
+  if (ue_cap_info->criticalExtensions.present == NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation) {
+    const NR_UE_CapabilityRAT_ContainerList_t *ue_CapabilityRAT_ContainerList =
+        ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList;
+    for (int i = 0; i < ue_CapabilityRAT_ContainerList->list.count; i++) {
+      const NR_UE_CapabilityRAT_Container_t *ue_cap_container = ue_CapabilityRAT_ContainerList->list.array[i];
+      if (ue_cap_container->rat_Type == NR_RAT_Type_nr) {
+        if (UE->UE_Capability_nr) {
+          ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
+          UE->UE_Capability_nr = 0;
+        }
+
+        asn_dec_rval_t dec_rval = uper_decode(NULL,
+                                              &asn_DEF_NR_UE_NR_Capability,
+                                              (void **)&UE->UE_Capability_nr,
+                                              ue_cap_container->ue_CapabilityRAT_Container.buf,
+                                              ue_cap_container->ue_CapabilityRAT_Container.size,
+                                              0,
+                                              0);
+        if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
+          xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
+        }
+
+        if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
+          LOG_E(NR_RRC,
+                PROTOCOL_NR_RRC_CTXT_UE_FMT " Failed to decode nr UE capabilities (%zu bytes)\n",
+                PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
+                dec_rval.consumed);
+          ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
+          UE->UE_Capability_nr = 0;
+        }
+
+        UE->UE_Capability_size = ue_cap_container->ue_CapabilityRAT_Container.size;
+        if (eutra_index != -1) {
+          LOG_E(NR_RRC, "fatal: more than 1 eutra capability\n");
+          exit(1);
+        }
+        eutra_index = i;
+      }
+
+      if (ue_cap_container->rat_Type == NR_RAT_Type_eutra_nr) {
+        if (UE->UE_Capability_MRDC) {
+          ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
+          UE->UE_Capability_MRDC = 0;
+        }
+        asn_dec_rval_t dec_rval = uper_decode(NULL,
+                                              &asn_DEF_NR_UE_MRDC_Capability,
+                                              (void **)&UE->UE_Capability_MRDC,
+                                              ue_cap_container->ue_CapabilityRAT_Container.buf,
+                                              ue_cap_container->ue_CapabilityRAT_Container.size,
+                                              0,
+                                              0);
+
+        if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
+          xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
+        }
+
+        if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
+          LOG_E(NR_RRC,
+                PROTOCOL_NR_RRC_CTXT_FMT " Failed to decode nr UE capabilities (%zu bytes)\n",
+                PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
+                dec_rval.consumed);
+          ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
+          UE->UE_Capability_MRDC = 0;
+        }
+        UE->UE_MRDC_Capability_size = ue_cap_container->ue_CapabilityRAT_Container.size;
+      }
+
+      if (ue_cap_container->rat_Type == NR_RAT_Type_eutra) {
+        // TODO
+      }
+    }
+
+    if (eutra_index == -1)
+      return -1;
+  }
+
+  if (get_softmodem_params()->sa) {
+    rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ue_cap_info);
+  }
+
+  // we send the UE capabilities request before RRC connection is complete,
+  // so we cannot have a PDU session yet
+  AssertFatal(UE->nb_of_pdusessions == 0, "logic bug: received capabilities while PDU session established\n");
+  // TODO: send UE context modification response with UE capabilities to
+  // allow DU configure CellGroupConfig
+  rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p);
+
+  return 0;
+}
+
+static int handle_rrcSetupComplete(const protocol_ctxt_t *const ctxt_pP,
+                                   rrc_gNB_ue_context_t *ue_context_p,
+                                   const NR_RRCSetupComplete_t *setup_complete)
+{
+  if (!ue_context_p) {
+    LOG_I(NR_RRC, "Processing NR_RRCSetupComplete UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
+    return -1;
+  }
+  gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
+
+  NR_RRCSetupComplete_IEs_t *setup_complete_ies = setup_complete->criticalExtensions.choice.rrcSetupComplete;
+
+  if (setup_complete_ies->ng_5G_S_TMSI_Value != NULL) {
+    if (setup_complete_ies->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2) {
+      if (setup_complete_ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size != 2) {
+        LOG_E(NR_RRC,
+              "wrong ng_5G_S_TMSI_Part2 size, expected 2, provided %lu",
+              (long unsigned int)
+                  setup_complete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size);
+        return -1;
+      }
+
+      if (UE->ng_5G_S_TMSI_Part1 != 0) {
+        UE->ng_5G_S_TMSI_Part2 = BIT_STRING_to_uint16(&setup_complete_ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2);
+      }
+
+      /* TODO */
+    } else if (setup_complete_ies->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI) {
+      if (setup_complete_ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size != 6) {
+        LOG_E(NR_RRC,
+              "wrong ng_5G_S_TMSI size, expected 6, provided %lu",
+              (long unsigned int)setup_complete_ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size);
+        return -1;
+      }
+
+      uint64_t fiveg_s_TMSI = bitStr_to_uint64(&setup_complete_ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI);
+      LOG_I(NR_RRC,
+            "Received rrcSetupComplete, 5g_s_TMSI: 0x%lX, amf_set_id: 0x%lX(%ld), amf_pointer: 0x%lX(%ld), 5g TMSI: 0x%X \n",
+            fiveg_s_TMSI,
+            fiveg_s_TMSI >> 38,
+            fiveg_s_TMSI >> 38,
+            (fiveg_s_TMSI >> 32) & 0x3F,
+            (fiveg_s_TMSI >> 32) & 0x3F,
+            (uint32_t)fiveg_s_TMSI);
+      if (UE->Initialue_identity_5g_s_TMSI.presence) {
+        UE->Initialue_identity_5g_s_TMSI.amf_set_id = fiveg_s_TMSI >> 38;
+        UE->Initialue_identity_5g_s_TMSI.amf_pointer = (fiveg_s_TMSI >> 32) & 0x3F;
+        UE->Initialue_identity_5g_s_TMSI.fiveg_tmsi = (uint32_t)fiveg_s_TMSI;
+      }
+    }
+  }
+
+  rrc_gNB_process_RRCSetupComplete(ctxt_pP, ue_context_p, setup_complete->criticalExtensions.choice.rrcSetupComplete);
+  LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT " UE State = NR_RRC_CONNECTED \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP));
+
+  UE->ue_release_timer = 0;
+  return 0;
+}
+
+static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_pP,
+                                              rrc_gNB_ue_context_t *ue_context_p,
+                                              const NR_RRCReconfigurationComplete_t *reconfig_complete)
+{
+  LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %lx\n", ctxt_pP->rntiMaybeUEid);
+  AssertFatal(ue_context_p != NULL, "Processing %s() for UE %lx, ue_context_p is NULL\n", __func__, ctxt_pP->rntiMaybeUEid);
+  gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
+
+  uint8_t xid = reconfig_complete->rrc_TransactionIdentifier;
+  rrc_gNB_process_RRCReconfigurationComplete(ctxt_pP, ue_context_p, xid);
+
+  if (get_softmodem_params()->sa) {
+    switch (UE->xids[xid]) {
+      case RRC_PDUSESSION_RELEASE: {
+        gtpv1u_gnb_delete_tunnel_req_t req = {0};
+        gtpv1u_delete_ngu_tunnel(ctxt_pP->instance, &req);
+        // NGAP_PDUSESSION_RELEASE_RESPONSE
+        rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid);
+      } break;
+      case RRC_PDUSESSION_ESTABLISH:
+        if (UE->nb_of_pdusessions > 0)
+          rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, ue_context_p, xid);
+        break;
+      case RRC_PDUSESSION_MODIFY:
+        rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(ctxt_pP, ue_context_p, xid);
+        break;
+      case RRC_FIRST_RECONF:
+        rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p);
+        break;
+      default:
+        LOG_E(RRC, "Received unexpected xid: %d\n", xid);
+    }
+  }
+}
 //-----------------------------------------------------------------------------
-int
-rrc_gNB_decode_dcch(
-  const protocol_ctxt_t *const ctxt_pP,
-  const rb_id_t                Srb_id,
-  const uint8_t    *const      Rx_sdu,
-  const sdu_size_t             sdu_sizeP
-)
+int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP,
+                        const rb_id_t Srb_id,
+                        const uint8_t *const Rx_sdu,
+                        const sdu_size_t sdu_sizeP)
 //-----------------------------------------------------------------------------
 {
-  asn_dec_rval_t                      dec_rval;
-  NR_UL_DCCH_Message_t *ul_dcch_msg = NULL;
-  uint8_t                             xid;
   gNB_RRC_INST *gnb_rrc_inst = RC.nrrrc[ctxt_pP->module_id];
-  int i;
 
   if ((Srb_id != 1) && (Srb_id != 2)) {
     LOG_E(NR_RRC, "Received message on SRB%ld, should not have ...\n", Srb_id);
@@ -1922,38 +2159,27 @@ rrc_gNB_decode_dcch(
   }
 
   LOG_D(NR_RRC, "Decoding UL-DCCH Message\n");
-
-  //for (int i=0;i<sdu_sizeP;i++) printf("%02x ",Rx_sdu[i]);
-  //printf("\n");
-
-  dec_rval = uper_decode(
-                  NULL,
-                  &asn_DEF_NR_UL_DCCH_Message,
-                  (void **)&ul_dcch_msg,
-                  Rx_sdu,
-                  sdu_sizeP,
-                  0,
-                  0);
-
-  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
-    xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
-  }
-
   {
-    for (i = 0; i < sdu_sizeP; i++) {
+    for (int i = 0; i < sdu_sizeP; i++) {
       LOG_T(NR_RRC, "%x.", Rx_sdu[i]);
     }
 
     LOG_T(NR_RRC, "\n");
   }
 
+  NR_UL_DCCH_Message_t *ul_dcch_msg = NULL;
+  asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_UL_DCCH_Message, (void **)&ul_dcch_msg, Rx_sdu, sdu_sizeP, 0, 0);
+
   if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
     LOG_E(NR_RRC, "Failed to decode UL-DCCH (%zu bytes)\n", dec_rval.consumed);
     return -1;
   }
 
+  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
+    xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
+  }
+
   rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(gnb_rrc_inst, ctxt_pP->rntiMaybeUEid);
-  gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
 
   if (ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1) {
     switch (ul_dcch_msg->message.choice.c1->present) {
@@ -1962,148 +2188,12 @@ rrc_gNB_decode_dcch(
         break;
 
       case NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete:
-        LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %lx\n", ctxt_pP->rntiMaybeUEid);
-        if(!ue_context_p) {
-          LOG_E(NR_RRC, "Processing NR_RRCReconfigurationComplete UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
-          break;
-        }
-
-        LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)(Rx_sdu), sdu_sizeP,
-                    "[MSG] RRC Connection Reconfiguration Complete\n");
-        LOG_D(NR_RRC,
-            PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
-            "(RRCReconfigurationComplete) ---> RRC_gNB]\n",
-            PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH,
-            sdu_sizeP);
-
-        if (ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete) {
-          if (ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->criticalExtensions.present ==
-            NR_RRCReconfigurationComplete__criticalExtensions_PR_rrcReconfigurationComplete)
-            rrc_gNB_process_RRCReconfigurationComplete(
-                ctxt_pP,
-                ue_context_p,
-                ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier);
-        }
-
-        if (get_softmodem_params()->sa) {
-          if (UE->pdu_session_release_command_flag == 1) {
-            xid = ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier;
-            UE->pdu_session_release_command_flag = 0;
-            //gtp tunnel delete
-	    gtpv1u_gnb_delete_tunnel_req_t req={0};
-            for(i = 0; i < NB_RB_MAX; i++) {
-              if (xid == UE->pduSession[i].xid) {
-                req.pdusession_id[req.num_pdusession++] = UE->gnb_gtp_psi[i];
-                UE->gnb_gtp_teid[i] = 0;
-                memset(&UE->gnb_gtp_addrs[i], 0, sizeof(UE->gnb_gtp_addrs[i]));
-                UE->gnb_gtp_psi[i] = 0;
-              }
-            }
-            gtpv1u_delete_ngu_tunnel(ctxt_pP->instance, &req);
-            //NGAP_PDUSESSION_RELEASE_RESPONSE
-            rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid);
-          } else if (UE->established_pdu_sessions_flag != 1) {
-            if (UE->reestablishment_xid < 0) {
-              if (UE->nb_of_pdusessions > 0) {
-                rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier);
-              }
-            } else {
-              UE->reestablishment_xid = -1;
-            }
-          }
-          if (UE->nb_of_modify_pdusessions > 0) {
-            rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(ctxt_pP,
-                                                     ue_context_p,
-                                                     ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier);
-            UE->nb_of_modify_pdusessions = 0;
-            UE->nb_of_failed_pdusessions = 0;
-            memset(UE->modify_pdusession, 0, sizeof(UE->modify_pdusession));
-
-            for(int i = 0; i < NR_NB_RB_MAX; i++) {
-              UE->modify_pdusession[i].xid = -1;
-            }
-          }
-        }
-        if (first_rrcreconfiguration == 0){
-          first_rrcreconfiguration = 1;
-          rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p);
-        }
-
+        handle_rrcReconfigurationComplete(ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete);
         break;
 
       case NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete:
-        if(!ue_context_p) {
-          LOG_I(NR_RRC, "Processing NR_RRCSetupComplete UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
-          break;
-        }
-
-        LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
-                    "[MSG] RRC SetupComplete\n");
-        LOG_D(NR_RRC,
-                PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
-                "(RRCSetupComplete) ---> RRC_gNB\n",
-                PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
-                DCCH,
-                sdu_sizeP);
-
-        if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.present ==
-              NR_RRCSetupComplete__criticalExtensions_PR_rrcSetupComplete) {
-          if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.
-            rrcSetupComplete->ng_5G_S_TMSI_Value != NULL) {
-            if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.
-            rrcSetupComplete->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2) {
-            // ng-5G-S-TMSI-Part2                  BIT STRING (SIZE (9))
-              if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.
-                rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size != 2) {
-                LOG_E(NR_RRC, "wrong ng_5G_S_TMSI_Part2 size, expected 2, provided %lu",
-                            (long unsigned int)ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->
-                            criticalExtensions.choice.rrcSetupComplete->
-                            ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size);
-                return -1;
-              }
-
-              if (UE->ng_5G_S_TMSI_Part1 != 0) {
-                UE->ng_5G_S_TMSI_Part2 =
-                    BIT_STRING_to_uint16(&ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2);
-              }
-
-            /* TODO */
-            } else if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.
-              rrcSetupComplete->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI) {
-              // NG-5G-S-TMSI ::=                         BIT STRING (SIZE (48))
-              if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.
-                rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size != 6) {
-                LOG_E(NR_RRC, "wrong ng_5G_S_TMSI size, expected 6, provided %lu",
-                            (long unsigned int)ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->
-                            criticalExtensions.choice.rrcSetupComplete->
-                            ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size);
-                return -1;
-              }
-
-              uint64_t fiveg_s_TMSI = bitStr_to_uint64(&ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->
-                  criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI);
-              LOG_I(NR_RRC, "Received rrcSetupComplete, 5g_s_TMSI: 0x%lX, amf_set_id: 0x%lX(%ld), amf_pointer: 0x%lX(%ld), 5g TMSI: 0x%X \n",
-                  fiveg_s_TMSI, fiveg_s_TMSI >> 38, fiveg_s_TMSI >> 38,
-                  (fiveg_s_TMSI >> 32) & 0x3F, (fiveg_s_TMSI >> 32) & 0x3F,
-                  (uint32_t)fiveg_s_TMSI);
-              if (UE->Initialue_identity_5g_s_TMSI.presence == true) {
-                UE->Initialue_identity_5g_s_TMSI.amf_set_id = fiveg_s_TMSI >> 38;
-                UE->Initialue_identity_5g_s_TMSI.amf_pointer = (fiveg_s_TMSI >> 32) & 0x3F;
-                UE->Initialue_identity_5g_s_TMSI.fiveg_tmsi = (uint32_t)fiveg_s_TMSI;
-              }
-            }
-          }
-
-          rrc_gNB_process_RRCSetupComplete(
-                  ctxt_pP,
-                  ue_context_p,
-                  ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.rrcSetupComplete);
-          LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" UE State = NR_RRC_CONNECTED \n",
-              PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP));
-        }
-
-        UE->ue_release_timer = 0;
+        if (handle_rrcSetupComplete(ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete) == -1)
+          return -1;
         break;
 
       case NR_UL_DCCH_MessageType__c1_PR_measurementReport:
@@ -2114,43 +2204,41 @@ rrc_gNB_decode_dcch(
         rrc_gNB_process_MeasurementReport(ue_context_p, ul_dcch_msg->message.choice.c1->choice.measurementReport);
         break;
 
-        case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
-            LOG_I(NR_RRC,"Recived RRC GNB UL Information Transfer \n");
-            if(!ue_context_p) {
-              LOG_I(NR_RRC, "Processing ulInformationTransfer UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
-              break;
-            }
+      case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
+        LOG_I(NR_RRC, "Recived RRC GNB UL Information Transfer \n");
+        if (!ue_context_p) {
+          LOG_I(NR_RRC, "Processing ulInformationTransfer UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
+          break;
+        }
 
-            LOG_D(NR_RRC,"[MSG] RRC UL Information Transfer \n");
-            LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
-                        "[MSG] RRC UL Information Transfer \n");
+        LOG_D(NR_RRC, "[MSG] RRC UL Information Transfer \n");
+        LOG_DUMPMSG(RRC, DEBUG_RRC, (char *)Rx_sdu, sdu_sizeP, "[MSG] RRC UL Information Transfer \n");
 
-            if (get_softmodem_params()->sa) {
-                rrc_gNB_send_NGAP_UPLINK_NAS(ctxt_pP,
-                                          ue_context_p,
-                                          ul_dcch_msg);
-            }
-            break;
+        if (get_softmodem_params()->sa) {
+          rrc_gNB_send_NGAP_UPLINK_NAS(ctxt_pP, ue_context_p, ul_dcch_msg);
+        }
+        break;
 
-        case NR_UL_DCCH_MessageType__c1_PR_securityModeComplete:
+      case NR_UL_DCCH_MessageType__c1_PR_securityModeComplete:
         // to avoid segmentation fault
-           if(!ue_context_p) {
-             LOG_I(NR_RRC, "Processing securityModeComplete UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
-             break;
-           }
+        if (!ue_context_p) {
+          LOG_I(NR_RRC, "Processing securityModeComplete UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
+          break;
+        }
 
         LOG_I(NR_RRC,
-              PROTOCOL_NR_RRC_CTXT_UE_FMT" received securityModeComplete on UL-DCCH %d from UE\n",
+              PROTOCOL_NR_RRC_CTXT_UE_FMT " received securityModeComplete on UL-DCCH %d from UE\n",
               PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
               DCCH);
         LOG_D(NR_RRC,
-              PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
+              PROTOCOL_NR_RRC_CTXT_UE_FMT
+              " RLC RB %02d --- RLC_DATA_IND %d bytes "
               "(securityModeComplete) ---> RRC_eNB\n",
               PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
               DCCH,
               sdu_sizeP);
 
-        if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
+        if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
           xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
         }
 
@@ -2159,178 +2247,35 @@ rrc_gNB_decode_dcch(
 
         rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p);
         break;
-        case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure:
-            LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
-                       "[MSG] NR RRC Security Mode Failure\n");
-            LOG_W(NR_RRC,
-                  PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
-                  "(securityModeFailure) ---> RRC_gNB\n",
-                  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-                  DCCH,
-                  sdu_sizeP);
-            
-            if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
-              xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
-            }
-            
-            rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p);
-            break;
-
-      case NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation:
-        if(!ue_context_p) {
-          LOG_I(NR_RRC, "Processing ueCapabilityInformation UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
-          break;
-        }
-
-        LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
-                "[MSG] NR_RRC UECapablility Information\n");
-        LOG_I(NR_RRC,
-            PROTOCOL_NR_RRC_CTXT_UE_FMT" received ueCapabilityInformation on UL-DCCH %d from UE\n",
-            PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH);
-        LOG_D(RRC,
-        PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
-        "(UECapabilityInformation) ---> RRC_eNB\n",
-        PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
-        DCCH,
-        sdu_sizeP);
-        if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
-            xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
-        }
-        LOG_I(NR_RRC, "got UE capabilities for UE %lx\n", ctxt_pP->rntiMaybeUEid);
-        int eutra_index = -1;
-
-        if( ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present ==
-        NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation ) {
-          for(i = 0;i < ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.count; i++){
-            if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type ==
-              NR_RAT_Type_nr){
-              if (UE->UE_Capability_nr) {
-                ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
-                UE->UE_Capability_nr = 0;
-              }
-
-              dec_rval = uper_decode(NULL,
-                                     &asn_DEF_NR_UE_NR_Capability,
-                                     (void **)&UE->UE_Capability_nr,
-                                     ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                                         ->ue_CapabilityRAT_Container.buf,
-                                     ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                                         ->ue_CapabilityRAT_Container.size,
-                                     0,
-                                     0);
-              if(LOG_DEBUGFLAG(DEBUG_ASN1)){
-                xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
-              }
-
-              if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){
-                LOG_E(NR_RRC,PROTOCOL_NR_RRC_CTXT_UE_FMT" Failed to decode nr UE capabilities (%zu bytes)\n",
-                PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),dec_rval.consumed);
-                ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
-                UE->UE_Capability_nr = 0;
-              }
-
-              UE->UE_Capability_size = ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                                           ->ue_CapabilityRAT_Container.size;
-              if(eutra_index != -1){
-                LOG_E(NR_RRC,"fatal: more than 1 eutra capability\n");
-                exit(1);
-              }
-              eutra_index = i;
-            }
-
-            if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type ==
-            NR_RAT_Type_eutra_nr){
-              if (UE->UE_Capability_MRDC) {
-                ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
-                UE->UE_Capability_MRDC = 0;
-              }
-              dec_rval = uper_decode(NULL,
-                                     &asn_DEF_NR_UE_MRDC_Capability,
-                                     (void **)&UE->UE_Capability_MRDC,
-                                     ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                                         ->ue_CapabilityRAT_Container.buf,
-                                     ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                                         ->ue_CapabilityRAT_Container.size,
-                                     0,
-                                     0);
-
-              if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
-                xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
-              }
 
-            if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){
-              LOG_E(NR_RRC,PROTOCOL_NR_RRC_CTXT_FMT" Failed to decode nr UE capabilities (%zu bytes)\n",
-                  PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),dec_rval.consumed);
-              ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC);
-              UE->UE_Capability_MRDC = 0;
-            }
-            UE->UE_MRDC_Capability_size =
-                ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]
-                    ->ue_CapabilityRAT_Container.size;
-            }
-
-            if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type ==
-            NR_RAT_Type_eutra){
-              //TODO
-            }
-          }
-
-          if(eutra_index == -1)
-          break;
-      }
-      if (get_softmodem_params()->sa) {
-          rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP,
-                                    ue_context_p,
-                                    ul_dcch_msg);
-      }
-
-      // we send the UE capabilities request before RRC connection is complete,
-      // so we cannot have a PDU session yet
-      AssertFatal(UE->established_pdu_sessions_flag == 0, "logic bug: received capabilities while PDU session established\n");
-      // TODO: send UE context modification response with UE capabilities to
-      // allow DU configure CellGroupConfig
-      rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p);
-
-      break;
-
-      case NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete: {
-        LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)Rx_sdu, sdu_sizeP, "[MSG] NR_RRC Connection Reestablishment Complete\n");
-        LOG_I(NR_RRC, "RLC RB %02d --- RLC_DATA_IND %d bytes (rrcReestablishmentComplete) ---> RRC_gNB\n", DCCH, sdu_sizeP);
-
-        rnti_t reestablish_rnti = 0;
-
-        //  Select C-RNTI from map
-        for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
-          nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &gnb_rrc_inst->nr_reestablish_rnti_map[i];
-          LOG_I(NR_RRC, "nr_reestablish_rnti_map[%d] UEid %lx, RNTI %04x, ctxt_pP->rntiMaybeUEid: %lx\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti, ctxt_pP->rntiMaybeUEid);
-          if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
-          LOG_I(NR_RRC, "Removing nr_reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti);
-          reestablish_rnti = nr_reestablish_rnti_map->c_rnti;
-          ue_context_p = rrc_gNB_get_ue_context_by_rnti(gnb_rrc_inst, reestablish_rnti);
-          UE = &ue_context_p->ue_context;
-          break;
-          }
-        }
+      case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure:
+        LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)Rx_sdu, sdu_sizeP, "[MSG] NR RRC Security Mode Failure\n");
+        LOG_W(NR_RRC,
+              PROTOCOL_RRC_CTXT_UE_FMT
+              " RLC RB %02d --- RLC_DATA_IND %d bytes "
+              "(securityModeFailure) ---> RRC_gNB\n",
+              PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
+              DCCH,
+              sdu_sizeP);
 
-        if (!ue_context_p) {
-          LOG_E(NR_RRC, "NR_RRCReestablishmentComplete without UE context, fault\n");
-          break;
+        if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
+          xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg);
         }
 
-        if (ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->criticalExtensions.present == NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete) {
-          rrc_gNB_process_RRCReestablishmentComplete(ctxt_pP, reestablish_rnti, ue_context_p, ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->rrc_TransactionIdentifier);
-
-          nr_rrc_mac_remove_ue(reestablish_rnti);
+        rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p);
+        break;
 
-          UE->ue_reestablishment_counter++;
-        }
+      case NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation:
+        if (handle_ueCapabilityInformation(ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation)
+            == -1)
+          return -1;
+        break;
 
-        // UE->ue_release_timer = 0;
-        UE->ue_reestablishment_timer = 1;
-        // remove UE after 100 frames after NR_RRCReestablishmentRelease is triggered
-        UE->ue_reestablishment_timer_thres = 1000;
-      } break;
+      case NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete:
+        if (handle_rrcReestablishmentComplete(ctxt_pP, ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete)
+            == -1)
+          return -1;
+        break;
 
       default:
         break;
@@ -2663,7 +2608,8 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
   }
 
   // send the F1 response message up to update F1-U tunnel info
-  rrc->cucp_cuup.bearer_context_mod(&req, instance);
+  // it seems the rrc transaction id (xid) is not needed here
+  rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
 
   NR_CellGroupConfig_t *cellGroupConfig = NULL;
 
diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c
index 1322317b3e7704ec5a062b9c9db83d1ae04ba40c..e7bbe5835effa61b2cc90af9701c36cb578acd77 100644
--- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c
+++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c
@@ -58,14 +58,14 @@ int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_
     return -1;
   }
   for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) {
-    ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->enb_S1u_teid[i];
-    ue_context_p->ue_context.gnb_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->enb_addr;
-    ue_context_p->ue_context.gnb_gtp_ebi[inde_list[i]] = create_tunnel_resp_pP->eps_bearer_id[i];
+    ue_context_p->ue_context.nsa_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->enb_S1u_teid[i];
+    ue_context_p->ue_context.nsa_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->enb_addr;
+    ue_context_p->ue_context.nsa_gtp_ebi[inde_list[i]] = create_tunnel_resp_pP->eps_bearer_id[i];
     LOG_I(RRC,
           PROTOCOL_RRC_CTXT_UE_FMT " rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp addr len %d \n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
           create_tunnel_resp_pP->enb_S1u_teid[i],
-          ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]],
+          ue_context_p->ue_context.nsa_gtp_teid[inde_list[i]],
           inde_list[i],
           i,
           create_tunnel_resp_pP->eps_bearer_id[i],
@@ -90,14 +90,14 @@ int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ct
   }
 
   for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) {
-    ue_context_p->ue_context.gnb_gtp_teid[i + offset] = create_tunnel_resp_pP->gnb_NGu_teid[i];
-    ue_context_p->ue_context.gnb_gtp_addrs[i + offset] = create_tunnel_resp_pP->gnb_addr;
-    ue_context_p->ue_context.gnb_gtp_psi[i + offset] = create_tunnel_resp_pP->pdusession_id[i];
+    ue_context_p->ue_context.pduSession[i + offset].param.gNB_teid_N3 = create_tunnel_resp_pP->gnb_NGu_teid[i];
+    ue_context_p->ue_context.pduSession[i + offset].param.gNB_addr_N3 = create_tunnel_resp_pP->gnb_addr;
+    AssertFatal(ue_context_p->ue_context.pduSession[i + offset].param.pdusession_id == create_tunnel_resp_pP->pdusession_id[i], "");
     LOG_I(NR_RRC,
-          PROTOCOL_NR_RRC_CTXT_UE_FMT " nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, id %u, gtp addr len %d \n",
+          PROTOCOL_NR_RRC_CTXT_UE_FMT
+          " nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u) bearer UE context index %u, id %u, gtp addr len %d \n",
           PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
           create_tunnel_resp_pP->gnb_NGu_teid[i],
-          ue_context_p->ue_context.gnb_gtp_teid[i + offset],
           i,
           create_tunnel_resp_pP->pdusession_id[i],
           create_tunnel_resp_pP->gnb_addr.length);
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 1f37210b9c25f403e760c6cf8f3c4f4b13eca5e4..102fb56091bce50a6c2f37d03a40791bf91e6ee5 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -319,7 +319,8 @@ static int decodePDUSessionResourceSetup(pdusession_t *session)
 
         /* mandatory PDUSessionType */
       case NGAP_ProtocolIE_ID_id_PDUSessionType:
-        session->upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
+        session->pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType;
+        AssertFatal(session->pdu_session_type == PDUSessionType_ipv4, "To be developped: support not IPv4 sessions\n");
         break;
 
         /* optional SecurityIndication */
@@ -405,7 +406,6 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
     }
 
     nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, &create_tunnel_resp, 0);
-    UE->established_pdu_sessions_flag = 1;
   }
 
   /* NAS PDU */
@@ -448,9 +448,11 @@ void rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(const protocol_ctxt_t *const c
     if (session->status == PDU_SESSION_STATUS_DONE) {
       pdu_sessions_done++;
       resp->pdusessions[pdusession].pdusession_id = session->param.pdusession_id;
-      resp->pdusessions[pdusession].gtp_teid = UE->gnb_gtp_teid[pdusession];
-      memcpy(resp->pdusessions[pdusession].gNB_addr.buffer, UE->gnb_gtp_addrs[pdusession].buffer, 20);
-      resp->pdusessions[pdusession].gNB_addr.length = 4;
+      resp->pdusessions[pdusession].gtp_teid = session->param.gNB_teid_N3;
+      memcpy(resp->pdusessions[pdusession].gNB_addr.buffer,
+             session->param.gNB_addr_N3.buffer,
+             sizeof(resp->pdusessions[pdusession].gNB_addr.buffer));
+      resp->pdusessions[pdusession].gNB_addr.length = 4; // Fixme: IPv4 hard coded here
       resp->pdusessions[pdusession].nb_of_qos_flow = session->param.nb_qos;
       for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
         resp->pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
@@ -679,10 +681,10 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(
       pdusession_setup_t *tmp = &resp->pdusessions[pdu_sessions_done];
       tmp->pdusession_id = session->param.pdusession_id;
       tmp->nb_of_qos_flow = session->param.nb_qos;
-      tmp->gtp_teid = UE->gnb_gtp_teid[pdusession];
-      tmp->gNB_addr.pdu_session_type = PDUSessionType_ipv4;
-      tmp->gNB_addr.length = UE->gnb_gtp_addrs[pdusession].length;
-      memcpy(tmp->gNB_addr.buffer, UE->gnb_gtp_addrs[pdusession].buffer, tmp->gNB_addr.length);
+      tmp->gtp_teid = session->param.gNB_teid_N3;
+      tmp->pdu_session_type = session->param.pdu_session_type; // FixMe: IPv4 hardcoded here
+      tmp->gNB_addr.length = session->param.gNB_addr_N3.length;
+      memcpy(tmp->gNB_addr.buffer, session->param.gNB_addr_N3.buffer, tmp->gNB_addr.length);
       for (int qos_flow_index = 0; qos_flow_index < tmp->nb_of_qos_flow; qos_flow_index++) {
         tmp->associated_qos_flows[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
         tmp->associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
@@ -729,15 +731,13 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(
 void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t instance)
 //------------------------------------------------------------------------------
 {
-  gNB_RRC_INST *rrc;
-  rrc_gNB_ue_context_t            *ue_context_p = NULL;
   protocol_ctxt_t                 ctxt={0};
 
   ngap_pdusession_setup_req_t* msg=&NGAP_PDUSESSION_SETUP_REQ(msg_p);
-  ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], msg->gNB_ue_ngap_id);
+  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], msg->gNB_ue_ngap_id);
   gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
-  rrc = RC.nrrrc[ctxt.module_id];
+  gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
   LOG_I(NR_RRC, "[gNB %ld] gNB_ue_ngap_id %u \n", instance, msg->gNB_ue_ngap_id);
 
   if (ue_context_p == NULL) {
@@ -759,6 +759,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
     pdusession_t *session = &pduSession->param;
     LOG_I(NR_RRC, "Adding pdusession %d, total nb of sessions %d\n", session->pdusession_id, UE->nb_of_pdusessions);
     session->pdusession_id = msg->pdusession_setup_params[i].pdusession_id;
+    session->pdu_session_type = msg->pdusession_setup_params[i].pdu_session_type;
     session->nas_pdu = msg->pdusession_setup_params[i].nas_pdu;
     session->pdusessionTransfer = msg->pdusession_setup_params[i].pdusessionTransfer;
     decodePDUSessionResourceSetup(session);
@@ -818,7 +819,9 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
       }
     }
   }
-  rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance);
+  int xid = rrc_gNB_get_next_transaction_identifier(instance);
+  UE->xids[xid] = RRC_PDUSESSION_ESTABLISH;
+  rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance, xid);
   return;
 }
 
@@ -929,50 +932,46 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
   gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
   PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rnti, 0, 0);
   ctxt.eNB_index = 0;
-  uint8_t nb_of_failed_pdusessions = 0;
-
+  bool all_failed = true;
   for (int i = 0; i < req->nb_pdusessions_tomodify; i++) {
-    int j;
-    for (j = 0; j < UE->nb_of_pdusessions; j++)
-      if (UE->modify_pdusession[j].param.pdusession_id == req->pdusession_modify_params[j].pdusession_id)
+    rrc_pdu_session_param_t *sess;
+    const pdusession_t *sessMod = req->pdusession_modify_params + i;
+    for (sess = UE->pduSession; sess < UE->pduSession + UE->nb_of_pdusessions; sess++)
+      if (sess->param.pdusession_id == sessMod->pdusession_id)
         break;
-    if (j == UE->nb_of_pdusessions) {
-      LOG_W(NR_RRC, "To finish, modify a not existing pdu session\n");
-      // handle multiple pdu session id
-      LOG_D(NR_RRC, "handle multiple pdu session id \n");
-      UE->modify_pdusession[j].status = PDU_SESSION_STATUS_NEW;
-      UE->modify_pdusession[j].param.pdusession_id = req->pdusession_modify_params[j].pdusession_id;
-      UE->modify_pdusession[j].cause = NGAP_CAUSE_RADIO_NETWORK;
-      UE->modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
-      nb_of_failed_pdusessions++;
+    if (sess == UE->pduSession + UE->nb_of_pdusessions) {
+      LOG_W(NR_RRC, "Requested modification of non-existing PDU session, refusing modification\n");
+      UE->nb_of_pdusessions++;
+      sess->status = PDU_SESSION_STATUS_FAILED;
+      sess->param.pdusession_id = sessMod->pdusession_id;
+      sess->cause = NGAP_CAUSE_RADIO_NETWORK;
+      UE->pduSession[i].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
     } else {
-      UE->modify_pdusession[j].status = PDU_SESSION_STATUS_NEW;
-      UE->modify_pdusession[j].param.pdusession_id = req->pdusession_modify_params[i].pdusession_id;
-      UE->modify_pdusession[j].cause = NGAP_CAUSE_RADIO_NETWORK;
-      UE->modify_pdusession[j].cause_value = NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances;
-      UE->modify_pdusession[j].status = PDU_SESSION_STATUS_NEW;
-      UE->modify_pdusession[j].param.pdusession_id = req->pdusession_modify_params[i].pdusession_id;
-      UE->modify_pdusession[j].cause = NGAP_CAUSE_NOTHING;
-      if (req->pdusession_modify_params[i].nas_pdu.buffer != NULL) {
-        UE->modify_pdusession[i].param.nas_pdu = req->pdusession_modify_params[i].nas_pdu;
+      all_failed = false;
+      sess->status = PDU_SESSION_STATUS_NEW;
+      sess->param.pdusession_id = sessMod->pdusession_id;
+      sess->cause = NGAP_CAUSE_RADIO_NETWORK;
+      sess->cause_value = NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances;
+      sess->status = PDU_SESSION_STATUS_NEW;
+      sess->param.pdusession_id = sessMod->pdusession_id;
+      sess->cause = NGAP_CAUSE_NOTHING;
+      if (sessMod->nas_pdu.buffer != NULL) {
+        UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
       }
       // Save new pdu session parameters, qos, upf addr, teid
-      decodePDUSessionResourceModify(&UE->modify_pdusession[j].param, UE->modify_pdusession[i].param.pdusessionTransfer);
-      UE->modify_pdusession[j].param.upf_addr = UE->pduSession[j].param.upf_addr;
-      UE->modify_pdusession[j].param.gtp_teid = UE->pduSession[j].param.gtp_teid;
+      decodePDUSessionResourceModify(&sess->param, UE->pduSession[i].param.pdusessionTransfer);
+      sess->param.UPF_addr_N3 = sessMod->upf_addr;
+      sess->param.UPF_teid_N3 = sessMod->gtp_teid;
     }
   }
 
-  UE->nb_of_modify_pdusessions = req->nb_pdusessions_tomodify - nb_of_failed_pdusessions;
-  UE->nb_of_failed_pdusessions = nb_of_failed_pdusessions;
-
-  if (UE->nb_of_failed_pdusessions < UE->nb_of_modify_pdusessions) {
+  if (!all_failed) {
     LOG_D(NR_RRC, "generate RRCReconfiguration \n");
     rrc_gNB_modify_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
-  } else { // all pdu modification failed
-    LOG_I(NR_RRC, "pdu session modify failed, fill NGAP_PDUSESSION_MODIFY_RESP with the pdu session information that failed to modify \n");
-    MessageDef *msg_fail_p = NULL;
-    msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP);
+  } else {
+    LOG_I(NR_RRC,
+          "pdu session modify failed, fill NGAP_PDUSESSION_MODIFY_RESP with the pdu session information that failed to modify \n");
+    MessageDef *msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP);
     if (msg_fail_p == NULL) {
       LOG_E(NR_RRC, "itti_alloc_new_message failed, msg_fail_p is NULL \n");
       return (-1);
@@ -981,21 +980,16 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
     msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id;
     msg->nb_of_pdusessions = 0;
 
-    for (int i = 0; i < UE->nb_of_failed_pdusessions; i++) {
-      msg->pdusessions_failed[i].pdusession_id = UE->modify_pdusession[i].param.pdusession_id;
-      msg->pdusessions_failed[i].cause = UE->modify_pdusession[i].cause;
-      msg->pdusessions_failed[i].cause_value = UE->modify_pdusession[i].cause_value;
+    for (int i = 0; i < UE->nb_of_pdusessions; i++) {
+      if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) {
+        msg->pdusessions_failed[i].pdusession_id = UE->pduSession[i].param.pdusession_id;
+        msg->pdusessions_failed[i].cause = UE->pduSession[i].cause;
+        msg->pdusessions_failed[i].cause_value = UE->pduSession[i].cause_value;
+      }
     }
-
-    msg->nb_of_pdusessions_failed = UE->nb_of_failed_pdusessions;
     itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
-    UE->nb_of_modify_pdusessions = 0;
-    UE->nb_of_failed_pdusessions = 0;
-    memset(UE->modify_pdusession, 0, sizeof(UE->modify_pdusession));
-    return (0);
   }
-
-  return 0;
+  return (0);
 }
 
 //------------------------------------------------------------------------------
@@ -1022,63 +1016,63 @@ rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(
 
   resp->gNB_ue_ngap_id = UE->gNB_ue_ngap_id;
 
-  for (int i = 0; i < UE->nb_of_modify_pdusessions; i++) {
-    if (xid != UE->modify_pdusession[i].xid) {
-      LOG_W(NR_RRC, "xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ", i, UE->modify_pdusession[i].status, xid, UE->modify_pdusession[i].xid);
+  for (int i = 0; i < UE->nb_of_pdusessions; i++) {
+    if (xid != UE->pduSession[i].xid) {
+      LOG_W(NR_RRC, "xid does not correspond (context pdu session index %d, status %d, xid %d/%d) \n ", i, UE->pduSession[i].status, xid, UE->pduSession[i].xid);
       continue;
     }
-    if (UE->modify_pdusession[i].status == PDU_SESSION_STATUS_DONE) {
-      rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->modify_pdusession[i].param.pdusession_id, false);
+    if (UE->pduSession[i].status == PDU_SESSION_STATUS_DONE) {
+      rrc_pdu_session_param_t *pduSession = find_pduSession(UE, UE->pduSession[i].param.pdusession_id, false);
       if (pduSession) {
         LOG_I(NR_RRC, "update pdu session %d \n", pduSession->param.pdusession_id);
         // Update UE->pduSession
         pduSession->status = PDU_SESSION_STATUS_ESTABLISHED;
         pduSession->cause = NGAP_CAUSE_NOTHING;
-        for (int qos_flow_index = 0; qos_flow_index < UE->modify_pdusession[i].param.nb_qos; qos_flow_index++) {
-          pduSession->param.qos[qos_flow_index] = UE->modify_pdusession[i].param.qos[qos_flow_index];
+        for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) {
+          pduSession->param.qos[qos_flow_index] = UE->pduSession[i].param.qos[qos_flow_index];
         }
-        resp->pdusessions[pdu_sessions_done].pdusession_id = UE->modify_pdusession[i].param.pdusession_id;
-        for (int qos_flow_index = 0; qos_flow_index < UE->modify_pdusession[i].param.nb_qos; qos_flow_index++) {
-          resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = UE->modify_pdusession[i].param.qos[qos_flow_index].qfi;
+        resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id;
+        for (int qos_flow_index = 0; qos_flow_index < UE->pduSession[i].param.nb_qos; qos_flow_index++) {
+          resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = UE->pduSession[i].param.qos[qos_flow_index].qfi;
         }
-        resp->pdusessions[pdu_sessions_done].pdusession_id = UE->modify_pdusession[i].param.pdusession_id;
-        resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = UE->modify_pdusession[i].param.nb_qos;
+        resp->pdusessions[pdu_sessions_done].pdusession_id = UE->pduSession[i].param.pdusession_id;
+        resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = UE->pduSession[i].param.nb_qos;
         LOG_I(NR_RRC,
-              "Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_modify_pdusessions %d,  pdusession_id %d \n ",
+              "Modify Resp (msg index %d, pdu session index %d, status %d, xid %d): nb_of_pduSessions %d,  pdusession_id %d \n ",
               pdu_sessions_done,
               i,
-              UE->modify_pdusession[i].status,
+              UE->pduSession[i].status,
               xid,
-              UE->nb_of_modify_pdusessions,
+              UE->nb_of_pdusessions,
               resp->pdusessions[pdu_sessions_done].pdusession_id);
         pdu_sessions_done++;
       } else {
-        LOG_W(NR_RRC, "PDU SESSION modify of a not existing pdu session %d \n", UE->modify_pdusession[i].param.pdusession_id);
-        resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->modify_pdusession[i].param.pdusession_id;
+        LOG_W(NR_RRC, "PDU SESSION modify of a not existing pdu session %d \n", UE->pduSession[i].param.pdusession_id);
+        resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id;
         resp->pdusessions_failed[pdu_sessions_failed].cause = NGAP_CAUSE_RADIO_NETWORK;
         resp->pdusessions_failed[pdu_sessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID;
         pdu_sessions_failed++;
       }
-    } else if ((UE->modify_pdusession[i].status == PDU_SESSION_STATUS_NEW) || (UE->modify_pdusession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) {
+    } else if ((UE->pduSession[i].status == PDU_SESSION_STATUS_NEW) || (UE->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED)) {
       LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n");
-    } else if (UE->modify_pdusession[i].status == PDU_SESSION_STATUS_FAILED) {
-      resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->modify_pdusession[i].param.pdusession_id;
-      resp->pdusessions_failed[pdu_sessions_failed].cause = UE->modify_pdusession[i].cause;
-      resp->pdusessions_failed[pdu_sessions_failed].cause_value = UE->modify_pdusession[i].cause_value;
+    } else if (UE->pduSession[i].status == PDU_SESSION_STATUS_FAILED) {
+      resp->pdusessions_failed[pdu_sessions_failed].pdusession_id = UE->pduSession[i].param.pdusession_id;
+      resp->pdusessions_failed[pdu_sessions_failed].cause = UE->pduSession[i].cause;
+      resp->pdusessions_failed[pdu_sessions_failed].cause_value = UE->pduSession[i].cause_value;
       pdu_sessions_failed++;
     }
     else
       LOG_W(NR_RRC,
             "Modify pdu session %d, unknown state %d \n ",
-            UE->modify_pdusession[i].param.pdusession_id,
-            UE->modify_pdusession[i].status);
+            UE->pduSession[i].param.pdusession_id,
+            UE->pduSession[i].status);
   }
 
   resp->nb_of_pdusessions = pdu_sessions_done;
   resp->nb_of_pdusessions_failed = pdu_sessions_failed;
 
   if (pdu_sessions_done > 0 || pdu_sessions_failed > 0) {
-    LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message: nb_of_pdusessions %d, total pdu session %d\n", UE->nb_of_modify_pdusessions, UE->nb_of_pdusessions);
+    LOG_D(NR_RRC, "NGAP_PDUSESSION_MODIFY_RESP: sending the message (total pdu session %d)\n", UE->nb_of_pdusessions);
     itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p);
   } else {
     itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
@@ -1179,22 +1173,19 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(
   itti_send_msg_to_task(TASK_NGAP, instance, msg);
 }
 
-void
-rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(
-  const protocol_ctxt_t    *const ctxt_pP,
-  rrc_gNB_ue_context_t     *const ue_context_pP,
-  NR_UL_DCCH_Message_t     *const ul_dcch_msg
-)
+void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(const protocol_ctxt_t *const ctxt_pP,
+                                           rrc_gNB_ue_context_t *const ue_context_pP,
+                                           const NR_UECapabilityInformation_t *const ue_cap_info)
 //------------------------------------------------------------------------------
 {
-    NR_UE_CapabilityRAT_ContainerList_t *ueCapabilityRATContainerList = ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList;
-    /* 4096 is arbitrary, should be big enough */
-    void *buf;
-    NR_UERadioAccessCapabilityInformation_t rac = {0};
-    gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
+  NR_UE_CapabilityRAT_ContainerList_t *ueCapabilityRATContainerList =
+      ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList;
+  void *buf;
+  NR_UERadioAccessCapabilityInformation_t rac = {0};
+  gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
 
-    if (ueCapabilityRATContainerList->list.count == 0) {
-      LOG_W(RRC, "[gNB %d][UE %x] bad UE capabilities\n", ctxt_pP->module_id, UE->rnti);
+  if (ueCapabilityRATContainerList->list.count == 0) {
+    LOG_W(RRC, "[gNB %d][UE %x] bad UE capabilities\n", ctxt_pP->module_id, UE->rnti);
     }
 
     int ret = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, ueCapabilityRATContainerList, &buf);
@@ -1242,31 +1233,21 @@ rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(
   memset(resp, 0, sizeof(*resp));
   resp->gNB_ue_ngap_id = UE->gNB_ue_ngap_id;
 
-  for (int i = 0;  i < NB_RB_MAX; i++) {
+  for (int i = 0; i < UE->nb_of_pdusessions; i++) {
     if (xid == UE->pduSession[i].xid) {
       resp->pdusession_release[pdu_sessions_released].pdusession_id = UE->pduSession[i].param.pdusession_id;
       pdu_sessions_released++;
       //clear
       memset(&UE->pduSession[i], 0, sizeof(*UE->pduSession));
+      UE->pduSession[i].status = PDU_SESSION_STATUS_RELEASED;
+      LOG_W(NR_RRC, "Released pdu session, but code to finish to free memory\n");
     }
   }
 
   resp->nb_of_pdusessions_released = pdu_sessions_released;
-  resp->nb_of_pdusessions_failed = UE->nb_release_of_pdusessions;
-  memcpy(resp->pdusessions_failed, UE->pdusessions_release_failed, sizeof(pdusession_failed_t) * UE->nb_release_of_pdusessions);
-  LOG_E(NR_RRC, "we have to pack the array!!!\n");
-  UE->nb_of_pdusessions -= pdu_sessions_released;
+  resp->nb_of_pdusessions_failed = 0;
   LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, pdu_sessions_released);
   itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p);
-
-  //clear xid
-  for(int i = 0; i < NB_RB_MAX; i++) {
-    UE->pduSession[i].xid = -1;
-  }
-
-  //clear release pdusessions
-  UE->nb_release_of_pdusessions = 0;
-  memset(UE->pdusessions_release_failed, 0, sizeof(UE->pdusessions_release_failed));
 }
 
 //------------------------------------------------------------------------------
@@ -1275,8 +1256,6 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
 {
   uint32_t gNB_ue_ngap_id;
   protocol_ctxt_t ctxt;
-  uint8_t xid;
-  uint8_t pdusession_release_drb = 0;
   ngap_pdusession_release_command_t *cmd = &NGAP_PDUSESSION_RELEASE_COMMAND(msg_p);
   gNB_ue_ngap_id = cmd->gNB_ue_ngap_id;
   if (cmd->nb_pdusessions_torelease > NGAP_MAX_PDUSESSION) {
@@ -1293,18 +1272,21 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
   LOG_I(NR_RRC, "[gNB %ld] gNB_ue_ngap_id %u \n", instance, gNB_ue_ngap_id);
   gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
   PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rnti, 0, 0);
-  xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id);
   LOG_I(
       NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu  GNB_UE_NGAP_ID %u release_pdusessions %d \n", cmd->amf_ue_ngap_id, gNB_ue_ngap_id, cmd->nb_pdusessions_torelease);
-
+  bool found = false;
+  uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id);
+  UE->xids[xid] = RRC_PDUSESSION_RELEASE;
   for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) {
     rrc_pdu_session_param_t *pduSession = find_pduSession(UE, cmd->pdusession_release_params[pdusession].pdusession_id, false);
     if (!pduSession) {
-      LOG_I(NR_RRC, "no pdusession_id \n");
-      UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id;
-      UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK;
-      UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].cause_value = 30;
-      UE->nb_release_of_pdusessions++;
+      LOG_I(NR_RRC, "no pdusession_id, AMF requested to close it id=%d\n", cmd->pdusession_release_params[pdusession].pdusession_id);
+      int j=UE->nb_of_pdusessions++;
+      UE->pduSession[j].status = PDU_SESSION_STATUS_FAILED;
+      UE->pduSession[j].param.pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id;
+      UE->pduSession[j].cause = NGAP_CAUSE_RADIO_NETWORK;
+      UE->pduSession[j].cause_value = 30;
+      pduSession->xid = xid;
       continue;
     }
     if (pduSession->status == PDU_SESSION_STATUS_FAILED) {
@@ -1312,37 +1294,22 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
       continue;
     }
     if (pduSession->status == PDU_SESSION_STATUS_ESTABLISHED) {
+      found = true;
       LOG_I(NR_RRC, "RELEASE pdusession %d \n", pduSession->param.pdusession_id);
       pduSession->status = PDU_SESSION_STATUS_TORELEASE;
       pduSession->xid = xid;
-      pdusession_release_drb++;
-      continue;
     }
-    // pdusession_id status NG
-    UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].pdusession_id = cmd->pdusession_release_params[pdusession].pdusession_id;
-    UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK;
-    UE->pdusessions_release_failed[UE->nb_release_of_pdusessions].cause_value = 0;
-    UE->nb_release_of_pdusessions++;
   }
 
-  if (pdusession_release_drb > 0) {
+  if (found) {
     // TODO RRCReconfiguration To UE
     LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n");
     rrc_gNB_generate_dedicatedRRCReconfiguration_release(&ctxt, ue_context_p, xid, cmd->nas_pdu.length, cmd->nas_pdu.buffer);
   } else {
     // gtp tunnel delete
-    LOG_I(NR_RRC, "gtp tunnel delete \n");
+    LOG_I(NR_RRC, "gtp tunnel delete all tunnels for UE %04x\n", UE->rnti);
     gtpv1u_gnb_delete_tunnel_req_t req = {0};
     req.ue_id = UE->rnti;
-
-    for (int i = 0; i < NB_RB_MAX; i++) {
-      if (xid == UE->pduSession[i].xid) {
-        req.pdusession_id[req.num_pdusession++] = UE->gnb_gtp_psi[i];
-        UE->gnb_gtp_teid[i] = 0;
-        memset(&UE->gnb_gtp_addrs[i], 0, sizeof(UE->gnb_gtp_addrs[i]));
-        UE->gnb_gtp_psi[i] = 0;
-      }
-    }
     gtpv1u_delete_ngu_tunnel(instance, &req);
     // NGAP_PDUSESSION_RELEASE_RESPONSE
     rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(&ctxt, ue_context_p, xid);
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h
index a0c42dcaaf465e130363d5f12bd0b443381c6f83..25e79746328f6dd6834a9462ea3610f2a2be50f3 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.h
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.h
@@ -96,12 +96,9 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_
 
 void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id);
 
-void
-rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(
-  const protocol_ctxt_t    *const ctxt_pP,
-  rrc_gNB_ue_context_t     *const ue_context_pP,
-  NR_UL_DCCH_Message_t     *const ul_dcch_msg
-);
+void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(const protocol_ctxt_t *const ctxt_pP,
+                                           rrc_gNB_ue_context_t *const ue_context_pP,
+                                           const NR_UECapabilityInformation_t *const ue_cap_info);
 
 int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance);
 
diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c
index 137ed695f5f3bd0c265d926936c79afbd6b3f846..b7f7e189ae7666c6aa1739053651c426389d2712 100644
--- a/openair2/RRC/NR/rrc_gNB_UE_context.c
+++ b/openair2/RRC/NR/rrc_gNB_UE_context.c
@@ -68,11 +68,8 @@ rrc_gNB_ue_context_t *rrc_gNB_allocate_new_ue_context(gNB_RRC_INST *rrc_instance
   }
   new_p->ue_context.gNB_ue_ngap_id = uid_linear_allocator_new(&rrc_instance_pP->uid_allocator);
 
-  for(int i = 0; i < NB_RB_MAX; i++) {
-    new_p->ue_context.e_rab[i].xid = -1;
+  for(int i = 0; i < NB_RB_MAX; i++)
     new_p->ue_context.pduSession[i].xid = -1;
-    new_p->ue_context.modify_e_rab[i].xid = -1;
-  }
 
   LOG_I(NR_RRC, "Returning new RRC UE context RRC ue id: %d\n", new_p->ue_context.gNB_ue_ngap_id);
   return(new_p);
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index 250402a2cfa3ce97c0ee3db982dd05c3c8673a8b..a8d9241b7f5675c57822d646943cca7bb7f41c5f 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -411,11 +411,11 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
   tmp.from_gnb=1;
   LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d will be deleted for rnti %d\n", ue_context->ue_context.nb_of_e_rabs, rnti);
   for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) {
-    tmp.eps_bearer_id[tmp.num_erab++]= ue_context->ue_context.gnb_gtp_ebi[e_rab];
+    tmp.eps_bearer_id[tmp.num_erab++]= ue_context->ue_context.nsa_gtp_ebi[e_rab];
     // erase data
-    ue_context->ue_context.gnb_gtp_teid[e_rab] = 0;
-    memset(&ue_context->ue_context.gnb_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.gnb_gtp_addrs[e_rab]));
-    ue_context->ue_context.gnb_gtp_ebi[e_rab] = 0;
+    ue_context->ue_context.nsa_gtp_teid[e_rab] = 0;
+    memset(&ue_context->ue_context.nsa_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.nsa_gtp_addrs[e_rab]));
+    ue_context->ue_context.nsa_gtp_ebi[e_rab] = 0;
   }
   gtpv1u_delete_s1u_tunnel(rrc->module_id,  &tmp);
   /* remove context */
diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c
index 069f3ce48bb19ae80853043e74a2c2ee987e454a..15f4b4b37654dce04a70867b24695f37b7fe82c9 100644
--- a/openair3/NGAP/ngap_gNB_nas_procedures.c
+++ b/openair3/NGAP/ngap_gNB_nas_procedures.c
@@ -58,7 +58,7 @@ static void allocCopy(OCTET_STRING_t *out, ngap_pdu_t in)
   out->size = in.length;
 }
 
-static void allocAddrCopy(BIT_STRING_t *out, ngap_transport_layer_addr_t in)
+static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
 {
   if (in.length) {
     out->buf = malloc(in.length);
diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp
index d8e1dc231414f106d49504806fbed116628c725b..5a75b8953ae291be852835a3edac08b2dd60fb02 100644
--- a/openair3/ocp-gtpu/gtp_itf.cpp
+++ b/openair3/ocp-gtpu/gtp_itf.cpp
@@ -762,6 +762,7 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance,
     create_tunnel_resp->gnb_NGu_teid[i]=teid;
     memcpy(create_tunnel_resp->gnb_addr.buffer,addr,sizeof(addr));
     create_tunnel_resp->gnb_addr.length= sizeof(addr);
+    create_tunnel_resp->pdusession_id[i] = create_tunnel_req->pdusession_id[i];
   }
 
   return !GTPNOK;