diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c
index 832f785551b08fb37208621f1c3a544b06ec1997..6fcf5b7ea32763fead2a1447d1b68f7d4f297a7e 100644
--- a/executables/nr-cuup.c
+++ b/executables/nr-cuup.c
@@ -84,7 +84,7 @@ int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t ch
   return 0;
 }
 
-void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_CellGroupConfig_t *cell_groupConfig_from_DU)
+void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
 {
   abort();
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
index 2c4f748fa83ab35f77354e7d17df0ad676f50189..006db8ac44ae6d63287001d99b1824dc71c93f56 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
@@ -33,25 +33,27 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_set
   return get_SRB_RLC_BearerConfig(srb->srb_id, priority, bucket);
 }
 
-static void handle_ue_context_srbs_setup(const f1ap_ue_context_setup_t *req,
-                                         f1ap_ue_context_setup_t *resp,
-                                         NR_CellGroupConfig_t *cellGroupConfig)
+static int handle_ue_context_srbs_setup(int rnti,
+                                        int srbs_len,
+                                        const f1ap_srb_to_be_setup_t *req_srbs,
+                                        f1ap_srb_to_be_setup_t **resp_srbs,
+                                        NR_CellGroupConfig_t *cellGroupConfig)
 {
-  DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
+  DevAssert(req_srbs != NULL && resp_srbs != NULL && cellGroupConfig != NULL);
 
-  resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length;
-  resp->srbs_to_be_setup = calloc(req->srbs_to_be_setup_length, sizeof(*resp->srbs_to_be_setup));
-  AssertFatal(resp->srbs_to_be_setup != NULL, "out of memory\n");
-  for (int i = 0; i < req->srbs_to_be_setup_length; i++) {
-    f1ap_srb_to_be_setup_t *srb = &req->srbs_to_be_setup[i];
+  *resp_srbs = calloc(srbs_len, sizeof(**resp_srbs));
+  AssertFatal(*resp_srbs != NULL, "out of memory\n");
+  for (int i = 0; i < srbs_len; i++) {
+    const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
     NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb);
-    nr_rlc_add_srb(req->rnti, srb->srb_id, rlc_BearerConfig);
+    nr_rlc_add_srb(rnti, srb->srb_id, rlc_BearerConfig);
 
-    resp->srbs_to_be_setup[i] = *srb;
+    (*resp_srbs)[i] = *srb;
 
     int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
     DevAssert(ret == 0);
   }
+  return srbs_len;
 }
 
 static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb)
@@ -61,27 +63,31 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_set
   return get_DRB_RLC_BearerConfig(3 + drb->drb_id, drb->drb_id, rlc_conf, priority);
 }
 
-static void handle_ue_context_drbs_setup(const f1ap_ue_context_setup_t *req,
-                                         f1ap_ue_context_setup_t *resp,
-                                         NR_CellGroupConfig_t *cellGroupConfig)
+static int handle_ue_context_drbs_setup(int rnti,
+                                        int drbs_len,
+                                        const f1ap_drb_to_be_setup_t *req_drbs,
+                                        f1ap_drb_to_be_setup_t **resp_drbs,
+                                        NR_CellGroupConfig_t *cellGroupConfig)
 {
-  DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
+  DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
 
   /* Note: the actual GTP tunnels are created in the F1AP breanch of
    * ue_context_*_response() */
-  resp->drbs_to_be_setup_length = req->drbs_to_be_setup_length;
-  resp->drbs_to_be_setup = calloc(req->drbs_to_be_setup_length, sizeof(*resp->drbs_to_be_setup));
-  AssertFatal(resp->drbs_to_be_setup != NULL, "out of memory\n");
-  for (int i = 0; i < req->drbs_to_be_setup_length; i++) {
-    f1ap_drb_to_be_setup_t *drb = &req->drbs_to_be_setup[i];
+  *resp_drbs = calloc(drbs_len, sizeof(**resp_drbs));
+  AssertFatal(*resp_drbs != NULL, "out of memory\n");
+  for (int i = 0; i < drbs_len; i++) {
+    const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
     NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
-    nr_rlc_add_drb(req->rnti, drb->drb_id, rlc_BearerConfig);
+    nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
 
-    resp->drbs_to_be_setup[i] = *drb;
+    (*resp_drbs)[i] = *drb;
+    // just put same number of tunnels in DL as in UL
+    (*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
 
     int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
     DevAssert(ret == 0);
   }
+  return drbs_len;
 }
 
 void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
@@ -105,11 +111,20 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
   NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
   AssertFatal(UE != NULL, "did not find UE with RNTI %04x, but UE Context Setup Failed not implemented\n", req->rnti);
 
-  if (req->srbs_to_be_setup_length > 0)
-    handle_ue_context_srbs_setup(req, &resp, UE->CellGroup);
+  if (req->srbs_to_be_setup_length > 0) {
+    resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
+                                                                req->srbs_to_be_setup_length,
+                                                                req->srbs_to_be_setup,
+                                                                &resp.srbs_to_be_setup,
+                                                                UE->CellGroup);
+  }
 
   if (req->drbs_to_be_setup_length > 0) {
-    handle_ue_context_drbs_setup(req, &resp, NULL);
+    resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
+                                                                req->drbs_to_be_setup_length,
+                                                                req->drbs_to_be_setup,
+                                                                &resp.drbs_to_be_setup,
+                                                                UE->CellGroup);
   }
 
   if (req->rrc_container != NULL)
