diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h
index b1161e2b6da6da56d901f885121b1d3156d2266f..11fdd0e7bf9e46de3d715feb80cd64695b6f1324 100644
--- a/openair2/COMMON/e1ap_messages_types.h
+++ b/openair2/COMMON/e1ap_messages_types.h
@@ -27,6 +27,7 @@
 #include "E1AP_E1AP-PDU.h"
 #include "E1AP_TransactionID.h"
 #include "E1AP_PriorityLevel.h"
+#include "ngap_messages_types.h"
 
 #define E1AP_MAX_NUM_TRANSAC_IDS 4
 #define E1AP_MAX_NUM_PLMNS 4
@@ -44,7 +45,7 @@
 #define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR)     (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp
 
 #define E1AP_PORT_NUMBER 25
-#define E1AP_SCTP_PPID 63
+#define E1AP_SCTP_PPID 64
 
 typedef f1ap_net_ip_address_t e1ap_net_ip_address_t;
 
@@ -101,6 +102,7 @@ typedef struct drb_to_setup_s {
 
 typedef struct qos_flow_to_setup_s {
   long id;
+  fiveQI_type_t fiveQI_type;
   long fiveQI;
   long qoSPriorityLevel;
   long packetDelayBudget;
@@ -116,6 +118,9 @@ typedef struct DRB_nGRAN_to_setup_s {
   long defaultDRB;
   long sDAP_Header_UL;
   long sDAP_Header_DL;
+  long pDCP_SN_Size_UL;
+  long pDCP_SN_Size_DL;
+  long rLC_Mode;
   int numCellGroups;
   cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
   int numQosFlow2Setup;
@@ -138,7 +143,7 @@ typedef struct e1ap_bearer_setup_req_s {
   uint64_t gNB_cu_cp_ue_id;
   uint64_t cipheringAlgorithm;
   char     encryptionKey[128];
-  long     bitRate;
+  long     ueDlAggMaxBitRate;
   PLMN_ID_t servingPLMNid;
   long activityNotificationLevel;
   int numDRBs;
diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h
index ca7dd0b0bb2c08ef0227c9a53db8a59863fc6650..6e9077088ee81ae5a786b329da07efcc4bb98312 100644
--- a/openair2/COMMON/ngap_messages_types.h
+++ b/openair2/COMMON/ngap_messages_types.h
@@ -262,9 +262,15 @@ typedef struct ngap_transport_layer_addr_s {
       dEST.length = sOURCE.length;                    \
   } while (0)
 
+typedef enum {
+  non_dynamic,
+  dynamic
+} fiveQI_type_t;
+
 typedef struct pdusession_level_qos_parameter_s {
   uint8_t  qfi;
   uint64_t fiveQI;
+  fiveQI_type_t fiveQI_type;
   ngap_allocation_retention_priority_t allocation_retention_priority;
 } pdusession_level_qos_parameter_t;
 
@@ -692,12 +698,21 @@ typedef struct ngap_pdusession_setup_req_s {
   /* gNB ue ngap id as initialized by NGAP layer */
   uint32_t  gNB_ue_ngap_id;
 
+  /* S-NSSAI */
+  ngap_allowed_NSSAI_t allowed_nssai[8];
+
   /* Number of pdusession to be setup in the list */
   uint8_t nb_pdusessions_tosetup;
 
   /* E RAB setup request */
   pdusession_t pdusession_setup_params[NGAP_MAX_PDUSESSION];
 
+  /* UE Uplink Aggregated Max Bitrates */
+  uint64_t ueAggMaxBitRateUplink;
+
+  /* UE Downlink Aggregated Max Bitrates */
+  uint64_t ueAggMaxBitRateDownlink;
+
 } ngap_pdusession_setup_req_t;
 
 typedef struct ngap_pdusession_setup_resp_s {
diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c
index acdc6388a2fb808296f7b37b899cf80c87240800..60b0bed2d37e722be36a8c3bab73ac431d193d4f 100644
--- a/openair2/E1AP/e1ap.c
+++ b/openair2/E1AP/e1ap.c
@@ -175,6 +175,7 @@ int e1apCUUP_send_SETUP_REQUEST(instance_t instance) {
   ieC1->value.present              = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID;
   setup->transac_id = E1AP_get_next_transaction_identifier();
   ieC1->value.choice.TransactionID = setup->transac_id;
+  LOG_I(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id);
   /* mandatory */
   /* c2. GNB_CU_ID (integer value) */
   asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2);
@@ -341,11 +342,17 @@ int e1apCUUP_handle_SETUP_RESPONSE(instance_t instance,
   E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie;
 
   /* transac_id */
-  int transaction_id;
+  long transaction_id;
+  long old_transaction_id = getCxtE1(UPtype, instance)->setupReq.transac_id;
   F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in,
                              E1AP_ProtocolIE_ID_id_TransactionID, true);
   transaction_id = ie->value.choice.TransactionID;
-  LOG_D(E1AP, "gNB CU UP E1 setup response transaction ID: %d\n", transaction_id);
+  LOG_D(E1AP, "gNB CU UP E1 setup response transaction ID: %ld\n", transaction_id);
+
+  if (old_transaction_id != transaction_id)
+    LOG_E(E1AP, "Transaction IDs do not match %ld != %ld\n", old_transaction_id, transaction_id);
+
+  E1AP_free_transaction_identifier(transaction_id);
 
   /* do the required processing */
 
@@ -527,21 +534,23 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
   ieC3->id                         = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate;
   ieC3->criticality                = E1AP_Criticality_reject;
   ieC3->value.present              = E1AP_BearerContextSetupRequestIEs__value_PR_BitRate;
-  asn_long2INTEGER(&ieC3->value.choice.BitRate, bearerCxt->bitRate);
+  asn_long2INTEGER(&ieC3->value.choice.BitRate, bearerCxt->ueDlAggMaxBitRate);
   /* mandatory */
   /* c4. Serving PLMN */
   asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC4);
   ieC4->id                         = E1AP_ProtocolIE_ID_id_Serving_PLMN;
   ieC4->criticality                = E1AP_Criticality_ignore;
   ieC4->value.present              = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity;
-  MCC_MNC_TO_PLMNID(bearerCxt->servingPLMNid.mcc, bearerCxt->servingPLMNid.mnc, bearerCxt->servingPLMNid.mnc_digit_length, &ieC4->value.choice.PLMN_Identity);
+  e1ap_setup_req_t *setup = &getCxtE1(CPtype, instance)->setupReq;
+  PLMN_ID_t *servingPLMN = setup->plmns; // First PLMN is serving PLMN. TODO: Remove hard coding here
+  MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity);
   /* mandatory */
   /* Activity Notification Level */
   asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC5);
   ieC5->id                         = E1AP_ProtocolIE_ID_id_ActivityNotificationLevel;
   ieC5->criticality                = E1AP_Criticality_reject;
   ieC5->value.present              = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel;
-  ieC5->value.choice.ActivityNotificationLevel = bearerCxt->activityNotificationLevel;
+  ieC5->value.choice.ActivityNotificationLevel = 2;// TODO: Remove hard coding
   /* mandatory */
   /*  */
   asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6);
@@ -612,6 +621,10 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
         ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL;
         ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL;
 
+        ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL;
+        ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL;
+        ieC6_1_1->pDCP_Configuration.rLC_Mode        = j->rLC_Mode;
+
         for (cell_group_t *k=j->cellGroupList; k < j->cellGroupList+j->numCellGroups; k++) {
           asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1);
           ieC6_1_1_1->cell_Group_ID = k->id;
@@ -621,7 +634,7 @@ int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
           asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1);
           ieC6_1_1_1->qoS_Flow_Identifier = k->id;
 
