From 01a87a1fba75e4f0ad40ce9fd3ab1cc6d9871294 Mon Sep 17 00:00:00 2001
From: Xue Song <xuesong@cn.fujitsu.com>
Date: Fri, 15 Jan 2021 19:57:26 +0900
Subject: [PATCH] split gNB into CU and DU

---
 common/utils/ocp_itti/intertask_interface.cpp |   2 +-
 executables/nr-softmodem.c                    | 157 ++++++++++++------
 openair2/GNB_APP/gnb_app.c                    |  24 ---
 openair2/GNB_APP/gnb_config.c                 |  98 ++++++++++-
 openair2/GNB_APP/gnb_config.h                 |   1 +
 openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c    |   2 +-
 openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c     |  28 +++-
 openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c       |  16 ++
 openair2/RRC/NR/rrc_gNB.c                     |   9 +-
 9 files changed, 250 insertions(+), 87 deletions(-)

diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp
index e81851c2734..2bb2600572e 100644
--- a/common/utils/ocp_itti/intertask_interface.cpp
+++ b/common/utils/ocp_itti/intertask_interface.cpp
@@ -133,7 +133,7 @@ task_list_t tasks[TASK_MAX];
       LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s );
 
     if ( s > 50 )
-      LOG_I(TMR,"Queue for %s task size: %ld\n",itti_get_task_name(destination_task_id), s+1);
+      LOG_I(TMR,"Queue for %s task size: %ld from %s task\n",itti_get_task_name(destination_task_id), s+1, itti_get_task_name(message->ittiMsgHeader.originTaskId));
 
     t->message_queue.insert(t->message_queue.begin(), message);
     eventfd_t sem_counter = 1;
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index fb757a9f47c..fd40900d948 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -85,6 +85,9 @@ unsigned short config_frames[4] = {2,9,11,13};
 #include "x2ap_eNB.h"
 #include "ngap_gNB.h"
 #include "gnb_paramdef.h"
+#include "f1ap_cu_task.h"
+#include "f1ap_du_task.h"
+
 
 pthread_cond_t nfapi_sync_cond;
 pthread_mutex_t nfapi_sync_mutex;
@@ -457,11 +460,29 @@ int create_gNB_tasks(uint32_t gnb_nb) {
       LOG_E(GNB_APP, "Create task for gNB APP failed\n");
       return -1;
     }
-    LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
+  }
 
-    if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
-      LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
-      return -1;
+  if(gnb_nb > 0) {
+    if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) {
+      LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
+      if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
+        LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
+        return -1;
+      }
+
+      if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
+        printf("####### node is CU \n");
+        if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) {
+          LOG_E(F1AP, "Create task for F1AP CU failed\n");
+          return -1;
+        }
+      }
+    } else {
+      printf("####### node is DU \n");
+      if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) {
+        LOG_E(F1AP, "Create task for F1AP DU failed\n");
+        return -1;
+      }
     }
   }
 