@@ -149,8 +164,81 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
 
 void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
 {
-  (void)req;
-  AssertFatal(false, "not implemented\n");
+  gNB_MAC_INST *mac = RC.nrmac[0];
+  f1ap_ue_context_modif_resp_t resp = {
+    .gNB_CU_ue_id = req->gNB_CU_ue_id,
+    .gNB_DU_ue_id = req->gNB_DU_ue_id,
+    .rnti = req->rnti,
+  };
+
+  if (req->cu_to_du_rrc_information != NULL) {
+    AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
+    AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n");
+    AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
+  }
+
+  NR_SCHED_LOCK(&mac->sched_lock);
+  NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
+
+  if (req->srbs_to_be_setup_length > 0) {
+    resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
+                                                                req->srbs_to_be_setup_length,
+                                                                req->srbs_to_be_setup,
+                                                                &resp.srbs_to_be_setup,
+                                                                UE->CellGroup);
+  }
+
+  if (req->drbs_to_be_setup_length > 0) {
+    resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
+                                                                req->drbs_to_be_setup_length,
+                                                                req->drbs_to_be_setup,
+                                                                &resp.drbs_to_be_setup,
+                                                                UE->CellGroup);
+  }
+
+  if (req->rrc_container != NULL)
+    nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length);
+
+  if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) {
+    LOG_E(NR_MAC,
+          "RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
+  }
+
+  if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
+    /* TODO: if we change e.g. BWP or MCS table, need to automatically call
+     * configure_UE_BWP() (form nr_mac_update_timers()) after some time? */
+
+    resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
+    AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
+    resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
+    AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n");
+    asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
+                                                    NULL,
+                                                    UE->CellGroup,
+                                                    resp.du_to_cu_rrc_information->cellGroupConfig,
+                                                    1024);
+    AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
+    resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
+
+    /* works? */
+    nr_mac_update_cellgroup(RC.nrmac[0], req->rnti, UE->CellGroup);
+  }
+  NR_SCHED_UNLOCK(&mac->sched_lock);
+
+  /* some sanity checks, since we use the same type for request and response */
+  DevAssert(resp.cu_to_du_rrc_information == NULL);
+  // resp.du_to_cu_rrc_information can be either NULL or not
+  DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0);
+
+  mac->mac_rrc.ue_context_modification_response(req, &resp);
+
+  /* free the memory we allocated above */
+  free(resp.srbs_to_be_setup);
+  free(resp.drbs_to_be_setup);
+  if (resp.du_to_cu_rrc_information != NULL) {
+    free(resp.du_to_cu_rrc_information->cellGroupConfig);
+    free(resp.du_to_cu_rrc_information);
+  }
 }
 
 void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