-          if (0) { // non Dynamic 5QI
+          if (k->fiveQI_type == non_dynamic) { // non Dynamic 5QI
             ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
             asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI);
             non_Dynamic_5QI->fiveQI = k->fiveQI;
@@ -825,7 +838,7 @@ int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance,
                     "ie->criticality != E1AP_Criticality_reject\n");
         AssertFatal(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_BitRate,
                     "ie->value.present != E1AP_BearerContextSetupRequestIEs__value_PR_BitRate\n");
-        asn_INTEGER2long(&ie->value.choice.BitRate, &bearerCxt->bitRate);
+        asn_INTEGER2long(&ie->value.choice.BitRate, &bearerCxt->ueDlAggMaxBitRate);
         break;
 
       case E1AP_ProtocolIE_ID_id_Serving_PLMN:
diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c
index bc5ae0789d641e6ca9f48e0a22278dc7ca6a1c55..dd92f9c100eaa2a622306d592c7693c4d9ec998b 100644
--- a/openair2/E1AP/e1ap_common.c
+++ b/openair2/E1AP/e1ap_common.c
@@ -96,6 +96,17 @@ E1AP_TransactionID_t E1AP_get_next_transaction_identifier() {
   return genTransacId;
 }
 
+void E1AP_free_transaction_identifier(E1AP_TransactionID_t id) {
+
+  for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) {
+    if (id == transacID[i]) {
+      transacID[i] = 0;
+      return;
+    }
+  }
+  LOG_E(E1AP, "Couldn't find transaction ID %ld in list\n", id);
+}
+
 int e1ap_decode_initiating_message(E1AP_E1AP_PDU_t *pdu) {
   DevAssert(pdu != NULL);
 
diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h
index 72c4accaecb3607c6f9e85b535488c092b4efd24..fdb3a96596107986e8a9a9443877a63146fb6767 100644
--- a/openair2/E1AP/e1ap_common.h
+++ b/openair2/E1AP/e1ap_common.h
@@ -41,4 +41,6 @@ int e1ap_assoc_id(E1_t type, instance_t instance);
 int e1ap_encode_send(E1_t type, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func);
 
 void e1ap_common_init();
+
+void E1AP_free_transaction_identifier(E1AP_TransactionID_t id);
 #endif /* E1AP_COMMON_H_ */
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 466c41957a32b8df03cf308b4f53788dc5444188..6687fb06b3751955fe5b0e7de182247a4d2a9097 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -3876,7 +3876,7 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
   }
 }
 