@@ -793,33 +814,38 @@ static  void wait_nfapi_init(char *thread_name) {
 }
 
 void init_pdcp(void) {
-  //if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
-  pdcp_layer_init();
-  uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
-                           (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
-
-  if (IS_SOFTMODEM_NOS1) {
-    printf("IS_SOFTMODEM_NOS1 option enabled \n");
-    pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT  ;
-  }
+  if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) {
+    // pdcp_layer_init();
+    pdcp_layer_init_for_CU();
+    uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
+                            (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
+    if (IS_SOFTMODEM_NOS1) {
+      printf("IS_SOFTMODEM_NOS1 option enabled \n");
+      pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT;
+    }
 
-  pdcp_module_init(pdcp_initmask);
+    pdcp_module_init(pdcp_initmask);
 
-  /*if (NODE_IS_CU(RC.rrc[0]->node_type)) {
-    pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
-  } else {*/
-  pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
-  pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
-  //}
-  /*} else {
+    if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
+      LOG_I(PDCP, "node is CU, pdcp send rlc_data_req by proto_agent \n");
+      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
+    } else {
+      LOG_I(PDCP, "node is gNB \n");
+      pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
+      pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
+    }
+  } else {
+    LOG_I(PDCP, "node is DU, rlc send pdcp_data_ind by proto_agent \n");
     pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
-  }*/
+  }
 }
 
 
 int main( int argc, char **argv )
 {
   int ru_id, CC_id = 0;
+  int node_type = ngran_gNB;
+
   start_background_system();
 
   ///static configuration for NR at the moment
@@ -884,17 +910,33 @@ if(!IS_SOFTMODEM_NOS1)
 #endif
   LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
 
-  if(IS_SOFTMODEM_NOS1)
-    init_pdcp();
+//  if(IS_SOFTMODEM_NOS1)
+//    init_pdcp();
 
   if (RC.nb_nr_inst > 0)  {
-    // don't create if node doesn't connect to RRC/S1/GTP
-    AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n");
+    nr_read_config_and_init();
   } else {
     printf("No ITTI, Initializing L1\n");
     RCconfig_L1();
   }
 
+  if (RC.nb_nr_inst > 0)  {
+
+    if(IS_SOFTMODEM_NOS1)
+      init_pdcp();
+
+    // don't create if node doesn't connect to RRC/S1/GTP
+    AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n");
+
+    for (int gnb_id = 0; gnb_id < RC.nb_nr_inst; gnb_id++) {
+      MessageDef *msg_p = itti_alloc_new_message (TASK_GNB_APP, NRRRC_CONFIGURATION_REQ);
+      NRRRC_CONFIGURATION_REQ(msg_p) = RC.nrrrc[gnb_id]->configuration;
+      LOG_I(GNB_APP, "Sending configuration message to NR_RRC task\n");
+      itti_send_msg_to_task (TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
+    }
+    node_type = RC.nrrrc[0]->node_type;
+  }
+
   /* Start the agent. If it is turned off in the configuration, it won't start */
   /*
   RCconfig_nr_flexran();
@@ -974,36 +1016,38 @@ if(!IS_SOFTMODEM_NOS1)
     wait_nfapi_init("main?");
   }
 
-  printf("wait RUs\n");
-  wait_RUs();
-  printf("ALL RUs READY!\n");
-  printf("RC.nb_RU:%d\n", RC.nb_RU);
-  // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
-  printf("ALL RUs ready - init gNBs\n");
-  if(IS_SOFTMODEM_DOFORMS) {
-    sleep(1);	
-    scopeParms_t p;
-    p.argc=&argc;
-    p.argv=argv;
-    p.gNB=RC.gNB[0];
-    p.ru=RC.ru[0];
-    load_softscope("nr",&p);
-  }
+  if (NODE_IS_DU(node_type) || (node_type == ngran_gNB)) {
+    printf("wait RUs\n");
+    wait_RUs();
+    printf("ALL RUs READY!\n");
+    printf("RC.nb_RU:%d\n", RC.nb_RU);
+    // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
+    printf("ALL RUs ready - init gNBs\n");
+    if(IS_SOFTMODEM_DOFORMS) {
+      sleep(1);	
+      scopeParms_t p;
+      p.argc=&argc;
+      p.argv=argv;
+      p.gNB=RC.gNB[0];
+      p.ru=RC.ru[0];
+      load_softscope("nr",&p);
+    }
 
-  if (nfapi_mode != 1 && nfapi_mode != 2) {
-    printf("Not NFAPI mode - call init_eNB_afterRU()\n");
-    init_eNB_afterRU();
-  } else {
-    printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
-  }
+    if (nfapi_mode != 1 && nfapi_mode != 2) {
+      printf("Not NFAPI mode - call init_eNB_afterRU()\n");
+      init_eNB_afterRU();
+    } else {
+      printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
+    }
 
-  printf("ALL RUs ready - ALL gNBs ready\n");
-  // connect the TX/RX buffers
-  printf("Sending sync to all threads\n");
-  pthread_mutex_lock(&sync_mutex);
-  sync_var=0;
-  pthread_cond_broadcast(&sync_cond);
-  pthread_mutex_unlock(&sync_mutex);
+    printf("ALL RUs ready - ALL gNBs ready\n");
+    // connect the TX/RX buffers
+    printf("Sending sync to all threads\n");
+    pthread_mutex_lock(&sync_mutex);
+    sync_var=0;
+    pthread_cond_broadcast(&sync_cond);
+    pthread_mutex_unlock(&sync_mutex);
+  }
   printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
   end_configmodule();
   printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
@@ -1041,7 +1085,10 @@ if(!IS_SOFTMODEM_NOS1)
   printf("stopping MODEM threads\n");
   // cleanup
   stop_gNB(NB_gNB_INST);
-  stop_RU(NB_RU);
+
+  if (NODE_IS_DU(node_type) || (node_type == ngran_gNB)) {
+    stop_RU(NB_RU);
+  }
 
   /* release memory used by the RU/gNB threads (incomplete), after all
    * threads have been stopped (they partially use the same memory) */
diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c
index 0b866f4ad32..5ed1f2815ea 100644
--- a/openair2/GNB_APP/gnb_app.c
+++ b/openair2/GNB_APP/gnb_app.c
@@ -159,30 +159,6 @@ void *gNB_app_task(void *args_p)
 
   LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__);
 
-  RCconfig_NR_L1();
-
-  RCconfig_nr_macrlc();
-
-  LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
-
-  if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
-
-  AssertFatal (gnb_nb <= RC.nb_nr_inst,
-               "Number of gNB is greater than gNB defined in configuration file (%d/%d)!",
-               gnb_nb, RC.nb_nr_inst);
-
-  LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst);
-
-  RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *));
-  LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc);
-
-  for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) {
-    RC.nrrrc[gnb_id] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST));
-    LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end);
-    memset((void *)RC.nrrrc[gnb_id],0,sizeof(gNB_RRC_INST));
-    configure_nr_rrc(gnb_id);
-  }
-
   if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(RC.rrc[0]->node_type)
 	  LOG_I(X2AP, "X2AP enabled \n");
 	  __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end);
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 35ed2b399bc..a2f7518a659 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -76,8 +76,11 @@
 #include "NR_ControlResourceSet.h"
 #include "NR_EUTRA-MBSFN-SubframeConfig.h"
 
+#include "RRC/NR/MESSAGES/asn1_msg.h"
+
 extern uint16_t sf_ahead;
 int macrlc_has_f1 = 0;
+ngran_node_t node_type = ngran_gNB;
 
 extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency,
                                          int32_t uplink_frequency_offset, uint32_t  frame_type);
@@ -1424,6 +1427,22 @@ int du_check_plmn_identity(rrc_gNB_carrier_data_t *carrier,uint16_t mcc,uint16_t
   return (1);
 }
 
+void configure_gnb_du_mac(int inst) {
+  gNB_RRC_INST *rrc = RC.nrrrc[inst];
+  // LOG_I(GNB_APP,"Configuring MAC/L1 %d, carrier->sib2 %p\n", inst, &carrier->sib2->radioResourceConfigCommon);
+  LOG_I(GNB_APP,"Configuring gNB DU MAC/L1 %d \n", inst);
+  rrc_mac_config_req_gNB(rrc->module_id,
+                        rrc->configuration.ssb_SubcarrierOffset,
+                        rrc->configuration.pdsch_AntennaPorts,
+                        rrc->configuration.pusch_TargetSNRx10,
+                        rrc->configuration.pucch_TargetSNRx10,
+                        rrc->configuration.scc,
+                        0,
+                        0, // rnti
+                        (NR_CellGroupConfig_t *)NULL
+                        );
+}
+
 void gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) {
   int i, j, si_ind;
   LOG_I(GNB_APP, "cells_to_activated %d, RRC instances %d\n",
@@ -1448,10 +1467,87 @@ void gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) {
         }
 
         // perform MAC/L1 common configuration
-        // configure_du_mac(i);
+        configure_gnb_du_mac(i);
       } else {
         LOG_E(GNB_APP, "F1 Setup Response not matching\n");
       }
     }
   }
 }