index 51944970c3764339e6aac70ffd79dce218197592..6780fad87332aea08ca768bfeb8c960d2c0405ab 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
@@ -59,8 +59,57 @@ static void ue_context_modification_response_direct(const f1ap_ue_context_modif_
                                                     const f1ap_ue_context_modif_resp_t *resp)
 {
   (void)req; /* we don't need the request -- it is to set up GTP in F1 case */
-  (void)resp;
-  AssertFatal(false, "not implemented yet\n");
+  MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
+  f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg);
+
+  f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id;
+  f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id;
+  f1ap_msg->rnti = resp->rnti;
+  f1ap_msg->mcc = resp->mcc;
+  f1ap_msg->mnc = resp->mnc;
+  f1ap_msg->mnc_digit_length = resp->mnc_digit_length;
+  f1ap_msg->nr_cellid = resp->nr_cellid;
+  f1ap_msg->servCellIndex = resp->servCellIndex;
+  AssertFatal(resp->cellULConfigured == NULL, "not handled\n");
+  f1ap_msg->servCellId = resp->servCellId;
+
+  DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0);
+  if (resp->du_to_cu_rrc_information) {
+    f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
+    AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
+    f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length;
+    du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
+    du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length;
+    du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig));
+    AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
+    memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
+  }
+
+  if (resp->drbs_to_be_setup_length > 0) {
+    DevAssert(resp->drbs_to_be_setup != NULL);
+    f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
+    f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
+    for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
+      f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
+  }
+
+  DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0);
+  f1ap_msg->QoS_information_type = resp->QoS_information_type;
+  AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n");
+
+  if (resp->srbs_to_be_setup_length > 0) {
+    DevAssert(resp->srbs_to_be_setup != NULL);
+    f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length;
+    f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup));
+    for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
+      f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
+  }
+
+  AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n");
+
+  DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0);
+
+  itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
 }
 
 static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req)
diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c
index d0d4365e70a8cdc30386f010d197d0cad8ec4548..9a74b3826bbd434e8c1b76ac81478759d539c38d 100644
--- a/openair2/RRC/NR/cucp_cuup_direct.c
+++ b/openair2/RRC/NR/cucp_cuup_direct.c
@@ -187,6 +187,19 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
 
   fill_DRB_configList(&ctxt, ue_context_p, xid);
+  e1ap_bearer_setup_resp_t resp = {0};
+  resp.numPDUSessions = req->numPDUSessions;
+  for (int i = 0; i < resp.numPDUSessions; ++i) {
+    resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
+    for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
+      DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
+      DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
+      resp_drb->id = req_drb->id;
+      resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
+      for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
+        resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
+    }
+  }
 
   gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
   // Fixme: xid not random, but almost!
@@ -195,21 +208,26 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
   int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, UE->DRB_configList, *SRB_configList2, rrc->e1_inst);
   if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
 
+  // Used to store teids: if monolithic, will simply be NULL
   if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
-    rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL);
+    // intentionally empty
   } else {
-    e1ap_bearer_setup_resp_t resp; // Used to store teids
     int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd;
     in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr);
     instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
     // GTP tunnel for DL
     fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rnti, remote_port, my_addr);
-
-    prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
   }
+  // actually, we should receive the corresponding context setup response
+  // message at the RRC and always react to this one. So in the following, we
+  // just call the corresponding message handler
+  prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
 }
 
 static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) {
+  // only update GTP tunnels if it is really a CU
+  if (!NODE_IS_CU(RC.nrrrc[0]->node_type))
+    return;
   instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
   CU_update_UP_DL_tunnel(req, gtpInst, req->rnti);
 }
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 384269748a48c52e6a19c9138a25b239683e62ab..504aced6818017d519b0eb63ffbab66897e7d023 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -142,11 +142,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
     uint32_t                 nas_length,
     uint8_t                 *nas_buffer);
 
-void 
-rrc_gNB_generate_dedicatedRRCReconfiguration(
-    const protocol_ctxt_t     *const ctxt_pP,
-    rrc_gNB_ue_context_t      *ue_context_pP,
-    NR_CellGroupConfig_t      *cell_groupConfig_from_DU);
+void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
 
 void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req,
                                  instance_t instance);
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index f618ccdf3101f52562313f8005be7a313101540f..1b4d09ba27dcf4e5e70721bdd3fb634262c3db6e 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -641,17 +641,10 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_contex
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_gNB_generate_dedicatedRRCReconfiguration(
-    const protocol_ctxt_t     *const ctxt_pP,
-    rrc_gNB_ue_context_t      *ue_context_pP,
-    NR_CellGroupConfig_t      *cell_groupConfig_from_DU
-)
+void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
 //-----------------------------------------------------------------------------
 {
   gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
-  long drb_priority[NGAP_MAX_DRBS_PER_UE];
-  NR_CellGroupConfig_t *cellGroupConfig = NULL;
   int xid = -1;
 
   int drb_id_to_setup_start = 1;
@@ -682,7 +675,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
     }
 
     xid = ue_p->pduSession[j].xid;
-    drb_priority[DRB_config->drb_Identity - 1] = 13; // For now, we assume only one drb per pdu sessions with a default preiority (will be dynamique in future)
   }
 
   /* If list is empty free the list and reset the address */
@@ -691,20 +683,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
     dedicatedNAS_MessageList = NULL;
   }
 
-  if(cell_groupConfig_from_DU == NULL){
-    cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
-    // FIXME: fill_mastercellGroupConfig() won't fill the right priorities
-    fill_mastercellGroupConfig(cellGroupConfig,
-                               ue_p->masterCellGroup,
-                               rrc->um_on_default_drb,
-                               (drb_id_to_setup_start < 2) ? 1 : 0,
-                               DRB_configList,
-                               drb_priority);
-  }
-  else{
-    LOG_I(NR_RRC, "Master cell group originating from the DU \n");
-    cellGroupConfig = cell_groupConfig_from_DU;
-  }
+  NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup;
 
   AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid);
   NR_SRB_ToAddModList_t *SRB_configList2 = NULL;
@@ -2572,69 +2551,46 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
   rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti);
   gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
 
-  e1ap_bearer_setup_req_t req = {0};
-  req.numPDUSessionsMod = UE->nb_of_pdusessions;
-  req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
-  req.rnti = UE->rnti;
-  for (int i=0; i < req.numPDUSessionsMod; i++) {
-    req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
-    for (int j=0; j < resp->drbs_to_be_setup_length; j++) {
-      f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
-      DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
-
-      drb_e1->id = drb_f1->drb_id;
-      drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
-      drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
-      drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
+  if (resp->drbs_to_be_setup_length > 0) {
+    e1ap_bearer_setup_req_t req = {0};
+    req.numPDUSessionsMod = UE->nb_of_pdusessions;
+    req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
+    req.rnti = UE->rnti;
+    for (int i = 0; i < req.numPDUSessionsMod; i++) {
+      req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
+      for (int j = 0; j < resp->drbs_to_be_setup_length; j++) {
+        f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
+        DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
+
+        drb_e1->id = drb_f1->drb_id;
+        drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
+        drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
+        drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
+      }
     }
-  }
-
-  // send the F1 response message up to update F1-U tunnel info
-  // 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;
-
-  if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){
-    asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
-      &asn_DEF_NR_CellGroupConfig,
-      (void **)&cellGroupConfig,
-      (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
-      (int) resp->du_to_cu_rrc_information->cellGroupConfig_length);
-
-    if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
-      AssertFatal(1==0,"Cell group config decode error\n");
-      // free the memory
-      SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, cellGroupConfig, 1 );
-      return;
-    }
-    //xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, cellGroupConfig);
+    // send the F1 response message up to update F1-U tunnel info
+    // it seems the rrc transaction id (xid) is not needed here
+    rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
+  }
 
-    if (UE->masterCellGroup == NULL) {
-      UE->masterCellGroup = calloc(1, sizeof(NR_CellGroupConfig_t));
-    }
+  if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) {
+    LOG_W(RRC, "UE context modification response contains new CellGroupConfig for UE %04x, triggering reconfiguration\n", UE->rnti);
+    NR_CellGroupConfig_t *cellGroupConfig = NULL;
+    asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
+                                                   &asn_DEF_NR_CellGroupConfig,
+                                                   (void **)&cellGroupConfig,
+                                                   (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
+                                                   resp->du_to_cu_rrc_information->cellGroupConfig_length);
+    AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n");
 
-    if(cellGroupConfig->rlc_BearerToAddModList!=NULL){
-      if (UE->masterCellGroup->rlc_BearerToAddModList != NULL) {
-        int ue_ctxt_rlc_Bearers = UE->masterCellGroup->rlc_BearerToAddModList->list.count;
-        for(int i=ue_ctxt_rlc_Bearers; i<ue_ctxt_rlc_Bearers + cellGroupConfig->rlc_BearerToAddModList->list.count; i++){
-          asn1cSeqAdd(&UE->masterCellGroup->rlc_BearerToAddModList->list, cellGroupConfig->rlc_BearerToAddModList->list.array[i - ue_ctxt_rlc_Bearers]);
-        }
-      } else {
-        LOG_W(NR_RRC, "Empty rlc_BearerToAddModList at ue_context of the CU before filling the updates from UE context setup response \n");
-        UE->masterCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
-        memcpy(UE->masterCellGroup->rlc_BearerToAddModList, cellGroupConfig->rlc_BearerToAddModList, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
-      }
+    if (UE->masterCellGroup) {
+      ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
+      LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti);
     }
-    LOG_I(NR_RRC, "Updated master cell group configuration stored at the UE context of the CU:\n");
-    if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
-      xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
-    }
-
-    rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig);
+    UE->masterCellGroup = cellGroupConfig;
 
-    free(cellGroupConfig->rlc_BearerToAddModList);
-    free(cellGroupConfig);
+    rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
   }
 }
 
@@ -2817,46 +2773,49 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
   return 0;
 }
 
-void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
-                                                 e1ap_bearer_setup_resp_t *e1ap_resp) {
+void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
+{
+  /* Generate a UE context modification request message towards the DU to
+   * instruct the DU for SRB2 and DRB configuration and get the updates on
+   * master cell group config from the DU*/
 
-  /*Generate a UE context modification request message towards the DU to instruct the DU
-   *for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/
+  gNB_RRC_INST *rrc = RC.nrrrc[0];
   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);
-  // TODO: So many hard codings
-  MessageDef *message_p;
-  message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
-  f1ap_ue_context_modif_req_t *req = &F1AP_UE_CONTEXT_MODIFICATION_REQ(message_p);
-  req->rnti = UE->rnti;
-  req->mcc              = RC.nrrrc[ctxt.module_id]->configuration.mcc[0];
-  req->mnc              = RC.nrrrc[ctxt.module_id]->configuration.mnc[0];
-  req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0];
-  req->nr_cellid        = RC.nrrrc[ctxt.module_id]->nr_cellid;
-
-  /*Instruction towards the DU for SRB2 configuration*/
-  req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t));
-  req->srbs_to_be_setup_length = 1;
-  f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup;
-  SRBs[0].srb_id = 2;
-  SRBs[0].lcid = 2;
-
-  /*Instruction towards the DU for DRB configuration and tunnel creation*/
-  req->drbs_to_be_setup_length = e1ap_resp->pduSession[0].numDRBSetup;
-  req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)*req->drbs_to_be_setup_length);
-  for (int i=0; i < e1ap_resp->pduSession[0].numDRBSetup; i++) {
-    f1ap_drb_to_be_setup_t *DRBs =  req->drbs_to_be_setup + i;
-    DRBs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
-    DRBs[i].rlc_mode = RLC_MODE_AM;
-    DRBs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
-    DRBs[i].up_ul_tnl[0].port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd;
-    DRBs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
-    DRBs[i].up_ul_tnl_length = 1;
-  }
-
-  itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p);
+  /* Instruction towards the DU for DRB configuration and tunnel creation */
+  int nb_drb = e1ap_resp->pduSession[0].numDRBSetup;
+  f1ap_drb_to_be_setup_t drbs[nb_drb];
+  for (int i = 0; i < nb_drb; i++) {
+    drbs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
+    drbs[i].rlc_mode = rrc->um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
+    drbs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
+    drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
+    drbs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
+    drbs[i].up_ul_tnl_length = 1;
+  }
+
+  /* Instruction towards the DU for SRB2 configuration */
+  int nb_srb = 1;
+  f1ap_srb_to_be_setup_t srbs[nb_srb];
+  srbs[0].srb_id = 2;
+  srbs[0].lcid = 2;
+  srbs[0].rlc_mode = RLC_MODE_AM;
+
+  f1ap_ue_context_modif_req_t ue_context_modif_req = {
+    .gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
+    .gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
+    .rnti = UE->rnti,
+    .mcc = rrc->configuration.mcc[0],
+    .mnc = rrc->configuration.mnc[0],
+    .mnc_digit_length = rrc->configuration.mnc_digit_length[0],
+    .nr_cellid = rrc->nr_cellid,
+    .servCellId = 0, /* TODO: correct value? */
+    .srbs_to_be_setup_length = nb_srb,
+    .srbs_to_be_setup = srbs,
+    .drbs_to_be_setup_length = nb_drb,
+    .drbs_to_be_setup = drbs,
+  };
+  rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
 }
 
 void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) {