-void rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
+int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
 
   AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
   gNB_RRC_INST *rrc = RC.nrrrc[0]; //TODO: remove hardcoding of RC index here
@@ -3890,10 +3890,13 @@ void rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
         rrc->configuration.mnc[i] == req->plmns[i].mnc) {
       LOG_E(NR_RRC, "PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n",
             req->plmns[i].mcc, req->plmns[i].mnc, rrc->configuration.mcc[i], rrc->configuration.mnc[i]);
+      return -1;
     }
   }
 
   itti_send_msg_to_task(TASK_CUCP_E1, instance, msg_p);
+
+  return 0;
 }
 
 ///---------------------------------------------------------------------------------------------------------------///
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 8f391417e0d991d518dd811e123981491def28dd..3c4e2dc269c752c532cec5c4d12e80cee0971620 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -58,6 +58,8 @@
 #include "NGAP_Cause.h"
 #include "NGAP_CauseRadioNetwork.h"
 #include "f1ap_messages_types.h"
+#include "E1AP_SDAP-Configuration.h"
+#include "E1AP_PDCP-Configuration.h"
 
 extern RAN_CONTEXT_t RC;
 
@@ -954,6 +956,7 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
 )
 //------------------------------------------------------------------------------
 {
+  gNB_RRC_INST                    *rrc;
   uint16_t                        ue_initial_id;
   uint32_t                        gNB_ue_ngap_id;
   rrc_gNB_ue_context_t            *ue_context_p = NULL;
@@ -967,68 +970,147 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
   ue_initial_id  = NGAP_PDUSESSION_SETUP_REQ(msg_p).ue_initial_id;
   gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id;
   ue_context_p   = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id);