+
+void set_node_type(void) {
+  int               j;
+  // ngran_node_t      node_type;
+  paramdef_t        MacRLC_Params[] = MACRLCPARAMS_DESC;
+  paramlist_def_t   MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
+  paramdef_t        GNBParams[]  = GNBPARAMS_DESC;
+  paramlist_def_t   GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
+
+  config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);   
+  config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);  
+
+  if ( MacRLC_ParamList.numelt > 0) {
+    RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; 
+    for (j=0;j<RC.nb_nr_macrlc_inst;j++) {
+      if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
+        macrlc_has_f1 = 1;
+      }
+    }
+  }
+
+  if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) {
+      node_type = ngran_gNB_CU;
+    } else {
+      if (macrlc_has_f1 == 0) {
+        node_type = ngran_gNB;
+        LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n");
+      } else {
+        node_type = ngran_gNB_DU;
+        LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n");
+      }
+    }
+}
+
+void nr_read_config_and_init(void) {
+  MessageDef *msg_p = NULL;
+  uint32_t    gnb_id;
+  uint32_t    gnb_nb = RC.nb_nr_inst;
+
+  RCconfig_NR_L1();
+  set_node_type();
+  RCconfig_nr_macrlc();
+
+  LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
+
+  if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
+
+  AssertFatal (gnb_nb <= RC.nb_nr_inst,
+               "Number of gNB is greater than gNB defined in configuration file (%d/%d)!",
+               gnb_nb, RC.nb_nr_inst);
+
+  LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst);
+
+  RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *));
+  LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc);
+
+  for (gnb_id = 0; gnb_id < RC.nb_nr_inst ; gnb_id++) {
+    RC.nrrrc[gnb_id] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST));
+    LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, RC.nb_nr_inst);
+    memset((void *)RC.nrrrc[gnb_id],0,sizeof(gNB_RRC_INST));
+    msg_p = itti_alloc_new_message (TASK_GNB_APP, NRRRC_CONFIGURATION_REQ);
+    RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]);
+  }
+
+  if (NODE_IS_DU(RC.nrrrc[0]->node_type)) {
+    RC.nrrrc[0]->carrier.servingcellconfigcommon = RC.nrrrc[0]->configuration.scc;
+    RC.nrrrc[0]->carrier.MIB             = (uint8_t *) malloc16(4);
+    RC.nrrrc[0]->carrier.sizeof_MIB      = do_MIB_NR(RC.nrrrc[0], 0);
+    RC.nrrrc[0]->carrier.sizeof_SIB1     = do_SIB1_NR(&RC.nrrrc[0]->carrier, &RC.nrrrc[0]->configuration);
+  }
+
+  if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
+    pdcp_layer_init();
+    nr_DRB_preconfiguration(0x1234);
+    rrc_init_nr_global_param();
+  }
+}
diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h
index 020aaf6f7b3..ec8cced70e0 100644
--- a/openair2/GNB_APP/gnb_config.h
+++ b/openair2/GNB_APP/gnb_config.h
@@ -108,6 +108,7 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
 int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
 int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i);
 void gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp);
+void nr_read_config_and_init(void);
 
 #endif /* GNB_CONFIG_H_ */
 /** @} */
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index c96d30b8c82..1b3a9ad0f5f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -357,7 +357,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
     void nr_rlc_tick(int frame, int subframe);
     nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
-    nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
+    // nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
   }
 
   const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 2);
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index 91341ead872..ed164528c28 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -44,6 +44,9 @@ static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager;
 /* necessary globals for OAI, not used internally */
 hash_table_t  *pdcp_coll_p;
 static uint64_t pdcp_optmask;
+#include "common/ran_context.h"
+extern RAN_CONTEXT_t RC;
+extern ngran_node_t node_type;
 
 /****************************************************************************/
 /* rlc_data_req queue - begin                                               */
@@ -397,9 +400,26 @@ void pdcp_layer_init(void)
   if (pthread_mutex_unlock(&m) != 0) abort();
 
   nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
+
   init_nr_rlc_data_req_queue();
 }
 
+void pdcp_layer_init_for_CU(void)
+{
+  /* hack: be sure to initialize only once */
+  static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+  static int initialized = 0;
+  if (pthread_mutex_lock(&m) != 0) abort();
+  if (initialized) {
+    if (pthread_mutex_unlock(&m) != 0) abort();
+    return;
+  }
+  initialized = 1;
+  if (pthread_mutex_unlock(&m) != 0) abort();
+
+  nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
+}
+
 #include "nfapi/oai_integration/vendor_ext.h"
 #include "targets/RT/USER/lte-softmodem.h"
 #include "openair2/RRC/NAS/nas_config.h"
@@ -980,7 +1000,8 @@ void nr_DRB_preconfiguration(uint16_t crnti)
     PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, crnti, 0, 0,0);
   }
 
