diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 4b06be7d6700b716647590cbf9e4156312ccabdc..73a220506b28f199c08fe6b067307cf44c04de19 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1939,6 +1939,8 @@ set (MAC_NR_SRC
   ${NR_GNB_MAC_DIR}/gNB_scheduler_srs.c
   ${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c
   ${NR_GNB_MAC_DIR}/mac_rrc_dl_handler.c
+  ${NR_GNB_MAC_DIR}/mac_rrc_ul_direct.c
+  ${NR_GNB_MAC_DIR}/mac_rrc_ul_f1ap.c
  )
 
 
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 78b253ca2af42c756fa56e37ba37c02f1f350ca6..47669fc0bdf022ff12e1b6ba5f05733bbf9c88df 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -756,7 +756,7 @@ int main(int argc, char **argv)
   RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
   for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
     RC.nb_nr_mac_CC[i] = 1;
-  mac_top_init_gNB();
+  mac_top_init_gNB(ngran_gNB);
   gNB_mac = RC.nrmac[0];
   gNB_RRC_INST rrc;
   memset((void*)&rrc,0,sizeof(rrc));
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index ffb168fd68d5b7d2a297fb25797d9be8deb7f46c..725c8d9e1ff8cbd3fda273f3eef4e8cb6111c0af 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -762,7 +762,7 @@ int main(int argc, char **argv)
   RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
   for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
     RC.nb_nr_mac_CC[i] = 1;
-  mac_top_init_gNB();
+  mac_top_init_gNB(ngran_gNB);
   //gNB_MAC_INST* gNB_mac = RC.nrmac[0];
   gNB_RRC_INST rrc;
   memset((void*)&rrc,0,sizeof(rrc));
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index e6c5c8036a2a5a3315f388c4860a20e36272e15c..90c8610c50be73dbd246b6198b9413104cc6781f 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -85,7 +85,8 @@
 
 extern uint16_t sf_ahead;
 int macrlc_has_f1 = 0;
-extern ngran_node_t node_type;
+
+static ngran_node_t get_node_type(void);
 
 extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency,
                                          int32_t uplink_frequency_offset, uint32_t  frame_type);
@@ -795,6 +796,7 @@ void RCconfig_nr_macrlc() {
   paramdef_t GNBParams[]  = GNBPARAMS_DESC;
 
   paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
+  ngran_node_t node_type = get_node_type();
 
   config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); 
   int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