+  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0);
+  rrc = RC.nrrrc[ctxt.module_id];
   LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n",
     instance, msg_name, ue_initial_id, gNB_ue_ngap_id);
 
-  if (ue_context_p == NULL) {
-    MessageDef *msg_fail_p = NULL;
-    LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id);
-    msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQUEST_FAIL);
-    NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id;
-    // TODO add failure cause when defined!
-    itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p);
-    return (-1);
-  } else {
-    memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t));
-    uint8_t nb_pdusessions_tosetup = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
-    pdu_sessions_done = 0;
+  if (RC.nrrrc[ctxt.module_id]->cu_type == CPtype) { // E1 split CU-CP node
+    /* Configurations are referred from rrc_gNB_generate_dedicatedRRCReconfiguration() and
+       rrc_gNB_process_RRCReconfigurationComplete()
+
+       At CU-CP we configure the E1 bearer context setup parameters (PDU sessions, DRBs and 
+       QoS flows) same as in these functions. At CU-UP we create PDU Sessions and allocate DRBs.
+    */
+    MessageDef *msg_p = NULL;
+    msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
+    e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p);
+
+    bearer_req->gNB_cu_cp_ue_id = gNB_ue_ngap_id;
+    bearer_req->cipheringAlgorithm = ue_context_p->ue_context.ciphering_algorithm;
+    memcpy(bearer_req->encryptionKey, ue_context_p->ue_context.kgnb, 128);
+    bearer_req->ueDlAggMaxBitRate = NGAP_PDUSESSION_SETUP_REQ(msg_p).ueAggMaxBitRateDownlink;
+
+    bearer_req->numPDUSessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
+    for (int i=0; i < bearer_req->numPDUSessions; i++) {
+      pdu_session_to_setup_t *pdu = bearer_req->pduSession + i;
+      pdu->sessionId   = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].pdusession_id;
+      pdu->sessionType = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].upf_addr.pdu_session_type;
+      pdu->sst         = NGAP_PDUSESSION_SETUP_REQ(msg_p).allowed_nssai[i].sST;
+      pdu->integrityProtectionIndication       = 1; // Preferred. TODO: Remove hardcoding
+      pdu->confidentialityProtectionIndication = 1; // Preferred. TODO: Remove hardcoding
+      pdu->teId                                = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].gtp_teid;
+      memcpy(&pdu->tlAddress,
+             NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].upf_addr.buffer,
+             sizeof(uint8_t)*20);
+
+      pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
+      for (int j=0; j < pdu->numDRB2Setup; j++) {
+        DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j;
+        drb->id = i + j;
+        drb->defaultDRB = E1AP_DefaultDRB_true;
+
+        drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap);
+        drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap);
+
+        drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18;
+        drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18;
+
+        drb->rLC_Mode = E1AP_RLC_Mode_rlc_am;
+
+        drb->numCellGroups = 1; // assume one cell group associated with a DRB
+        for (int k=0; k < drb->numCellGroups; k++) {
+          cell_group_t *cellGroup = drb->cellGroupList + k;
+          cellGroup->id = 0; // MCG
+        }
 
