diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 5457768998f33502b4907e8e79f20adfe991243c..e7da79dda0666d486d7ead0b24ac6707b0b5d06a 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -2106,7 +2106,7 @@ add_executable(lte-softmodem-nos1
   )
 target_link_libraries (lte-softmodem-nos1
   -Wl,--start-group
-  RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} 
+  RRC_LIB F1AP F1AP_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB}
   ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} LFDS7
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl )
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index c120e79496599ead2aed5bbc6102d9e388ec120e..077265b246eb02633422183dd9c44b9f6340b8ab 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -43,15 +43,8 @@
 # if defined(ENABLE_USE_MME)
 #   define ENB_REGISTER_RETRY_DELAY 10
 #   include "s1ap_eNB.h"
-#   include "sctp_eNB_task.h"
-#   include "gtpv1u_eNB_task.h"
-#   include "nas_ue_task.h"
-#   include "udp_eNB_task.h"
 # endif
 
-extern void *F1AP_CU_task(void *);
-extern void *F1AP_DU_task(void *);
-
 #if defined(FLEXRAN_AGENT_SB_IF)
 #   include "flexran_agent.h"
 #endif
@@ -60,72 +53,11 @@ extern void *F1AP_DU_task(void *);
 extern unsigned char NB_eNB_INST;
 #endif
 
-extern int emulate_rf;
 extern RAN_CONTEXT_t RC;
-extern void *l2l1_task(void *arg);
+extern int emulate_rf;
 
 #if defined(ENABLE_ITTI)
 
-/*------------------------------------------------------------------------------*/
-static void create_remaining_tasks(module_id_t enb_id)
-{
-  ngran_node_t type = RC.rrc[enb_id]->node_type;
-  int rc;
-  itti_wait_ready(1);
-  switch (type) {
-  case ngran_eNB_CU:
-  case ngran_ng_eNB_CU:
-  case ngran_gNB_CU:
-    rc = itti_create_task(TASK_CU_F1, F1AP_CU_task, enb_id);
-    AssertFatal(rc >= 0, "Create task for CU F1AP failed\n");
-    /* fall through */
-  case ngran_eNB:
-  case ngran_ng_eNB:
-  case ngran_gNB:
-    rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL);
-    AssertFatal(rc >= 0, "Create task for S1AP failed\n");
-    if (!emulate_rf){
-      rc = itti_create_task(TASK_UDP, udp_eNB_task, NULL);
-      AssertFatal(rc >= 0, "Create task for UDP failed\n");
-    }
-    rc = itti_create_task(TASK_GTPV1_U, &gtpv1u_eNB_task, NULL);
-    AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
-    break;
-  default:
-    /* intentionally left blank */
-    break;
-  }
-  switch (type) {
-  case ngran_eNB_DU:
-  case ngran_gNB_DU:
-    rc = itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL);
-    AssertFatal(rc >= 0, "Create task for DU F1AP failed\n");
-    /* fall through */
-  case ngran_eNB:
-  case ngran_ng_eNB:
-  case ngran_gNB:
-    rc = itti_create_task (TASK_L2L1, l2l1_task, NULL);
-    AssertFatal(rc >= 0, "Create task for L2L1 failed\n");
-    break;
-  default:
-    /* intentioally left blank */
-    break;
-  }
-  itti_wait_ready(0);
-}
-
-/*------------------------------------------------------------------------------*/
-static void configure_rrc(uint32_t enb_id, MessageDef **msg_p)
-{
-  RC.rrc[enb_id] = malloc(sizeof(eNB_RRC_INST));
-  AssertFatal(RC.rrc[enb_id], "RRC context for eNB %d not allocated\n", enb_id);
-  LOG_I(ENB_APP, "%s() Creating RRC instance RC.rrc[%d]: %p\n",
-      __FUNCTION__, enb_id, RC.rrc[enb_id]);
-  memset((void *)RC.rrc[enb_id],0,sizeof(eNB_RRC_INST));
-  *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
-  RCconfig_RRC(*msg_p, enb_id, RC.rrc[enb_id]);
-}
-
 /*------------------------------------------------------------------------------*/
 # if defined(ENABLE_USE_MME)
 static uint32_t eNB_app_register(ngran_node_t node_type,uint32_t enb_id_start, uint32_t enb_id_end)//, const Enb_properties_array_t *enb_properties)
