From b08ce59bc284dde8f510b5053bcc89ff6c6b4032 Mon Sep 17 00:00:00 2001
From: Robert Schmidt <robert.schmidt@openairinterface.org>
Date: Wed, 27 Sep 2023 13:51:18 +0200
Subject: [PATCH] Pass assoc_id to RRC and use when sending E1AP messages

---
 executables/nr-softmodem.c         |  1 +
 openair2/E1AP/e1ap.c               | 42 ++++++++++++++++--------------
 openair2/E1AP/e1ap.h               | 18 ++++++-------
 openair2/E1AP/e1ap_api.c           |  4 +--
 openair2/E1AP/e1ap_common.c        |  2 +-
 openair2/E1AP/e1ap_common.h        |  2 +-
 openair2/F1AP/f1ap_ids.h           |  5 +++-
 openair2/RRC/NR/cucp_cuup_direct.c | 12 +++++----
 openair2/RRC/NR/cucp_cuup_e1ap.c   | 16 +++++++-----
 openair2/RRC/NR/cucp_cuup_if.h     |  5 +++-
 openair2/RRC/NR/nr_rrc_defs.h      |  1 +
 openair2/RRC/NR/nr_rrc_proto.h     |  4 ++-
 openair2/RRC/NR/rrc_gNB.c          |  8 +++---
 openair2/RRC/NR/rrc_gNB_NGAP.c     |  3 ++-
 openair2/RRC/NR/rrc_gNB_cuup.c     | 41 +++++++++++++++++++++++++++--
 15 files changed, 111 insertions(+), 53 deletions(-)

diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 392ff166da..cbb36dc580 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -410,6 +410,7 @@ static int create_gNB_tasks(ngran_node_t node_type)
       /* send E1 Setup Request to RRC */
       MessageDef *new_msg = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ);
       E1AP_SETUP_REQ(new_msg) = E1AP_REGISTER_REQ(msg).setup_req;
+      new_msg->ittiMsgHeader.originInstance = -1; /* meaning, it is local */
       itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, new_msg);
       itti_free(TASK_UNKNOWN, msg);
     }
diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c
index b51576ad05..f7ca3c379b 100644
--- a/openair2/E1AP/e1ap.c
+++ b/openair2/E1AP/e1ap.c
@@ -35,7 +35,7 @@
 #include "gtp_itf.h"
 
 #define E1AP_NUM_MSG_HANDLERS 14
-typedef int (*e1ap_message_processing_t)(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p);
+typedef int (*e1ap_message_processing_t)(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p);
 const e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3] = {
 
     {0, 0, 0}, /* Reset */
@@ -92,7 +92,7 @@ int e1ap_handle_message(instance_t instance, sctp_assoc_t assoc_id, const uint8_
   } else {
     /* Calling the right handler */
     LOG_D(E1AP, "Calling handler with instance %ld\n",instance);
-    ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(getCxtE1(instance), &pdu);
+    ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(assoc_id, getCxtE1(instance), &pdu);
   }
 
   ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu);
@@ -355,17 +355,18 @@ void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
   }
 }
 
-int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu != NULL);
   /* Create ITTI message and send to queue */
   MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0 /*unused by callee*/, E1AP_SETUP_REQ);
   extract_SETUP_REQUEST(pdu, &E1AP_SETUP_REQ(msg_p));
+  msg_p->ittiMsgHeader.originInstance = assoc_id;
 
   if (E1AP_SETUP_REQ(msg_p).supported_plmns > 0) {
     itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, msg_p);
   } else {
-    e1apCUCP_send_SETUP_FAILURE(inst->assoc_id, E1AP_SETUP_REQ(msg_p).transac_id);
+    e1apCUCP_send_SETUP_FAILURE(assoc_id, E1AP_SETUP_REQ(msg_p).transac_id);
     itti_free(TASK_CUCP_E1, msg_p);
     return -1;
   }