-    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0);
-    for (int i = 0; i < NR_NB_RB_MAX - 3; i++) {
-      if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE)
-        continue;
-      ue_context_p->ue_context.pduSession[i].status      = PDU_SESSION_STATUS_NEW;
-      ue_context_p->ue_context.pduSession[i].param       = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done];
-      create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id;
-      create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1;
-      create_tunnel_req.outgoing_teid[pdu_sessions_done]  = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid;
-      create_tunnel_req.outgoing_qfi[pdu_sessions_done]  = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].qos[0].qfi;
-      memcpy(create_tunnel_req.dst_addr[pdu_sessions_done].buffer,
-              NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer,
-              sizeof(uint8_t)*20);
-      create_tunnel_req.dst_addr[pdu_sessions_done].length = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.length;
-      LOG_I(NR_RRC,"NGAP PDUSESSION SETUP REQ: local index %d teid %u, pdusession id %d \n",
-            i,
-            create_tunnel_req.outgoing_teid[pdu_sessions_done],
-            create_tunnel_req.pdusession_id[pdu_sessions_done]);
-      inde_list[pdu_sessions_done] = i;
-      pdu_sessions_done++;
+        drb->numQosFlow2Setup = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].nb_qos;
+        for (int k=0; k < drb->numQosFlow2Setup; k++) {
+          qos_flow_to_setup_t *qos = drb->qosFlows + k;
 
-      if(pdu_sessions_done >= nb_pdusessions_tosetup) {
-        break;
+          qos->id          = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].qfi;
+          qos->fiveQI      = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].fiveQI;
+          qos->fiveQI_type = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].fiveQI_type;
+
+          qos->qoSPriorityLevel = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].allocation_retention_priority.priority_level;
+          qos->pre_emptionCapability = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_capability;
+          qos->pre_emptionVulnerability = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_vulnerability;
+        }
       }
     }
+    itti_send_msg_to_task (TASK_CUCP_E1, ctxt.module_id, msg_p);
+
+  } else { // Monolithic
+    if (ue_context_p == NULL) {
+      MessageDef *msg_fail_p = NULL;
+      LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id);
+      msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQUEST_FAIL);
+      NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id;
+      // TODO add failure cause when defined!
+      itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p);
+      return (-1);
+    } else {
+      memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t));
+      uint8_t nb_pdusessions_tosetup = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
+      pdu_sessions_done = 0;
 
-    ue_context_p->ue_context.nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
-    ue_context_p->ue_context.gNB_ue_ngap_id    = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id;
-    ue_context_p->ue_context.amf_ue_ngap_id    = NGAP_PDUSESSION_SETUP_REQ(msg_p).amf_ue_ngap_id;
-    create_tunnel_req.rnti                     = ue_context_p->ue_context.rnti;
-    create_tunnel_req.num_tunnels              = pdu_sessions_done;
+      for (int i = 0; i < NR_NB_RB_MAX - 3; i++) {
+        if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE)
+          continue;
+        ue_context_p->ue_context.pduSession[i].status      = PDU_SESSION_STATUS_NEW;
+        ue_context_p->ue_context.pduSession[i].param       = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done];
+        create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id;
+        create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1;
+        create_tunnel_req.outgoing_teid[pdu_sessions_done]  = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid;
+        create_tunnel_req.outgoing_qfi[pdu_sessions_done]  = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].qos[0].qfi;
+        memcpy(create_tunnel_req.dst_addr[pdu_sessions_done].buffer,
+                NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer,
+                sizeof(uint8_t)*20);
+        create_tunnel_req.dst_addr[pdu_sessions_done].length = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.length;
+        LOG_I(NR_RRC,"NGAP PDUSESSION SETUP REQ: local index %d teid %u, pdusession id %d \n",
+              i,
+              create_tunnel_req.outgoing_teid[pdu_sessions_done],
+              create_tunnel_req.pdusession_id[pdu_sessions_done]);
+        inde_list[pdu_sessions_done] = i;
+        pdu_sessions_done++;
 