@@ -185,49 +117,10 @@ void *eNB_app_task(void *args_p)
   MessageDef                     *msg_p           = NULL;
   instance_t                      instance;
   int                             result;
-  MessageDef                     *rrc_msg_p[enb_nb];
   /* for no gcc warnings */
   (void)instance;
-  int mac_has_f1[MAX_MAC_INST];
-  memset(mac_has_f1,0,MAX_MAC_INST*sizeof(int));
 
   itti_mark_task_ready (TASK_ENB_APP);
-  LOG_I(PHY, "%s() Task ready, initialise L1/MAC/RRC structures\n", __FUNCTION__);
-
-  RCconfig_L1();
-
-  RCconfig_macrlc(mac_has_f1);
-
-  LOG_I(PHY, "%s() RC.nb_L1_inst:%d\n", __FUNCTION__, RC.nb_L1_inst);
-
-  LOG_I(PHY, "%s() RC.nb_macrlc_inst:%d\n", __FUNCTION__, RC.nb_macrlc_inst);
-
-  if (RC.nb_L1_inst>0)
-    AssertFatal(l1_north_init_eNB()==0,"could not initialize L1 north interface\n");
-  if (RC.nb_macrlc_inst>0)
-    AssertFatal(RC.nb_macrlc_inst == enb_id_end-enb_id_start,
-      "Number of MACRLC instances %d != number of RRC instances %d\n",
-      RC.nb_macrlc_inst, enb_id_end-enb_id_start);
-
-  LOG_I(ENB_APP,"Allocating eNB_RRC_INST for %d instances\n",RC.nb_inst);
-  RC.rrc = (eNB_RRC_INST **)malloc(RC.nb_inst*sizeof(eNB_RRC_INST *));
-  LOG_I(ENB_APP, "%s() RC.nb_inst:%d RC.rrc:%p\n", __FUNCTION__, RC.nb_inst, RC.rrc);
-
-  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
-    configure_rrc(enb_id, &rrc_msg_p[enb_id]);
-
-    if (RC.nb_macrlc_inst > 0 && mac_has_f1[enb_id]==1)
-      RC.rrc[enb_id]->node_type = ngran_eNB_DU;
-    else
-      pdcp_layer_init();
-  }
-
-  create_remaining_tasks(0);
-
-  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
-    LOG_I(ENB_APP,"Sending configuration message to RRC task\n");
-    itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), rrc_msg_p[enb_id]);
-  }
 
 # if defined(ENABLE_USE_MME)
   /* Try to register each eNB */
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 41ac60cc0b545287d5496164e809aa6aeb060a9a..dcad36dc71eb7327ce4c25e87b842399c82d59da 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -333,7 +333,7 @@ void RCconfig_L1(void) {
   }
 }
 
-void RCconfig_macrlc(int *mac_has_f1) {
+void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
 
   int               j;
 
@@ -371,7 +371,7 @@ void RCconfig_macrlc(int *mac_has_f1) {
 	RC.mac[j]->eth_params_n.my_portd                 = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
 	RC.mac[j]->eth_params_n.remote_portd             = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);;
 	RC.mac[j]->eth_params_n.transp_preference        = ETH_UDP_MODE;
-	mac_has_f1[j]                                    = 1;
+        macrlc_has_f1[j]                                 = 1;
       } else { // other midhaul
 	AssertFatal(1==0,"MACRLC %d: %s unknown northbound midhaul\n",j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr));
       }	
@@ -541,7 +541,7 @@ cudu_params_t *get_cudu_config()
     return &(RC.cudu);
 }
 	       
-int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
+int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc) {
 
   int               num_enbs                      = 0;
  
@@ -708,6 +708,7 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
   char* 	    osa_log_verbosity		  = NULL;
 */  
 
+  MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_CONFIGURATION_REQ);
   
   // for no gcc warnings 
   (void)my_int;
@@ -786,7 +787,6 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
       else if (strcmp(*(ENBParamList.paramarray[i][ENB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) {
 
 	paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
-	paramdef_t NETParams[]  =  NETPARAMS_DESC;
 	char aprefix[MAX_OPTNAME_SIZE*2 + 8];
 
 	sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,i,ENB_CONFIG_STRING_SCTP_CONFIG);
@@ -2308,6 +2308,12 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
 	  }
 	}
       }
+
+#if defined (ENABLE_ITTI)
+      memcpy(&RC.rrc[i]->configuration, &RRC_CONFIGURATION_REQ(msg_p),
+             sizeof(RRC_CONFIGURATION_REQ(msg_p)));
+#endif
+
   }
 return 0;
 }
@@ -2380,7 +2386,6 @@ int RCconfig_DU_F1(MessageDef *msg_p, uint32_t i) {
       if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[k], *(ENBParamList.paramarray[i][ENB_ENB_NAME_IDX].strptr) )== 0) {
 
         paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
-        paramdef_t NETParams[]  =  NETPARAMS_DESC;
         char aprefix[MAX_OPTNAME_SIZE*2 + 8];
 	
         F1AP_SETUP_REQ (msg_p).gNB_DU_id        = *(ENBParamList.paramarray[0][ENB_ENB_ID_IDX].uptr);
@@ -2959,3 +2964,36 @@ void handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) {
     }
   }
 }
+
+void read_config_and_init()
+{
+  int macrlc_has_f1[MAX_MAC_INST];
+  memset(macrlc_has_f1, 0 , MAX_MAC_INST*sizeof(int));
+
+  if (RC.nb_macrlc_inst > 0)
+    AssertFatal(RC.nb_macrlc_inst == RC.nb_inst,
+                "Number of MACRLC instances %d != number of RRC instances %d\n",
+                RC.nb_macrlc_inst, RC.nb_inst);
+
+  RCconfig_L1();
+  LOG_I(PHY, "%s() RC.nb_L1_inst: %d\n", __FUNCTION__, RC.nb_L1_inst);
+
+  RCconfig_macrlc(macrlc_has_f1);
+  LOG_I(MAC, "%s() RC.nb_macrlc_inst: %d\n", __FUNCTION__, RC.nb_macrlc_inst);
+
+  if (RC.nb_L1_inst > 0)
+    AssertFatal(l1_north_init_eNB() == 0, "could not initialize L1 north interface\n");
+
+  RC.rrc = malloc(RC.nb_inst * sizeof(eNB_RRC_INST *));
+  AssertFatal(RC.rrc, "could not allocate memory for RC.rrc\n");
+  for (uint32_t enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
+    RC.rrc[enb_id] = malloc(sizeof(eNB_RRC_INST));
+    AssertFatal(RC.rrc[enb_id], "RRC context for eNB %d not allocated\n", enb_id);
+    memset((void *)RC.rrc[enb_id], 0, sizeof(eNB_RRC_INST));
+    RCconfig_RRC(enb_id, RC.rrc[enb_id]);
+    if (macrlc_has_f1[enb_id]) RC.rrc[enb_id]->node_type = ngran_eNB_DU;
+  }
+
+  if (RC.nb_macrlc_inst == 0)
+    pdcp_layer_init();
+}
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 33076c6e3fdb19c750c3886dfd017c835de70151..0dc934dfdabc1e427fcfe9cfa8b2121452306bf7 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -135,7 +135,7 @@ typedef struct ru_config_s {
 extern void RCconfig_RU(void);
 extern void RCconfig_flexran(void);
 extern void RCconfig_L1(void);
-extern void RCconfig_macrlc(int*);
+extern void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]);
 extern void UE_config_stub_pnf(void);
 extern int  RCconfig_gtpu(void );
 extern void RCConfig(void);
@@ -143,13 +143,14 @@ extern void RCConfig(void);
 void                          enb_config_display(void);
 void                          ru_config_display(void);
 
-int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc);
+int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc);
 int RCconfig_S1(MessageDef *msg_p, uint32_t i);
 int RCconfig_DU_F1(MessageDef *msg_p, uint32_t i);
 int RCconfig_CU_F1(uint32_t i);
 
 void RCconfig_cudu(void);
 cudu_params_t *get_cudu_config(void);
+void read_config_and_init(void);
 
 #endif /* ENB_CONFIG_H_ */
 /** @} */
diff --git a/openair2/F1AP/CU_F1AP.c b/openair2/F1AP/CU_F1AP.c
index c92bdb0240c7cffd5b22fcecd7f2e0c688441fb3..0e3b4ba14f104e35b6788e7c8e5675aa0b3392ce 100644
--- a/openair2/F1AP/CU_F1AP.c
+++ b/openair2/F1AP/CU_F1AP.c
@@ -135,7 +135,7 @@ void *F1AP_CU_task(void *arg) {
 
   itti_mark_task_ready(TASK_CU_F1);
 
-  CU_send_sctp_init_req(arg);
+  CU_send_sctp_init_req(0);
 
   while (1) {
     itti_receive_msg(TASK_CU_F1, &received_msg);
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index 124e573d9549f51aee0ee2b3e09863372fd6ce26..8b06950292d56e2b9f82c830510f178d2b86e302 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -5923,8 +5923,7 @@ void setup_ngran_CU(eNB_RRC_INST *rrc) {
 //-----------------------------------------------------------------------------
 char
 openair_rrc_eNB_configuration(
-  const module_id_t enb_mod_idP,
-  RrcConfigurationReq* configuration
+  const module_id_t enb_mod_idP
 )
 #else
 char
@@ -5950,9 +5949,6 @@ openair_rrc_eNB_init(
 #endif 
   AssertFatal(RC.rrc[enb_mod_idP] != NULL, "RC.rrc not initialized!");
   AssertFatal(MAX_MOBILES_PER_ENB < (module_id_t)0xFFFFFFFFFFFFFFFF, " variable overflow");
-#ifdef ENABLE_ITTI
-  AssertFatal(configuration!=NULL,"configuration input is null\n");
-#endif
   //    for (j = 0; j < MAX_MOBILES_PER_ENB; j++)
   //        RC.rrc[ctxt.module_id].Info.UE[j].Status = RRC_IDLE;  //CH_READY;
   //
@@ -5987,8 +5983,6 @@ openair_rrc_eNB_init(
   RC.rrc[ctxt.module_id]->initial_id2_s1ap_ids = hashtable_create (MAX_MOBILES_PER_ENB * 2, NULL, NULL);
   RC.rrc[ctxt.module_id]->s1ap_id2_s1ap_ids    = hashtable_create (MAX_MOBILES_PER_ENB * 2, NULL, NULL);
 
-  memcpy(&RC.rrc[ctxt.module_id]->configuration,configuration,sizeof(RrcConfigurationReq));
-
   /// System Information INIT
 
   LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Checking release \n",
@@ -6038,7 +6032,7 @@ openair_rrc_eNB_init(
     init_SI(&ctxt,
             CC_id
 #if defined(ENABLE_ITTI)
-            , configuration
+            , &RC.rrc[enb_mod_idP]->configuration
 #endif
            );
     for (int ue_id = 0; ue_id < MAX_MOBILES_PER_ENB; ue_id++) {
@@ -7616,8 +7610,8 @@ rrc_enb_task(
 
       /* Messages from eNB app */
     case RRC_CONFIGURATION_REQ:
-      LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p));
-      openair_rrc_eNB_configuration(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p));
+      LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p, &RRC_CONFIGURATION_REQ(msg_p));
+      openair_rrc_eNB_configuration(ENB_INSTANCE_TO_MODULE_ID(instance));
       break;
 
     default:
diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h
index 4e8ee304c1c3d6836dff6a29e17d0e14a05416cc..7934d96cb1d748ee5fd1be9f5eb4393a2ea14b63 100644
--- a/openair2/RRC/LTE/rrc_proto.h
+++ b/openair2/RRC/LTE/rrc_proto.h
@@ -42,8 +42,7 @@ void openair_rrc_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_a
 #if defined(ENABLE_ITTI)
 char
 openair_rrc_eNB_configuration(
-  const module_id_t enb_mod_idP,
-  RrcConfigurationReq* configuration
+  const module_id_t enb_mod_idP
 );
 #endif
 char openair_rrc_eNB_init(
diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c
index 391e448deb590584e9a4b917edd4a6210b1fa1a5..03b13c879c74c890fc02293331f6478d10119936 100644
--- a/targets/COMMON/create_tasks.c
+++ b/targets/COMMON/create_tasks.c
@@ -23,81 +23,107 @@
 # include "intertask_interface.h"
 # include "create_tasks.h"
 # include "log.h"
+# include "common/ran_context.h"
 
 # ifdef OPENAIR2
 #   if defined(ENABLE_USE_MME)
-#     include "sctp_eNB_task.h"
 #     include "s1ap_eNB.h"
 #     include "nas_ue_task.h"
 #     include "udp_eNB_task.h"
 #     include "gtpv1u_eNB_task.h"
 #   endif
-#   if ENABLE_RAL
-#     include "lteRALue.h"
-#     include "lteRALenb.h"
-#   endif
 #   include "RRC/LTE/rrc_defs.h"
 # endif
+# include "sctp_eNB_task.h"
+# include "cu_f1ap_task.h"
+# include "du_f1ap_task.h"
 # include "enb_app.h"
 
+extern RAN_CONTEXT_t RC;
 extern int emulate_rf;
 
 int create_tasks(uint32_t enb_nb)
 {
-  LOG_D(ENB_APP, "%s(enb_nb:%d\n", __FUNCTION__, enb_nb);
+  ngran_node_t type = RC.rrc[0]->node_type;
+  int rc;
 
   itti_wait_ready(1);
-  if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
-    LOG_E(PDCP, "Create task for L2L1 failed\n");
-    return -1;
-  }
 
   if (enb_nb > 0) {
-    /* Last task to create, others task must be ready before its start */
+    LOG_I(ENB_APP, "Creating ENB_APP eNB Task\n");
     if (itti_create_task (TASK_ENB_APP, eNB_app_task, NULL) < 0) {
       LOG_E(ENB_APP, "Create task for eNB APP failed\n");
       return -1;
     }
+    LOG_I(RRC,"Creating RRC eNB Task\n");
+    if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
+      LOG_E(RRC, "Create task for RRC eNB failed\n");
+      return -1;
+    }
   }
 
-#   if defined(ENABLE_USE_MME)
-      if (enb_nb > 0) {
-        if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
-          LOG_E(SCTP, "Create task for SCTP failed\n");
-          return -1;
-        }
-
-        if (itti_create_task (TASK_S1AP, s1ap_eNB_task, NULL) < 0) {
-          LOG_E(S1AP, "Create task for S1AP failed\n");
-          return -1;
-        }
-        if(!emulate_rf){
-          if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) {
-            LOG_E(UDP_, "Create task for UDP failed\n");
-            return -1;
-          }
-        }
-
-        if (itti_create_task (TASK_GTPV1_U, &gtpv1u_eNB_task, NULL) < 0) {
-          LOG_E(GTPU, "Create task for GTPV1U failed\n");
-          return -1;
-        }
-      }
-
-#      endif
+  if (enb_nb > 0) {
+    /* this task needs not be started if:
+     * * there is no CU/DU split
+     * * ENABLE_USE_MME is not defined
+     * Since we cannot express this condition on both configuration and
+     * compilation defines, we always start this task.
+     */
+    if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
+      LOG_E(SCTP, "Create task for SCTP failed\n");
+      return -1;
+    }
+  }
 
+  switch (type) {
+  case ngran_eNB_CU:
+  case ngran_ng_eNB_CU:
+  case ngran_gNB_CU:
     if (enb_nb > 0) {
-      LOG_I(RRC,"Creating RRC eNB Task\n");
-
-      if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
-        LOG_E(RRC, "Create task for RRC eNB failed\n");
-        return -1;
+      rc = itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL);
+      AssertFatal(rc >= 0, "Create task for CU F1AP failed\n");
+    }
+    /* fall through */
+  case ngran_eNB:
+  case ngran_ng_eNB:
+  case ngran_gNB:
+#if defined(ENABLE_USE_MME)
+    if (enb_nb > 0) {
+      rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL);
+      AssertFatal(rc >= 0, "Create task for S1AP failed\n");
+      if (!emulate_rf){
+        rc = itti_create_task(TASK_UDP, udp_eNB_task, NULL);
+        AssertFatal(rc >= 0, "Create task for UDP failed\n");
       }
+      rc = itti_create_task(TASK_GTPV1_U, &gtpv1u_eNB_task, NULL);
+      AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
     }
-
+#endif
+    break;
+  default:
+    /* intentionally left blank */
+    break;
+  }
+  switch (type) {
+  case ngran_eNB_DU:
+  case ngran_gNB_DU:
+    if (enb_nb > 0) {
+      rc = itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL);
+      AssertFatal(rc >= 0, "Create task for DU F1AP failed\n");
+    }
+    /* fall through */
+  case ngran_eNB:
+  case ngran_ng_eNB:
+  case ngran_gNB:
+    rc = itti_create_task (TASK_L2L1, l2l1_task, NULL);
+    AssertFatal(rc >= 0, "Create task for L2L1 failed\n");
+    break;
+  default:
+    /* intentioally left blank */
+    break;
+  }
 
   itti_wait_ready(0);
-
   return 0;
 }
 #endif
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 43a5cf9ee46eb0cad19ab528bd73175ea0b208f2..3b51f2c712f270baad7f718a8110852453c2a30c 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -1058,69 +1058,33 @@ int main( int argc, char **argv )
   LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
 #endif
   
+  /* Start the agent. If it is turned off in the configuration, it won't start */
+  RCconfig_flexran();
+  for (i = 0; i < RC.nb_inst; i++) {
+    flexran_agent_start(i);
+  }
     
-
-    
-  int have_rrc=0;
-
   if (RC.nb_inst > 0)  {
-    itti_wait_ready(1);
-    LOG_I(ENB_APP, "Creating ENB_APP eNB Task\n");
-    if (itti_create_task (TASK_ENB_APP, eNB_app_task, NULL) < 0) {
-      LOG_E(ENB_APP, "Create task for eNB APP failed\n");
-      return -1;
-    }
-    LOG_I(RRC,"Creating RRC eNB Task\n");
-    if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
-      LOG_E(RRC, "Create task for RRC eNB failed\n");
-      return -1;
+    read_config_and_init();
+
+    if (create_tasks(1) < 0) {
+      printf("cannot create ITTI tasks\n");
+      exit(-1);
     }
-    printf("ITTI tasks created\n");
-    have_rrc=1;
-    if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
-      LOG_E(SCTP, "Create task for SCTP failed\n");
-      return -1;
+
+    for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) {
+      MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
+      itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
     }
-    itti_wait_ready(0);
   }
   else {
     printf("No ITTI, Initializing L1\n");
     RCconfig_L1();
   }
 
-
-  /* Start the agent. If it is turned off in the configuration, it won't start */
-  RCconfig_flexran();
-  for (i = 0; i < RC.nb_L1_inst; i++) {
-    flexran_agent_start(i);
-  }
-
-  int cu_flag =0;
-
-  if (have_rrc == 1) {
-
-    // wait for RRC to be initialized
-    
-
-    int rrc_allocated;
-    do {
-      rrc_allocated=1;
-      for (int i=0;i<RC.nb_inst;i++) 
-	if (RC.rrc == NULL || RC.rrc[i]==NULL) rrc_allocated=0;
-      if (rrc_allocated==0) { printf("Waiting for RRC allocation ...\n"); usleep(10000); }
-    } while (rrc_allocated==0);
-
-    int cell_info_configured;
-    do {
-      pthread_mutex_lock(&RC.rrc[0]->cell_info_mutex);
-      cell_info_configured = RC.rrc[0]->cell_info_configured;
-      pthread_mutex_unlock(&RC.rrc[0]->cell_info_mutex);
-      if (cell_info_configured == 0) {printf ("Waiting for RRC cell configuration\n"); usleep(10000);}
-    } while(cell_info_configured == 0);
-    if (RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU) cu_flag=1;  
-   }
- 
-  if (cu_flag == 0) {
+  /* start threads if only L1 or not a CU */
+  if (RC.nb_inst == 0 ||
+      !(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
       // init UE_PF_PO and mutex lock
     pthread_mutex_init(&ue_pf_po_mutex, NULL);
     memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
@@ -1285,7 +1249,8 @@ int main( int argc, char **argv )
   // stop threads
 
 
-  if (cu_flag == 0) {
+  if (RC.nb_inst == 0 ||
+      !(RC.rrc[0]->node_type == ngran_eNB_CU || RC.rrc[0]->node_type == ngran_ng_eNB_CU)) {
     int UE_id;
 #ifdef XFORMS
     printf("waiting for XFORMS thread\n");