-  nr_rrc_pdcp_config_asn1_req(
+  if (!NODE_IS_DU(node_type)) {
+    nr_rrc_pdcp_config_asn1_req(
     &ctxt,
     rbconfig->srb_ToAddModList,
     rbconfig->drb_ToAddModList ,
@@ -992,13 +1013,16 @@ void nr_DRB_preconfiguration(uint16_t crnti)
     NULL,
     NULL,
     Rlc_Bearer_ToAdd_list);
+  }
 
-  nr_rrc_rlc_config_asn1_req (&ctxt,
+  if (!NODE_IS_CU(node_type)) {
+    nr_rrc_rlc_config_asn1_req (&ctxt,
       rbconfig->srb_ToAddModList,
       rbconfig->drb_ToAddModList,
       rbconfig->drb_ToReleaseList,
       (LTE_PMCH_InfoList_r9_t *) NULL,
       Rlc_Bearer_ToAdd_list);
+  }
 
   LOG_D(PDCP, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %x\n", __FUNCTION__, __LINE__, ctxt.rnti);
 
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index f577a46373c..02ff2672710 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -35,6 +35,8 @@
 #include "NR_DRB-ToReleaseList.h"
 #include "NR_CellGroupConfig.h"
 #include "NR_RLC-Config.h"
+#include "common/ran_context.h"
+extern RAN_CONTEXT_t RC;
 
 #include <stdint.h>
 
@@ -460,6 +462,20 @@ rb_found:
     T(T_ENB_RLC_UL,
       T_INT(0 /*ctxt_pP->module_id*/),
       T_INT(ue->rnti), T_INT(rb_id), T_INT(size));
+
+    const ngran_node_t type = RC.nrrrc[0 /*ctxt_pP->module_id*/]->node_type;
+    AssertFatal(type != ngran_eNB_CU && type != ngran_ng_eNB_CU && type != ngran_gNB_CU,
+                "Can't be CU, bad node type %d\n", type);
+
+    if (NODE_IS_DU(type) && is_srb == 1) {
+      MessageDef *msg = itti_alloc_new_message(TASK_RLC_ENB, F1AP_UL_RRC_MESSAGE);
+      F1AP_UL_RRC_MESSAGE(msg).rnti = ue->rnti;
+      F1AP_UL_RRC_MESSAGE(msg).srb_id = rb_id;
+      F1AP_UL_RRC_MESSAGE(msg).rrc_container = (unsigned char *)buf;
+      F1AP_UL_RRC_MESSAGE(msg).rrc_container_length = size;
+      itti_send_msg_to_task(TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(0 /*ctxt_pP->module_id*/), msg);
+      return;
+    }
   }
 
   if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock)) {
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 9d1e0e7bc56..8d3cb7e399b 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -218,6 +218,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
   rrc->carrier.sizeof_SIB1      = do_SIB1_NR(&rrc->carrier,configuration);
   LOG_I(NR_RRC,"Done init_NR_SI\n");
   if (!NODE_IS_CU(RC.nrrrc[0]->node_type)){
+    printf("################ init_NR_SI rrc_mac_config_req_gNB \n");
     rrc_mac_config_req_gNB(rrc->module_id,
                           rrc->carrier.ssb_SubcarrierOffset,
                           rrc->carrier.pdsch_AntennaPorts,
@@ -276,7 +277,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
     } else {
       struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(rrc);
       LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p);
-      rrc_add_nsa_user(rrc,ue_context_p,NULL);
+      // rrc_add_nsa_user(rrc,ue_context_p,NULL);
     }
   }
 }
@@ -2442,8 +2443,10 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *f1_setup_req) {
         itti_send_msg_to_task (TASK_CU_F1, GNB_MODULE_ID_TO_INSTANCE(j), msg_p);
         break;
       } else {// setup_req mcc/mnc match rrc internal list element
-        LOG_W(NR_RRC,"[Inst %d] No matching MCC/MNC: rrc->mcc/f1_setup_req->mcc %d/%d rrc->mnc/f1_setup_req->mnc %d/%d \n",
-              j, rrc->configuration.mcc[0], f1_setup_req->mcc[i],rrc->configuration.mnc[0], f1_setup_req->mnc[i]);
+        LOG_W(NR_RRC,"[Inst %d] No matching MCC/MNC: rrc->mcc/f1_setup_req->mcc %d/%d rrc->mnc/f1_setup_req->mnc %d/%d rrc->nr_cellid/f1_setup_req->nr_cellid %d/%d \n",
+              j, rrc->configuration.mcc[0], f1_setup_req->mcc[i],
+                 rrc->configuration.mnc[0], f1_setup_req->mnc[i],
+                 rrc->nr_cellid, f1_setup_req->nr_cellid[i]);
       }
     }// for (int j=0;j<RC.nb_inst;j++)
 
-- 
GitLab