@@ -373,7 +374,7 @@ int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t
   return 0;
 }
 
-int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
 {
   LOG_D(E1AP, "%s\n", __func__);
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
@@ -401,7 +402,7 @@ int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t
   return 0;
 }
 
-int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
 {
   E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie;
   DevAssert(pdu != NULL);
@@ -985,7 +986,7 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
 
 }
 
-int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu != NULL);
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -1085,7 +1086,7 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu,
   }
 }
 
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
   DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup);
@@ -1095,6 +1096,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const
   MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP);
   e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg);
   extract_BEARER_CONTEXT_SETUP_RESPONSE(pdu, bearerCxt);
+  msg->ittiMsgHeader.originInstance = assoc_id;
   // Fixme: instance is the NGAP instance, no good way to set it here
   instance_t instance = 0;
   itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
@@ -1102,7 +1104,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const
   return 0;
 }
 
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu)
 {
   AssertFatal(false,"Not implemented yet\n");
   return -1;
@@ -1269,7 +1271,7 @@ void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu,
   }
 }
 
-int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu != NULL);
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -1442,7 +1444,7 @@ void extract_BEARER_CONTEXT_RELEASE_COMMAND(const E1AP_E1AP_PDU_t *pdu,
   }
 }
 
-int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu != NULL);
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage);
@@ -1486,7 +1488,7 @@ void extract_BEARER_CONTEXT_RELEASE_COMPLETE(const E1AP_E1AP_PDU_t *pdu,
   }
 }
 
-int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
+int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu)
 {
   DevAssert(pdu != NULL);
   DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome);
@@ -1598,7 +1600,7 @@ static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance,
 
   if (type == UPtype) {
     e1ap_upcp_inst_t *inst = getCxtE1(instance);
-    inst->assoc_id = sctp_new_association_resp->assoc_id;
+    inst->cuup.assoc_id = sctp_new_association_resp->assoc_id;
 
     e1ap_net_config_t *nc = &inst->net_config;
     eth_params_t IPaddr;
@@ -1611,7 +1613,7 @@ static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance,
     extern instance_t CUuniqInstance;
     CUuniqInstance = getCxtE1(instance)->gtpInstF1U;
     cuup_init_n3(instance);
-    e1apCUUP_send_SETUP_REQUEST(inst->assoc_id, &inst->cuup.setupReq);
+    e1apCUUP_send_SETUP_REQUEST(inst->cuup.assoc_id, &inst->cuup.setupReq);
   }
 }
 
@@ -1662,7 +1664,8 @@ void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_ne
     createE1inst(type, instance, NULL, NULL);
   e1ap_upcp_inst_t *inst = getCxtE1(instance);
   inst->sockState = SCTP_STATE_ESTABLISHED;
-  inst->assoc_id = sctp_new_ind->assoc_id;
+  if (type == UPtype)
+    inst->cuup.assoc_id = sctp_new_ind->assoc_id;
 }
 
 void e1apHandleTimer(instance_t myInstance)
@@ -1683,8 +1686,7 @@ void *E1AP_CUCP_task(void *arg) {
     instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg);
     const int msgType = ITTI_MSG_ID(msg);
     LOG_D(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
-    /* TODO get the assoc ID through the ITTI message to address multiple CU-UPs */
-    e1ap_upcp_inst_t *inst = getCxtE1(myInstance);
+    sctp_assoc_t assoc_id = msg->ittiMsgHeader.originInstance;
 
     switch (ITTI_MSG_ID(msg)) {
       case SCTP_NEW_ASSOCIATION_IND:
@@ -1713,15 +1715,15 @@ void *E1AP_CUCP_task(void *arg) {
         break;
 
       case E1AP_SETUP_RESP:
-        e1ap_send_SETUP_RESPONSE(inst->assoc_id, &E1AP_SETUP_RESP(msg));
+        e1ap_send_SETUP_RESPONSE(assoc_id, &E1AP_SETUP_RESP(msg));
         break;
 
       case E1AP_BEARER_CONTEXT_SETUP_REQ:
-        e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(inst->assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
+        e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
         break;
 
       case E1AP_BEARER_CONTEXT_MODIFICATION_REQ:
-        e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(inst->assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
+        e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(assoc_id, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg));
         break;
 
       default:
diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h
index f5ba9350d7..8a7c6ba2df 100644
--- a/openair2/E1AP/e1ap.h
+++ b/openair2/E1AP/e1ap.h
@@ -28,25 +28,25 @@
 #include "e1ap_asnc.h"
 #include "openair2/E1AP/e1ap_common.h"
 
-int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
 void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, e1ap_bearer_setup_resp_t *const resp);
 
-int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
-int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
+int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu);
 
 int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, e1ap_bearer_release_cmd_t *const cmd);
 
diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c
index 9096a9faf7..cf3fe14de1 100644
--- a/openair2/E1AP/e1ap_api.c
+++ b/openair2/E1AP/e1ap_api.c
@@ -172,7 +172,7 @@ void process_e1_bearer_context_setup_req(instance_t instance, e1ap_bearer_setup_
     pduSetup->numDRBFailed = 0;
   }
 
-  e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->assoc_id, resp);
+  e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst->cuup.assoc_id, resp);
 }
 
 void CUUP_process_bearer_context_mod_req(instance_t instance, e1ap_bearer_setup_req_t *const req)
@@ -190,5 +190,5 @@ void CUUP_process_bearer_release_command(instance_t instance, e1ap_bearer_releas
   AssertFatal(inst, "");
   newGtpuDeleteAllTunnels(inst->gtpInstN3, cmd->gNB_cu_up_ue_id);
   newGtpuDeleteAllTunnels(inst->gtpInstF1U, cmd->gNB_cu_up_ue_id);
-  e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst->assoc_id, cmd);
+  e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst->cuup.assoc_id, cmd);
 }
diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c
index 366d2b82e6..28764b5dec 100644
--- a/openair2/E1AP/e1ap_common.c
+++ b/openair2/E1AP/e1ap_common.c
@@ -43,7 +43,7 @@ void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_se
   e1ap_inst[instance] = calloc(1, sizeof(e1ap_upcp_inst_t));
   e1ap_inst[instance]->type = type;
   e1ap_inst[instance]->instance = instance;
-  e1ap_inst[instance]->assoc_id = -1;
+  e1ap_inst[instance]->cuup.assoc_id = -1;
   if (nc)
     memcpy(&e1ap_inst[instance]->net_config, nc, sizeof(*nc));
   if (req) {
diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h
index bcd3d3b936..dc615d75b3 100644
--- a/openair2/E1AP/e1ap_common.h
+++ b/openair2/E1AP/e1ap_common.h
@@ -32,8 +32,8 @@ typedef struct e1ap_upcp_inst_s {
   instance_t instance;
   E1_t type;
   enum sctp_state_e sockState;
-  sctp_assoc_t assoc_id;
   struct {
+    sctp_assoc_t assoc_id;
     e1ap_setup_req_t setupReq;
   } cuup;
   instance_t gtpInstN3;
diff --git a/openair2/F1AP/f1ap_ids.h b/openair2/F1AP/f1ap_ids.h
index 96b146f6ba..60d35de737 100644
--- a/openair2/F1AP/f1ap_ids.h
+++ b/openair2/F1AP/f1ap_ids.h
@@ -27,10 +27,13 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/sctp.h>
 
 typedef struct f1_ue_data_t {
   uint32_t secondary_ue;
-  /* can be extended with F1-specific data also relevant for monolithic */
+  sctp_assoc_t e1_assoc_id;
 } f1_ue_data_t;
 
 void cu_init_f1_ue_data(void);
diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c
index 8b81a3c5dd..a62f576c72 100644
--- a/openair2/RRC/NR/cucp_cuup_direct.c
+++ b/openair2/RRC/NR/cucp_cuup_direct.c
@@ -159,9 +159,10 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
   return ret;
 }
 
-static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_setup_direct(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req)
 {
-  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], req->gNB_cu_cp_ue_id);
+  AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
+  rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], req->gNB_cu_cp_ue_id);
   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->rrc_ue_id, 0, 0, 0);
@@ -194,7 +195,7 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
   } else {
     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(instance)->gtpInst;
+    instance_t gtpInst = getCxt(0)->gtpInst;
     // GTP tunnel for DL
     fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rrc_ue_id, remote_port, my_addr);
   }
@@ -204,12 +205,13 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
   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)
+static void cucp_cuup_bearer_context_mod_direct(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req)
 {
+  AssertFatal(assoc_id == -1, "illegal assoc_id %d, impossible for integrated CU\n", assoc_id);
   // only update GTP tunnels if it is really a CU
   if (!NODE_IS_CU(RC.nrrrc[0]->node_type))
     return;
-  instance_t gtpInst = getCxt(instance)->gtpInst;
+  instance_t gtpInst = getCxt(0)->gtpInst;
   CU_update_UP_DL_tunnel(req, gtpInst, req->gNB_cu_cp_ue_id);
 }
 
diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c
index 199c949959..7604cabf14 100644
--- a/openair2/RRC/NR/cucp_cuup_e1ap.c
+++ b/openair2/RRC/NR/cucp_cuup_e1ap.c
@@ -36,21 +36,25 @@
 
 extern RAN_CONTEXT_t RC;
 
-static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_setup_e1ap(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req)
 {
-  MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ);
+  AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id);
+  MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_REQ);
+  msg_p->ittiMsgHeader.originInstance = assoc_id;
   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);
+  itti_send_msg_to_task (TASK_CUCP_E1, 0, msg_p);
 }
 
-static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance)
+static void cucp_cuup_bearer_context_mod_e1ap(sctp_assoc_t assoc_id, e1ap_bearer_setup_req_t *const req)
 {
-  MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
+  AssertFatal(assoc_id > 0, "illegal assoc_id %d\n", assoc_id);
+  MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_MODIFICATION_REQ);
+  msg->ittiMsgHeader.originInstance = assoc_id;
   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);
+  itti_send_msg_to_task(TASK_CUCP_E1, 0, msg);
 }
 
 void cucp_cuup_message_transfer_e1ap_init(gNB_RRC_INST *rrc) {
diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h
index 8f072eb753..3a3fb7948a 100644
--- a/openair2/RRC/NR/cucp_cuup_if.h
+++ b/openair2/RRC/NR/cucp_cuup_if.h
@@ -23,11 +23,14 @@
 #define CUCP_CUUP_IF_H
 
 #include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/sctp.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 *const req, instance_t instance);
+typedef void (*cucp_cuup_bearer_context_setup_func_t)(sctp_assoc_t assoc_id, struct e1ap_bearer_setup_req_s *const req);
 
 struct gNB_RRC_INST_s;
 void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc);
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 845e4337aa..a1952de7a7 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -373,6 +373,7 @@ typedef struct nr_rrc_du_container_t {
 
 typedef struct nr_rrc_cuup_container_t {
   e1ap_setup_req_t *setup_req;
+  sctp_assoc_t assoc_id;
 } nr_rrc_cuup_container_t;
 
 //---NR---(completely change)---------------------
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 13f8efce50..c85aada0b9 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -132,7 +132,9 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
 
 void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
 
-int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req);
+sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
+sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
+int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req);
 
 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 8360152375..d92360f40b 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -2074,7 +2074,8 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i
 
     // send the F1 response message up to update F1-U tunnel info
     // it seems the rrc transaction id (xid) is not needed here
-    rrc->cucp_cuup.bearer_context_mod(&req, instance);
+    sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE);
+    rrc->cucp_cuup.bearer_context_mod(assoc_id, &req);
   }
 
   if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) {
@@ -2676,7 +2677,7 @@ void *rrc_gnb_task(void *args_p) {
         break;
 
       case E1AP_SETUP_REQ:
-        rrc_gNB_process_e1_setup_req(&E1AP_SETUP_REQ(msg_p));
+        rrc_gNB_process_e1_setup_req(msg_p->ittiMsgHeader.originInstance, &E1AP_SETUP_REQ(msg_p));
         break;
 
       case E1AP_BEARER_CONTEXT_SETUP_RESP:
@@ -2914,7 +2915,8 @@ void rrc_gNB_trigger_new_bearer(int rnti)
   ue->xids[xid] = RRC_PDUSESSION_MODIFY;
   ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session
   LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid);
-  rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0);
+  sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue);
+  rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
 }
 
 void rrc_gNB_trigger_release_bearer(int rnti)
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 214382767f..553cf9ecf1 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -827,7 +827,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
   }
   int xid = rrc_gNB_get_next_transaction_identifier(instance);
   UE->xids[xid] = RRC_PDUSESSION_ESTABLISH;
-  rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance);
+  sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE);
+  rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
   return;
 }
 
diff --git a/openair2/RRC/NR/rrc_gNB_cuup.c b/openair2/RRC/NR/rrc_gNB_cuup.c
index 56ee7d59ca..a612ebe8b0 100644
--- a/openair2/RRC/NR/rrc_gNB_cuup.c
+++ b/openair2/RRC/NR/rrc_gNB_cuup.c
@@ -21,8 +21,43 @@
 
 #include "common/ran_context.h"
 #include "nr_rrc_defs.h"
+#include "openair2/F1AP/f1ap_ids.h"
 
-int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req)
+sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue)
+{
+  f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
+  if (ue_data.e1_assoc_id == 0) {
+    LOG_W(RRC, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id);
+    return get_new_cuup_for_ue(rrc, ue);
+  }
+  LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
+  return ue_data.e1_assoc_id;
+}
+
+sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue)
+{
+  /* check if there is already a UE associated */
+  f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
+  if (ue_data.e1_assoc_id != 0) {
+    LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
+    return ue_data.e1_assoc_id;
+  }
+
+  /* it is zero -> no CUUP for this UE yet, get the (only) CU-UP that is
+   * connected */
+  if (!rrc->cuup)
+    return 0; /* no CUUP connected */
+
+  /* update the association for the UE so it will be picked up later */
+  ue_data.e1_assoc_id = rrc->cuup->assoc_id;
+  cu_remove_f1_ue_data(ue->rrc_ue_id);
+  cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
+  LOG_I(RRC, "UE %d associating to CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
+
+  return ue_data.e1_assoc_id;
+}
+
+int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req)
 {
   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];
@@ -42,13 +77,15 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req)
     }
   }
 
-  LOG_I(RRC, "Accepting new CU-UP ID %ld name %s\n", req->gNB_cu_up_id, req->gNB_cu_up_name);
+  LOG_I(RRC, "Accepting new CU-UP ID %ld name %s (assoc_id %d)\n", req->gNB_cu_up_id, req->gNB_cu_up_name, assoc_id);
   rrc->cuup = malloc(sizeof(*rrc->cuup));
   AssertFatal(rrc->cuup, "out of memory\n");
   rrc->cuup->setup_req = malloc(sizeof(*rrc->cuup->setup_req));
   *rrc->cuup->setup_req = *req;
+  rrc->cuup->assoc_id = assoc_id;
 
   MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, E1AP_SETUP_RESP);
+  msg_p->ittiMsgHeader.originInstance = assoc_id;
   e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(msg_p);
   resp->transac_id = req->transac_id;
   itti_send_msg_to_task(TASK_CUCP_E1, 0, msg_p);
-- 
2.26.2