@@ -821,7 +823,7 @@ void RCconfig_nr_macrlc() {
   if ( MacRLC_ParamList.numelt > 0) {
 
     RC.nb_nr_macrlc_inst=MacRLC_ParamList.numelt; 
-    mac_top_init_gNB();   
+    mac_top_init_gNB(node_type);
     RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
 
     for (j=0;j<RC.nb_nr_macrlc_inst;j++) {
@@ -2253,8 +2255,8 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up
   return(ret);
 }
 
-void set_node_type(void) {
-  int               j;
+static ngran_node_t get_node_type(void)
+{
   paramdef_t        MacRLC_Params[] = MACRLCPARAMS_DESC;
   paramlist_def_t   MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
   paramdef_t        GNBParams[]  = GNBPARAMS_DESC;
@@ -2265,24 +2267,19 @@ void set_node_type(void) {
 
   if ( MacRLC_ParamList.numelt > 0) {
     RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; 
-    for (j=0;j<RC.nb_nr_macrlc_inst;j++) {
+    for (int 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");
-      }
-    }
+  if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0)
+    return ngran_gNB_CU;
+  else if (macrlc_has_f1 == 0)
+    return ngran_gNB;
+  else
+    return ngran_gNB_DU;
 }
 
 void nr_read_config_and_init(void) {
@@ -2291,7 +2288,6 @@ void nr_read_config_and_init(void) {
   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);
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index 218b75b2e816663c24e694ad8516077f2256053e..6be41a8a683983bf6bed9d977ec20c05584dab1a 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -51,7 +51,6 @@
 
 extern RAN_CONTEXT_t RC;
 //extern int l2_init_gNB(void);
-extern void mac_top_init_gNB(void);
 extern uint8_t nfapi_mode;
 
 void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list,
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 2229dc32f2d465e145a0d4cc3f15d9db2c0af25e..4b48eb74dd411923d082bfa6e47feb6362a54fcf 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -36,7 +36,7 @@
 
 void set_cset_offset(uint16_t);
 
-void mac_top_init_gNB(void);
+void mac_top_init_gNB(ngran_node_t node_type);
 
 void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl);
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb80ba4fa55c1f5c3a6ba9df5e6a41b546a3a850
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h
@@ -0,0 +1,34 @@
+/*
+ * 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 MAC_RRC_UL_H
+#define MAC_RRC_UL_H
+
+#include "platform_types.h"
+#include "f1ap_messages_types.h"
+
+typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc);
+
+struct nr_mac_rrc_ul_if_s;
+void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc);
+void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc);
+
+#endif /* MAC_RRC_UL_H */
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
new file mode 100644
index 0000000000000000000000000000000000000000..f290e0d2680606da19123ce902fc2021560a499e
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c
@@ -0,0 +1,35 @@
+/*
+ * 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 "nr_mac_gNB.h"
+
+#include "mac_rrc_ul.h"
+
+static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc)
+{
+  /* TODO ITTI message for NR_RRC_MAC_IND? */
+  AssertFatal(0 == 1, "not implemented\n");
+}
+
+void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
+{
+  mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct;
+}
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed67fb91193fc84ab5ef720ea0621e8538aaf5bc
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c
@@ -0,0 +1,35 @@
+/*
+ * 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 "nr_mac_gNB.h"
+
+#include "mac_rrc_ul.h"
+
+static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc)
+{
+  AssertFatal(0 == 1, "not implemented\n");
+}
+
+void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
+{
+  mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap;
+}
+
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index 9b9fd4e76cbed3900730877eca4af3d13ecde5c0..9b38b6fcab8be5848e8f3fcae7ad77898744e0de 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -165,8 +165,25 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
   return output - begin;
 }
 
+static void mac_rrc_init(gNB_MAC_INST *mac, ngran_node_t node_type)
+{
+  switch (node_type) {
+    case ngran_gNB_CU:
+      AssertFatal(1 == 0, "nothing to do for CU\n");
+      break;
+    case ngran_gNB_DU:
+      mac_rrc_ul_f1ap_init(&mac->mac_rrc);
+      break;
+    case ngran_gNB:
+      mac_rrc_ul_direct_init(&mac->mac_rrc);
+      break;
+    default:
+      AssertFatal(0 == 1, "Unknown node type %d\n", node_type);
+      break;
+  }
+}
 
-void mac_top_init_gNB(void)
+void mac_top_init_gNB(ngran_node_t node_type)
 {
   module_id_t     i;
   gNB_MAC_INST    *nrmac;
@@ -213,6 +230,7 @@ void mac_top_init_gNB(void)
       }
       pthread_create(&RC.nrmac[i]->stats_thread,NULL,nrmac_stats_thread,(void*)RC.nrmac[i]);
 
+      mac_rrc_init(RC.nrmac[i], node_type);
     }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
 
     AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n");
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index 7658441aed63941282b248dc53f2e04f6fcfaa38..f41aea73baae6b944430aba8354b0b9044113312 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -60,6 +60,7 @@
 /* Interface */
 #include "nfapi_nr_interface_scf.h"
 #include "NR_PHY_INTERFACE/NR_IF_Module.h"
+#include "mac_rrc_ul.h"
 
 /* MAC */
 #include "LAYER2/MAC/mac.h"
@@ -701,6 +702,11 @@ typedef struct NR_bler_options {
   uint8_t max_mcs;
 } NR_bler_options_t;
 
+typedef struct nr_mac_rrc_ul_if_s {
+  /* TODO add other message types as necessary */
+  initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer;
+} nr_mac_rrc_ul_if_t;
+
 /*! \brief UE list used by gNB to order UEs/CC for scheduling*/
 #define MAX_CSI_REPORTCONFIG 48
 typedef struct {
@@ -853,6 +859,8 @@ typedef struct gNB_MAC_INST_s {
   uint8_t harq_round_max;
   uint8_t min_grant_prb;
   uint8_t min_grant_mcs;
+
+  nr_mac_rrc_ul_if_t mac_rrc;
 } gNB_MAC_INST;
 
 #endif /*__LAYER2_NR_MAC_GNB_H__ */