-    ret = gtpv1u_create_ngu_tunnel(
-            instance,
-            &create_tunnel_req,
-            &create_tunnel_resp);
-    if (ret != 0) {
-      LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti);
-      ue_context_p->ue_context.ue_release_timer_ng = 1;
-      ue_context_p->ue_context.ue_release_timer_thres_ng = 100;
-      ue_context_p->ue_context.ue_release_timer = 0;
-      ue_context_p->ue_context.ue_reestablishment_timer = 0;
-      ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
-      // rrc_gNB_free_UE(ctxt.module_id,ue_context_p);
-      ue_context_p->ue_context.ul_failure_timer = 0;
-      return (0);
+        if(pdu_sessions_done >= nb_pdusessions_tosetup) {
+          break;
+        }
+      }
+
+      ue_context_p->ue_context.nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup;
+      ue_context_p->ue_context.gNB_ue_ngap_id    = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id;
+      ue_context_p->ue_context.amf_ue_ngap_id    = NGAP_PDUSESSION_SETUP_REQ(msg_p).amf_ue_ngap_id;
+      create_tunnel_req.rnti                     = ue_context_p->ue_context.rnti;
+      create_tunnel_req.num_tunnels              = pdu_sessions_done;
+
+      ret = gtpv1u_create_ngu_tunnel(
+              instance,
+              &create_tunnel_req,
+              &create_tunnel_resp);
+      if (ret != 0) {
+        LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti);
+        ue_context_p->ue_context.ue_release_timer_ng = 1;
+        ue_context_p->ue_context.ue_release_timer_thres_ng = 100;
+        ue_context_p->ue_context.ue_release_timer = 0;
+        ue_context_p->ue_context.ue_reestablishment_timer = 0;
+        ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
+        // rrc_gNB_free_UE(ctxt.module_id,ue_context_p);
+        ue_context_p->ue_context.ul_failure_timer = 0;
+        return (0);
+      }
+      nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
+        &ctxt,
+        &create_tunnel_resp,
+        &inde_list[0]);
+      ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup;
+
+      // TEST 
+      // ue_context_p->ue_context.pdusession[0].status = PDU_SESSION_STATUS_DONE;
+      // rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(&ctxt, ue_context_p, 0);
+      rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
+      return(0);
     }
     nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
       &ctxt,
diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c
index 35b152f1298ee2e7ab35fe57a2640e68673740ec..ebe86afe2a7e4afbd44b9ac21428088fd6623fba 100644
--- a/openair3/NGAP/ngap_gNB_handlers.c
+++ b/openair3/NGAP/ngap_gNB_handlers.c
@@ -1321,6 +1321,14 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t         assoc_id,
   NGAP_PDUSESSION_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id;
   NGAP_PDUSESSION_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id;
 
+  /* UE Aggregated Maximum Bitrate */
+  NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container,
+                         NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, true);
+  asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL),
+                    &NGAP_PDUSESSION_SETUP_REQ(message_p).ueAggMaxBitRateUplink);
+  asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL),
+                    &NGAP_PDUSESSION_SETUP_REQ(message_p).ueAggMaxBitRateDownlink);
+
   NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container,
                          NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true);
 
@@ -1334,9 +1342,13 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t         assoc_id,
       NGAP_PDUSessionResourceSetupRequestTransfer_t    *pdusessionTransfer_p   = NULL;
       NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL;
 
+      // PDU session ID
       item_p = (NGAP_PDUSessionResourceSetupItemSUReq_t *)ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i];
       NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID;
 
+      // S-NSSAI
+      OCTET_STRING_TO_INT32(&item_p->s_NSSAI.sST, NGAP_PDUSESSION_SETUP_REQ(message_p).allowed_nssai[i].sST);
+      OCTET_STRING_TO_INT32(item_p->s_NSSAI.sD, *NGAP_PDUSESSION_SETUP_REQ(message_p).allowed_nssai[i].sD);
 
       // check for the NAS PDU
       if (item_p->pDUSessionNAS_PDU->size > 0 ) {
@@ -1422,10 +1434,14 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t         assoc_id,
               /* Set the QOS informations */
               NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
               if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){
+                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI_type = non_dynamic;
                 if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){
                   NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI = 
                     (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI;
                 }
+              } else if (qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI)
+              {
+                NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI_type = dynamic;
               }
               NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level =
                 qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP;