From e665dbab28c49327066cff72aed22e1de7797b59 Mon Sep 17 00:00:00 2001
From: Sakthivel Velumani <velumani@eurecom.fr>
Date: Thu, 1 Sep 2022 17:52:07 -0400
Subject: [PATCH] Common interface between CUCP & CUUP for E1 and non E1 modes

---
 CMakeLists.txt                     |   2 +
 openair2/E1AP/e1ap_api.c           |  67 +--------
 openair2/E1AP/e1ap_api.h           |   9 --
 openair2/RRC/NR/cucp_cuup_direct.c | 219 +++++++++++++++++++++++++++++
 openair2/RRC/NR/cucp_cuup_e1ap.c   |  61 ++++++++
 openair2/RRC/NR/cucp_cuup_if.h     |  42 ++++++
 openair2/RRC/NR/nr_rrc_defs.h      |  12 +-
 openair2/RRC/NR/nr_rrc_proto.h     |   5 +
 openair2/RRC/NR/rrc_gNB.c          | 176 ++---------------------
 openair2/RRC/NR/rrc_gNB_NGAP.c     |   2 +-
 10 files changed, 356 insertions(+), 239 deletions(-)
 create mode 100644 openair2/RRC/NR/cucp_cuup_direct.c
 create mode 100644 openair2/RRC/NR/cucp_cuup_e1ap.c
 create mode 100644 openair2/RRC/NR/cucp_cuup_if.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 71728f79f49..e8642f5fafa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1900,6 +1900,8 @@ set(L2_NR_SRC
   ${NR_RRC_DIR}/L2_nr_interface.c
   ${NR_RRC_DIR}/mac_rrc_dl_direct.c
   ${NR_RRC_DIR}/mac_rrc_dl_f1ap.c
+  ${NR_RRC_DIR}/cucp_cuup_direct.c
+  ${NR_RRC_DIR}/cucp_cuup_e1ap.c
   ${NR_RRC_DIR}/nr_rrc_config.c
   ${NR_RRC_DIR}/rrc_gNB_nsa.c
   ${NR_RRC_DIR}/rrc_gNB_internode.c
diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c
index 45c7be47565..ec60e0c9504 100644
--- a/openair2/E1AP/e1ap_api.c
+++ b/openair2/E1AP/e1ap_api.c
@@ -25,9 +25,10 @@
 #include "UTIL/OSA/osa_defs.h"
 #include "nr_pdcp/nr_pdcp_entity.h"
 #include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
+#include "openair2/RRC/NR/cucp_cuup_if.h"
 #include "openair3/ocp-gtpu/gtp_itf.h"
 
-static void fill_DRB_configList(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) {
+static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) {
 
   for (int i=0; i < pdu->numDRB2Setup; i++) {
     DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i;
@@ -109,7 +110,7 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t *req,
            sizeof(uint8_t)*4);
     create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes
     create_tunnel_req.outgoing_teid[i] = pdu->teId;
-    fill_DRB_configList(&DRB_configList, pdu);
+    fill_DRB_configList_e1(&DRB_configList, pdu);
   }
   create_tunnel_req.num_tunnels = req->numPDUSessions;
   create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF);
@@ -145,44 +146,6 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t *req,
   return ret;
 }
 
-void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp,
-                                e1ap_bearer_setup_req_t *req,
-                                instance_t gtpInst,
-                                ue_id_t ue_id,
-                                int remote_port,
-                                in_addr_t my_addr) {
-
-  resp->numPDUSessions = req->numPDUSessions;
-  transport_layer_addr_t dummy_address = {0};
-  dummy_address.length = 32; // IPv4
-  for (int i=0; i < req->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 *drb2Setup = req->pduSession[i].DRBnGRanList + j;
-      DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j;
-
-      drbSetup->numUpParam = 1;
-      drbSetup->UpParamList[0].tlAddress = my_addr;
-      drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst,
-                                                          (ue_id & 0xFFFF),
-                                                          drb2Setup->id,
-                                                          drb2Setup->id,
-                                                          0xFFFF, // We will set the right value from DU answer
-                                                          -1, // no qfi
-                                                          dummy_address, // We will set the right value from DU answer
-                                                          remote_port,
-                                                          cu_f1u_data_req,
-                                                          NULL);
-      drbSetup->id = drb2Setup->id;
-
-      drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup;
-      for (int k=0; k < drbSetup->numQosFlowSetup; k++) {
-        drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id;
-      }
-    }
-  }
-}
-
 void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
 
   gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0};
@@ -200,7 +163,7 @@ void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, inst
             &my_addr);
 
   gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
-  gNB_CU_create_up_ul_tunnel(&resp, req, gtpInst, req->gNB_cu_cp_ue_id, remote_port, my_addr);
+  CU_create_UP_DL_tunnel(&resp, req, gtpInst, req->gNB_cu_cp_ue_id, remote_port, my_addr);
 
   resp.gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id;
   resp.numPDUSessions = req->numPDUSessions;
@@ -224,29 +187,9 @@ void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, inst
   e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance, &resp);
 }
 
-void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id) {
-  for (int i=0; i < req->numPDUSessionsMod; i++) {
-    for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
-      DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
-
-      transport_layer_addr_t newRemoteAddr;
-      newRemoteAddr.length = 32; // IPv4
-      memcpy(newRemoteAddr.buffer,
-             &drb_p->DlUpParamList[0].tlAddress,
-             sizeof(in_addr_t));
-
-      GtpuUpdateTunnelOutgoingPair(instance,
-                                   (ue_id & 0xFFFF),
-                                   (ebi_t)drb_p->id,
-                                   drb_p->DlUpParamList[0].teId,
-                                   newRemoteAddr);
-    }
-  }
-}
-
 void CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance) {
   instance_t gtpInst = getCxtE1(UPtype, instance)->gtpInstF1U;
-  update_UL_UP_tunnel_info(req, gtpInst, req->gNB_cu_cp_ue_id);
+  CU_update_UP_DL_tunnel(req, gtpInst, req->gNB_cu_cp_ue_id);
   // TODO: send bearer cxt mod response
 }
 
diff --git a/openair2/E1AP/e1ap_api.h b/openair2/E1AP/e1ap_api.h
index fa0de8fd0d8..482cd3dd60c 100644
--- a/openair2/E1AP/e1ap_api.h
+++ b/openair2/E1AP/e1ap_api.h
@@ -28,15 +28,6 @@
 #include "e1ap_common.h"
 #include "NR_DRB-ToAddModList.h"
 
-void gNB_CU_create_up_ul_tunnel(e1ap_bearer_setup_resp_t *resp,
-                                e1ap_bearer_setup_req_t *req,
-                                instance_t gtpInst,
-                                ue_id_t ue_id,
-                                int remote_port,
-                                in_addr_t my_addr);
-
-void update_UL_UP_tunnel_info(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id);
-
 void CUUP_process_e1_bearer_context_setup_req(e1ap_bearer_setup_req_t *req, instance_t instance);
 
 void CUUP_process_bearer_context_mod_req(e1ap_bearer_setup_req_t *req, instance_t instance);
diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c
new file mode 100644
index 00000000000..1aa48b10e0e
--- /dev/null
+++ b/openair2/RRC/NR/cucp_cuup_direct.c
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      conmnc_digit_lengtht@openairinterface.org
+ */
+
+#include <arpa/inet.h>
+
+#include "cucp_cuup_if.h"
+#include "platform_types.h"
+#include "nr_rrc_defs.h"
+
+#include "softmodem-common.h"
+#include "nr_rrc_proto.h"
+#include "nr_rrc_extern.h"
+#include "openair2/E1AP/e1ap_common.h"
+#include "UTIL/OSA/osa_defs.h"
+#include "nr_pdcp/nr_pdcp_entity.h"
+#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
+#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
+#include "openair3/ocp-gtpu/gtp_itf.h"
+#include "openair2/F1AP/f1ap_common.h"
+#include "rrc_gNB_GTPV1U.h"
+#include "common/ran_context.h"
+
+extern RAN_CONTEXT_t RC;
+
+void CU_create_UP_DL_tunnel(e1ap_bearer_setup_resp_t *resp,
+                            e1ap_bearer_setup_req_t *req,
+                            instance_t gtpInst,
+                            ue_id_t ue_id,
+                            int remote_port,
+                            in_addr_t my_addr) {
+
+  resp->numPDUSessions = req->numPDUSessions;
+  transport_layer_addr_t dummy_address = {0};
+  dummy_address.length = 32; // IPv4
+  for (int i=0; i < req->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 *drb2Setup = req->pduSession[i].DRBnGRanList + j;
+      DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j;
+
+      drbSetup->numUpParam = 1;
+      drbSetup->UpParamList[0].tlAddress = my_addr;
+      drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst,
+                                                          (ue_id & 0xFFFF),
+                                                          drb2Setup->id,
+                                                          drb2Setup->id,
+                                                          0xFFFF, // We will set the right value from DU answer
+                                                          -1, // no qfi
+                                                          dummy_address, // We will set the right value from DU answer
+                                                          remote_port,
+                                                          cu_f1u_data_req,
+                                                          NULL);
+      drbSetup->id = drb2Setup->id;
+
+      drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup;
+      for (int k=0; k < drbSetup->numQosFlowSetup; k++) {
+        drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id;
+      }
+    }
+  }
+}
+
+void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *req, instance_t instance, ue_id_t ue_id) {
+  for (int i=0; i < req->numPDUSessionsMod; i++) {
+    for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
+      DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
+
+      transport_layer_addr_t newRemoteAddr;
+      newRemoteAddr.length = 32; // IPv4
+      memcpy(newRemoteAddr.buffer,
+             &drb_p->DlUpParamList[0].tlAddress,
+             sizeof(in_addr_t));
+
+      GtpuUpdateTunnelOutgoingPair(instance,
+                                   (ue_id & 0xFFFF),
+                                   (ebi_t)drb_p->id,
+                                   drb_p->DlUpParamList[0].teId,
+                                   newRemoteAddr);
+    }
+  }
+}
+
+static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
+                                  rrc_gNB_ue_context_t  *ue_context_p,
+                                  e1ap_bearer_setup_req_t *req,
+                                  NR_DRB_ToAddModList_t *DRB_configList,
+                                  NR_SRB_ToAddModList_t *SRB_configList,
+                                  instance_t instance) {
+
+  gtpv1u_gnb_create_tunnel_req_t  create_tunnel_req={0};
+  gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
+
+  for (int i=0; i < ue_context_p->ue_context.nb_of_pdusessions; i++) {
+    pdu_session_param_t *pdu = ue_context_p->ue_context.pduSession + i;
+    create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id;
+    create_tunnel_req.incoming_rb_id[i] = i + 1;
+    create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id;
+    memcpy(&create_tunnel_req.dst_addr[i].buffer,
+           &pdu->param.upf_addr.buffer,
+           sizeof(uint8_t)*20);
+    create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length;
+    create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid;
+  }
+  create_tunnel_req.num_tunnels = ue_context_p->ue_context.nb_of_pdusessions;
+  create_tunnel_req.ue_id       = ue_context_p->ue_context.rnti;
+
+  int 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 rnti %ld\n",
+          create_tunnel_req.ue_id);
+    return ret;
+  }
+
+  nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p,
+                                               &create_tunnel_resp);
+
+  uint8_t *kRRCenc = NULL;
+  uint8_t *kRRCint = NULL;
+  uint8_t *kUPenc = NULL;
+  uint8_t *kUPint = NULL;
+  /* Derive the keys from kgnb */
+  if (DRB_configList != NULL) {
+    nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm,
+                         ue_context_p->ue_context.kgnb,
+                         &kUPenc);
+    nr_derive_key_up_int(ue_context_p->ue_context.integrity_algorithm,
+                         ue_context_p->ue_context.kgnb,
+                         &kUPint);
+  }
+
+  nr_derive_key_rrc_enc(ue_context_p->ue_context.ciphering_algorithm,
+                        ue_context_p->ue_context.kgnb,
+                        &kRRCenc);
+  nr_derive_key_rrc_int(ue_context_p->ue_context.integrity_algorithm,
+                        ue_context_p->ue_context.kgnb,
+                        &kRRCint);
+  /* Refresh SRBs/DRBs */
+
+  LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_p->ue_context.rnti);
+
+  nr_pdcp_add_srbs(ctxt_p->enb_flag, ctxt_p->rnti,
+                   SRB_configList,
+                   (ue_context_p->ue_context.integrity_algorithm << 4)
+                   | ue_context_p->ue_context.ciphering_algorithm,
+                   kRRCenc,
+                   kRRCint);
+                   
+  nr_pdcp_add_drbs(ctxt_p->enb_flag, ctxt_p->rnti,
+                   DRB_configList,
+                   (ue_context_p->ue_context.integrity_algorithm << 4)
+                   | ue_context_p->ue_context.ciphering_algorithm,
+                   kUPenc,
+                   kUPint,
+                   get_softmodem_params()->sa ? ue_context_p->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL);
+  
+  return ret;
+}
+
+static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, instance_t instance) {
+  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(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);
+
+  gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
+  // GTP tunnel for UL
+  int ret = drb_config_gtpu_create(&ctxt,
+                                   ue_context_p,
+                                   req,
+                                   ue_context_p->ue_context.DRB_configList,
+                                   ue_context_p->ue_context.SRB_configList,
+                                   rrc->gtpInstN3);
+  if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
+
+  if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
+    rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL);
+  } 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
+    CU_create_UP_DL_tunnel(&resp, req, gtpInst, ue_context_p->ue_context.rnti, remote_port, my_addr);
+
+    prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
+  }
+}
+
+static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *req, instance_t instance) {
+  instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
+  CU_update_UP_DL_tunnel(req, gtpInst, req->rnti);
+}
+
+void cucp_cuup_message_transfer_direct_init(gNB_RRC_INST *rrc) {
+  rrc->cucp_cuup.cucp_cuup_bearer_context_setup = cucp_cuup_bearer_context_setup_direct;
+  rrc->cucp_cuup.cucp_cuup_bearer_context_mod = cucp_cuup_bearer_context_mod_direct;
+}
diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c
new file mode 100644
index 00000000000..2b90af4880f
--- /dev/null
+++ b/openair2/RRC/NR/cucp_cuup_e1ap.c
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      conmnc_digit_lengtht@openairinterface.org
+ */
+
+#include "cucp_cuup_if.h"
+#include <arpa/inet.h>
+
+#include "platform_types.h"
+#include "nr_rrc_defs.h"
+
+#include "nr_rrc_proto.h"
+#include "nr_rrc_extern.h"
+#include "cucp_cuup_if.h"
+#include "openair2/E1AP/e1ap_common.h"
+#include "UTIL/OSA/osa_defs.h"
+#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
+#include "common/ran_context.h"
+
+extern RAN_CONTEXT_t RC;
+
+static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance) {
+  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(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);
+  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));
+
+  itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p);
+}
+
+static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance) {
+  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));
+  itti_send_msg_to_task(TASK_CUCP_E1, instance, msg);
+}
+
+void cucp_cuup_message_transfer_e1ap_init(gNB_RRC_INST *rrc) {
+  rrc->cucp_cuup.cucp_cuup_bearer_context_setup = cucp_cuup_bearer_context_setup_e1ap;
+  rrc->cucp_cuup.cucp_cuup_bearer_context_mod = cucp_cuup_bearer_context_mod_e1ap;
+}
diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h
new file mode 100644
index 00000000000..6b641b55f8a
--- /dev/null
+++ b/openair2/RRC/NR/cucp_cuup_if.h
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      conmnc_digit_lengtht@openairinterface.org
+ */
+
+#ifndef CUCP_CUUP_IF_H
+#define CUCP_CUUP_IF_H
+
+#include <netinet/in.h>
+#include "platform_types.h"
+
+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 *req, instance_t instance);
+
+struct gNB_RRC_INST_s;
+void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc);
+void cucp_cuup_message_transfer_e1ap_init(struct gNB_RRC_INST_s *rrc);
+void CU_create_UP_DL_tunnel(struct e1ap_bearer_setup_resp_s *resp,
+                            struct e1ap_bearer_setup_req_s *req,
+                            instance_t gtpInst,
+                            ue_id_t ue_id,
+                            int remote_port,
+                            in_addr_t my_addr);
+void CU_update_UP_DL_tunnel(struct e1ap_bearer_setup_req_s *req, instance_t instance, ue_id_t ue_id);
+#endif
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 0c3fc2b15c6..502a4c43b59 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -43,6 +43,7 @@
 #include "COMMON/platform_constants.h"
 #include "COMMON/platform_types.h"
 #include "mac_rrc_dl.h"
+#include "cucp_cuup_if.h"
 
 //#include "COMMON/mac_rrc_primitives.h"
 
@@ -467,16 +468,16 @@ typedef struct {
   int do_drb_integrity;
 } nr_security_configuration_t;
 
-typedef void (*nr_e1_bearer_cxt_msg_transfer_func_t)(e1ap_bearer_setup_req_t *req, instance_t instance);
-typedef void (*nr_e1_ue_cxt_mod_msg_transfer_func_t)(MessageDef *msg, instance_t instance);
-
 typedef struct nr_mac_rrc_dl_if_s {
   /* TODO add other message types as necessary */
   dl_rrc_message_transfer_func_t dl_rrc_message_transfer;
-  nr_e1_bearer_cxt_msg_transfer_func_t nr_e1_bearer_cxt_msg_transfer;
-  nr_e1_ue_cxt_mod_msg_transfer_func_t nr_e1_ue_cxt_mod_msg_transfer;
 } nr_mac_rrc_dl_if_t;
 
+typedef struct cucp_cuup_if_s {
+  cucp_cuup_bearer_context_setup_func_t cucp_cuup_bearer_context_setup;
+  cucp_cuup_bearer_context_setup_func_t cucp_cuup_bearer_context_mod;
+} cucp_cuup_if_t;
+
 //---NR---(completely change)---------------------
 typedef struct gNB_RRC_INST_s {
 
@@ -531,6 +532,7 @@ typedef struct gNB_RRC_INST_s {
   nr_security_configuration_t security;
 
   nr_mac_rrc_dl_if_t mac_rrc;
+  cucp_cuup_if_t cucp_cuup;
 
 } gNB_RRC_INST;
 
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 25223f118a2..a1ead3750a0 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -231,3 +231,8 @@ 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 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 e4d3c4bf3e7..382692b6f62 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -88,8 +88,6 @@
 
 #include "nr_pdcp/nr_pdcp_entity.h"
 #include "pdcp.h"
-#include "openair3/ocp-gtpu/gtp_itf.h"
-
 
 #include "intertask_interface.h"
 #include "SIMULATION/TOOLS/sim.h" // for taus
@@ -105,6 +103,7 @@
 #include "openair2/E1AP/e1ap_common.h"
 #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
 #include "openair2/E1AP/e1ap_api.h"
+#include "cucp_cuup_if.h"
 
 #include "BIT_STRING.h"
 #include "assertions.h"
@@ -201,23 +200,20 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
   }
 }
 
-static void rrc_gNB_mac_rrc_init(gNB_RRC_INST *rrc)
+static void rrc_gNB_CU_DU_init(gNB_RRC_INST *rrc)
 {
   switch (rrc->node_type) {
     case ngran_gNB_CUCP:
       mac_rrc_dl_f1ap_init(&rrc->mac_rrc);
-      rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_e1ap;
-      rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_send_e1ap;
+      cucp_cuup_message_transfer_e1ap_init(rrc);
       break;
     case ngran_gNB_CU:
       mac_rrc_dl_f1ap_init(&rrc->mac_rrc);
-      rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_direct;
-      rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_direct;
+      cucp_cuup_message_transfer_direct_init(rrc);
       break;
     case ngran_gNB:
       mac_rrc_dl_direct_init(&rrc->mac_rrc);
-      rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer = bearer_context_setup_direct;
-      rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer = ue_cxt_mod_direct;
+      cucp_cuup_message_transfer_direct_init(rrc);
        break;
     case ngran_gNB_DU:
       /* silently drop this, as we currently still need the RRC at the DU. As
@@ -243,7 +239,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
   rrc->module_id = gnb_mod_idP;
   rrc->Nb_ue = 0;
   rrc->carrier.Srb0.Active = 0;
-  rrc_gNB_mac_rrc_init(rrc);
+  rrc_gNB_CU_DU_init(rrc);
   uid_linear_allocator_init(&rrc->uid_allocator);
   RB_INIT(&rrc->rrc_ue_head);
   rrc->initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
@@ -1322,85 +1318,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
   }
 }
 
-int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
-                           rrc_gNB_ue_context_t  *ue_context_p,
-                           e1ap_bearer_setup_req_t *req,
-                           NR_DRB_ToAddModList_t *DRB_configList,
-                           NR_SRB_ToAddModList_t *SRB_configList,
-                           instance_t instance) {
-
-  gtpv1u_gnb_create_tunnel_req_t  create_tunnel_req={0};
-  gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
-
-  for (int i=0; i < ue_context_p->ue_context.nb_of_pdusessions; i++) {
-    pdu_session_param_t *pdu = ue_context_p->ue_context.pduSession + i;
-    create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id;
-    create_tunnel_req.incoming_rb_id[i] = i + 1;
-    create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id;
-    memcpy(&create_tunnel_req.dst_addr[i].buffer,
-           &pdu->param.upf_addr.buffer,
-           sizeof(uint8_t)*20);
-    create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length;
-    create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid;
-  }
-  create_tunnel_req.num_tunnels = ue_context_p->ue_context.nb_of_pdusessions;
-  create_tunnel_req.ue_id       = ue_context_p->ue_context.rnti;
-
-  int 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 rnti %ld\n",
-          create_tunnel_req.ue_id);
-    return ret;
-  }
-
-  nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p,
-                                               &create_tunnel_resp);
-
-  uint8_t *kRRCenc = NULL;
-  uint8_t *kRRCint = NULL;
-  uint8_t *kUPenc = NULL;
-  uint8_t *kUPint = NULL;
-  /* Derive the keys from kgnb */
-  if (DRB_configList != NULL) {
-    nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm,
-                         ue_context_p->ue_context.kgnb,
-                         &kUPenc);
-    nr_derive_key_up_int(ue_context_p->ue_context.integrity_algorithm,
-                         ue_context_p->ue_context.kgnb,
-                         &kUPint);
-  }
-
-  nr_derive_key_rrc_enc(ue_context_p->ue_context.ciphering_algorithm,
-                        ue_context_p->ue_context.kgnb,
-                        &kRRCenc);
-  nr_derive_key_rrc_int(ue_context_p->ue_context.integrity_algorithm,
-                        ue_context_p->ue_context.kgnb,
-                        &kRRCint);
-  /* Refresh SRBs/DRBs */
-
-  LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_p->ue_context.rnti);
-
-  nr_pdcp_add_srbs(ctxt_p->enb_flag, ctxt_p->rnti,
-                   SRB_configList,
-                   (ue_context_p->ue_context.integrity_algorithm << 4)
-                   | ue_context_p->ue_context.ciphering_algorithm,
-                   kRRCenc,
-                   kRRCint);
-                   
-  nr_pdcp_add_drbs(ctxt_p->enb_flag, ctxt_p->rnti,
-                   DRB_configList,
-                   (ue_context_p->ue_context.integrity_algorithm << 4)
-                   | ue_context_p->ue_context.ciphering_algorithm,
-                   kUPenc,
-                   kUPint,
-                   get_softmodem_params()->sa ? ue_context_p->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL);
-  
-  return ret;
-}
-
 //-----------------------------------------------------------------------------
 /*
 * Process the RRC Reconfiguration Complete from the UE
@@ -3607,21 +3524,6 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch
 
 }
 
-void ue_cxt_mod_send_e1ap(MessageDef *msg, instance_t instance) {
-  int module_id = 0;
-  itti_send_msg_to_task(TASK_CUCP_E1, module_id, msg);
-}
-
-void ue_cxt_mod_direct(MessageDef *msg, instance_t instance) {
-  e1ap_bearer_setup_req_t *req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg);
-  instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
-
-  update_UL_UP_tunnel_info(req, gtpInst, req->rnti);
-
-  int result = itti_free (ITTI_MSG_ORIGIN_ID(msg), msg);
-  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
-}
-
 static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){
 
   f1ap_ue_context_setup_t *resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
@@ -3636,16 +3538,15 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, c
   gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
   struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti);
 
-  MessageDef *msg_e1 = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
-  e1ap_bearer_setup_req_t *req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_e1);
-  req->numPDUSessionsMod = ue_context_p->ue_context.nb_of_pdusessions;
-  req->gNB_cu_cp_ue_id = ue_context_p->ue_context.gNB_ue_ngap_id;
-  req->rnti = ue_context_p->ue_context.rnti;
-  for (int i=0; i < req->numPDUSessionsMod; i++) {
-    req->pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
+  e1ap_bearer_setup_req_t req = {0};
+  req.numPDUSessionsMod = ue_context_p->ue_context.nb_of_pdusessions;
+  req.gNB_cu_cp_ue_id = ue_context_p->ue_context.gNB_ue_ngap_id;
+  req.rnti = ue_context_p->ue_context.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_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;
@@ -3655,7 +3556,7 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, c
   }
 
   // send the F1 response message up to update F1-U tunnel info
-  rrc->mac_rrc.nr_e1_ue_cxt_mod_msg_transfer(msg_e1, instance);
+  rrc->cucp_cuup.cucp_cuup_bearer_context_mod(&req, instance);
 
   NR_CellGroupConfig_t *cellGroupConfig = NULL;
 
@@ -4030,55 +3931,6 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
   itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p);
 }
 
-void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, instance_t instance) {
-
-  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(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);
-
-  gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
-  // GTP tunnel for UL
-  int ret = drb_config_gtpu_create(&ctxt,
-                                   ue_context_p,
-                                   req,
-                                   ue_context_p->ue_context.DRB_configList,
-                                   ue_context_p->ue_context.SRB_configList,
-                                   rrc->gtpInstN3);
-  if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
-
-  if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
-    rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL);
-  } 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;
-    gNB_CU_create_up_ul_tunnel(&resp, req, gtpInst, ue_context_p->ue_context.rnti, remote_port, my_addr);
-
-    prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
-  }
-  // call the code that sends UE context modification message to DU
-}
-
-void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, instance_t instance) {
-
-  // create ITTI msg and send to CUCP E1 task to send via SCTP
-  // then in CUUP the function rrc_gNB_process_e1_bearer_context_setup_req
-  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(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);
-  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));
-
-  itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p);
-
-}
-
 void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) {
   // Find the UE context from UE ID and send ITTI message to F1AP to send UE context modification message to DU
 
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 1f3b5a2f10c..f44abd6ae5d 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -1072,7 +1072,7 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(
     }
   }
 
-  rrc->mac_rrc.nr_e1_bearer_cxt_msg_transfer(&bearer_req, instance);
+  rrc->cucp_cuup.cucp_cuup_bearer_context_setup(&bearer_req, instance);
   return;
 }
 
-- 
GitLab