diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..6d85cbb418fd792e571e8e67456996d335438795
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "openair2/E2AP/flexric"]
+	path = openair2/E2AP/flexric
+	url = https://gitlab.eurecom.fr/mosaic5g/flexric.git
+	branch = remotes/origin/mir_dev
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 110a10bf044c2292be5303bc301342f954166e17..c495fb52ccd14644a1aa52d76400943b57f58f24 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -328,6 +328,18 @@ endif()
 # asn1c skeletons need this
 add_definitions(-DHAVE_NETINET_IN_H)
 
+#########################
+##### E2 AGENT
+#########################
+#add_boolean_option() does not work -- why?
+set(E2_AGENT "OFF" CACHE STRING "O-RAN-compliant E2 Agent")
+set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF")
+
+if(E2_AGENT)
+  set(E2AP_DIR ${OPENAIR2_DIR}/E2AP)
+  add_subdirectory ("${E2AP_DIR}")
+endif()
+
 ##################################################
 # ASN.1 grammar C code generation & dependencies #
 ##################################################
@@ -1567,6 +1579,11 @@ add_library(L2
   )
 target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap)
 target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
+if(E2_AGENT)
+  target_link_libraries(L2 PUBLIC e2_agent e2_ran_func)
+  target_compile_definitions(L2 PRIVATE E2_AGENT)
+endif()
+
 
 add_library(MAC_NR ${MAC_NR_SRC})
 target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
@@ -1597,6 +1614,11 @@ add_library(e1_pdcp_if
 target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
 
 target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap)
+if(E2_AGENT)
+  target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func)
+  target_compile_definitions(L2_NR PRIVATE E2_AGENT)
+endif()
+
 
 add_library(L2_LTE_NR
   ${L2_RRC_SRC}
@@ -2174,6 +2196,10 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP
 target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
 target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
 
+if(E2_AGENT)
+  target_compile_definitions(lte-softmodem PRIVATE E2_AGENT)
+endif()
+
 add_executable(oairu
   ${OPENAIR_DIR}/executables/lte-ru.c
   ${OPENAIR_DIR}/executables/ru_control.c
@@ -2285,6 +2311,10 @@ endif()
 # force the generation of ASN.1 so that we don't need to wait during the build
 target_link_libraries(nr-softmodem PRIVATE
   asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
+if(E2_AGENT)
+  target_compile_definitions(nr-softmodem PRIVATE E2_AGENT)
+endif()
+
 
 add_executable(nr-cuup
   executables/nr-cuup.c
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index 1d4c55da2050c6a089be0094cd9f970a4266495e..0639385a1abf1795dfe6eb65ea3ec8600648a7d9 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -78,6 +78,8 @@ Options:
    Pass the supplied option verbatim to cmake.
 -d | --build-dir
    Sets build directory (will be <oai-root>/cmake_targets/<build-dir>/build)
+--build-e2
+   Enable the the E2 Agent
 -I | --install-external-packages
    Installs required packages such as LibXML, asn1.1 compiler, ...
    This option will require root password
@@ -197,6 +199,10 @@ function main() {
        -d | --build-dir)
             BUILD_DIR=$2
             shift 2;;
+       --build-e2 )
+             CMAKE_CMD="$CMAKE_CMD -DE2_AGENT=ON"
+             shift
+             ;;
        -I | --install-external-packages)
             INSTALL_EXTERNAL=1
             echo_info "Will install external packages"
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 13ea4b94eedc24446bb5d820c8ac7a0ef1827a0c..8f55024ef45ab7e3b802b6d88fe0ba8b12a1ac0d 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -82,6 +82,12 @@ unsigned short config_frames[4] = {2,9,11,13};
 #include "openair2/E1AP/e1ap_common.h"
 #include "openair2/E1AP/e1ap_api.h"
 
+#ifdef E2_AGENT
+#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
+#include "openair2/E2AP/RAN_FUNCTION/init_ran_func.h"
+#endif
+
+
 pthread_cond_t nfapi_sync_cond;
 pthread_mutex_t nfapi_sync_mutex;
 int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -683,6 +689,53 @@ int main( int argc, char **argv ) {
 
   config_sync_var=0;
 
+
+
+
+#ifdef E2_AGENT
+
+//////////////////////////////////
+//////////////////////////////////
+//// Init the E2 Agent
+ 
+  sm_io_ag_ran_t io = init_ran_func_ag();
+  fr_args_t args = init_fr_args(0, NULL);
+  
+  // OAI Wrapper 
+  e2_agent_args_t oai_args = RCconfig_NR_E2agent();
+  if(oai_args.sm_dir != NULL)
+    memcpy(args.libs_dir, oai_args.sm_dir, 128);
+
+  sleep(1);
+  const gNB_RRC_INST* rrc = RC.nrrrc[0];
+  assert(rrc != NULL && "rrc cannot be NULL");
+
+  const int mcc = rrc->configuration.mcc[0];
+  const int mnc = rrc->configuration.mnc[0];
+  const int mnc_digit_len = rrc->configuration.mnc_digit_length[0];
+  const ngran_node_t node_type = rrc->node_type;
+  int nb_id = 0;
+  int cu_du_id = 0;
+  if (node_type == ngran_gNB) {
+    nb_id = rrc->configuration.cell_identity;
+  } else if (node_type == ngran_gNB_DU) {
+    cu_du_id = rrc->node_id + 1; // Hack to avoid been 0
+    nb_id = rrc->configuration.cell_identity;
+  } else if (node_type == ngran_gNB_CU) {
+    cu_du_id = rrc->node_id + 1;
+    nb_id = rrc->configuration.cell_identity;
+  } else {
+    LOG_E(NR_RRC, "not supported ran type detect\n");
+  }
+     
+  printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
+
+  init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
+//   }
+
+#endif // E2_AGENT
+
+
   if (NFAPI_MODE==NFAPI_MODE_PNF) {
     wait_nfapi_init("main?");
   }
diff --git a/openair2/E2AP/CMakeLists.txt b/openair2/E2AP/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..865eac5ffaee16c8459ef246efa69b676816e6c6
--- /dev/null
+++ b/openair2/E2AP/CMakeLists.txt
@@ -0,0 +1,98 @@
+# Check that the submodule exists or init+update if not 
+if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt)
+  message(STATUS "E2AP submoduled not detected, therefore $git submodule init && git submodule update.")
+  execute_process(COMMAND git submodule init)
+  execute_process(COMMAND git submodule update) 
+else()
+  message(STATUS "E2AP submodule detected.")
+endif()
+
+if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/flexric/CMakeLists.txt)
+  message(FATAL_ERROR "The submodules for E2 agent were not downloaded!")
+endif()
+
+
+set(BUILDING_LIBRARY "STATIC" CACHE STRING "Static or dynamic library")
+set_property(CACHE BUILDING_LIBRARY PROPERTY STRINGS "STATIC" "DYNAMIC")
+message(STATUS "Selected LIBRARY TYPE: ${BUILDING_LIBRARY}")
+
+
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+if(BUILDING_LIBRARY STREQUAL "STATIC")
+  add_compile_options("-W;-Wall;-Wextra;-g;-Wno-unused-result;")
+elseif(BUILDING_LIBRARY STREQUAL "DYNAMIC")
+  # -fPIC flag
+  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+  add_compile_options("-W;-Wall;-Wextra;-g")
+else()
+  message(FATAL_ERROR "Unknown building type. Either choose a static or a dynamic library")
+endif()
+
+
+set(E2AP_ENCODING "ASN" CACHE STRING "The E2AP encoding to use")
+set_property(CACHE E2AP_ENCODING PROPERTY STRINGS "ASN" "FLATBUFFERS")
+message(STATUS "Selected E2AP_ENCODING: ${E2AP_ENCODING}")
+
+
+#######
+## Service Models 
+#######
+
+add_definitions(-DSERVICE_MODEL_DIR_PATH="${SM_DIR_PATH}/")
+
+# KPM service Model encoding definitions
+set(SM_ENCODING_KPM "ASN" CACHE STRING "The KPM SM encoding to use")
+set_property(CACHE SM_ENCODING_KPM PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected KPM SM_ENCODING: ${SM_ENCODING_KPM}")
+
+# RC service Model encoding definitions
+set(SM_ENCODING_RC "ASN" CACHE STRING "The RC SM encoding to use")
+set_property(CACHE SM_ENCODING_RC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected RC SM_ENCODING: ${SM_ENCODING_RC}")
+
+# MAC Service Model
+set(SM_ENCODING_MAC "PLAIN" CACHE STRING "The MAC SM encoding to use")
+set_property(CACHE SM_ENCODING_MAC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected MAC SM_ENCODING: ${SM_ENCODING_MAC}")
+
+# RLC Service Model
+set(SM_ENCODING_RLC "PLAIN" CACHE STRING "The RLC SM encoding to use")
+set_property(CACHE SM_ENCODING_RLC PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected RLC SM_ENCODING: ${SM_ENCODING_RLC}")
+
+# PDCP Service Model
+set(SM_ENCODING_PDCP "PLAIN" CACHE STRING "The PDCP SM encoding to use")
+set_property(CACHE SM_ENCODING_PDCP PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected PDCP SM_ENCODING: ${SM_ENCODING_PDCP}")
+
+# SLICE Service Model
+set(SM_ENCODING_SLICE "PLAIN" CACHE STRING "The SLICE SM encoding to use")
+set_property(CACHE SM_ENCODING_SLICE PROPERTY STRINGS "PLAIN" "ASN" "FLATBUFFERS")
+message(STATUS "Selected SLICE SM_ENCODING: ${SM_ENCODING_SLICE}")
+
+# GTP Service Model
+set(SM_ENCODING_GTP "PLAIN" CACHE STRING "The GTP SM encoding to use")
+set_property(CACHE SM_ENCODING_GTP PROPERTY STRINGS "PLAIN")
+message(STATUS "Selected GTP SM_ENCODING: ${SM_ENCODING_GTP}")
+
+########
+### Flatbuffer 
+########
+set(FlatCC_INCLUDE_DIR "" CACHE STRING "The Flatbuffers include directory")
+set(FlatCC_LIB_DIR "" CACHE STRING "The Flatbuffers lib directory")
+
+if(E2AP_ENCODING STREQUAL "FLATBUFFERS")
+  find_library(FlatCC
+    NAMES flatccrt_d
+    HINTS ${FlatCC_LIB_DIR} 
+    )
+endif()
+
+include_directories(flexric/src)
+add_subdirectory(flexric/src/agent)
+add_subdirectory(flexric/src/lib)
+add_subdirectory(flexric/src/sm)
+add_subdirectory(flexric/src/util)
+add_subdirectory(RAN_FUNCTION)
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ef92ddb0be1239ed4518c81d3b907ecaa4db08f3
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_subdirectory(CUSTOMIZED)
+add_subdirectory(O-RAN)
+
+add_library(e2_ran_func STATIC 
+          init_ran_func.c
+          )
+
+target_link_libraries(e2_ran_func   
+                       PUBLIC  
+                       e2_ran_func_cust 
+                       e2_ran_func_oran 
+                       ) 
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b165e1589b763c20576026e42e7cf2e1ef68e0ba
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_library(e2_ran_func_cust STATIC 
+          ran_func_gtp.c
+          ran_func_mac.c
+          ran_func_pdcp.c
+          ran_func_rlc.c
+          ran_func_slice.c
+          ran_func_tc.c
+          # For testing purposes 
+  ../../flexric/test/rnd/fill_rnd_data_gtp.c             
+  ../../flexric/test/rnd/fill_rnd_data_tc.c              
+  ../../flexric/test/rnd/fill_rnd_data_mac.c             
+  ../../flexric/test/rnd/fill_rnd_data_rlc.c             
+  ../../flexric/test/rnd/fill_rnd_data_pdcp.c  
+  ../../flexric/test/rnd/fill_rnd_data_slice.c           
+  ../../flexric/src/util/time_now_us.c
+          )
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd8b8b5881f52a8a48582e1eb0872e3f543836d2
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c
@@ -0,0 +1,24 @@
+#include "ran_func_gtp.h"
+#include "../../flexric/test/rnd/fill_rnd_data_gtp.h"
+#include <assert.h>
+
+void read_gtp_sm(void * data)
+{
+  assert(data != NULL);
+
+  gtp_ind_data_t* gtp = (gtp_ind_data_t*)(data);
+  fill_gtp_ind_data(gtp);
+}
+
+void read_gtp_setup_sm(void* data)
+{
+  assert(data != NULL);
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_gtp_sm(void const* src)
+{
+  assert(src != NULL);
+  assert(0 !=0 && "Not supported");
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e882004010e53b052a3ee57f36487db32d52dfa
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_gtp_sm(void*);
+
+void read_gtp_setup_sm(void*);
+
+sm_ag_if_ans_t write_ctrl_gtp_sm(void const*);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b150e71ed49e962492881c7c5bf7f6c8374f241
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c
@@ -0,0 +1,24 @@
+#include "ran_func_mac.h"
+#include "../../flexric/test/rnd/fill_rnd_data_mac.h"
+#include <assert.h>
+
+void read_mac_sm(void* data)
+{
+  assert(data != NULL);
+
+  mac_ind_data_t* mac = (mac_ind_data_t*)data;
+  fill_mac_ind_data(mac);
+}
+
+void read_mac_setup_sm(void* data)
+{
+  assert(data != NULL);
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_mac_sm(void const* data)
+{
+  assert(data != NULL);
+  assert(0 !=0 && "Not supported");
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h
new file mode 100644
index 0000000000000000000000000000000000000000..26ae184b37c5b021aca63033a8472d491c682fb9
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h
@@ -0,0 +1,12 @@
+#ifndef SM_MAC_READ_WRITE_AGENT_H
+#define SM_MAC_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_mac_sm(void*);
+
+void read_mac_setup_sm(void*);
+
+sm_ag_if_ans_t write_ctrl_mac_sm(void const*);
+
+#endif
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c
new file mode 100644
index 0000000000000000000000000000000000000000..14bb2400f7612b01bd73d7b838c153a9d55592f3
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c
@@ -0,0 +1,31 @@
+#include "ran_func_pdcp.h"
+#include "../../flexric/test/rnd/fill_rnd_data_pdcp.h"
+#include <assert.h>
+
+void read_pdcp_sm(void* data)
+{
+  assert(data != NULL);
+  //assert(data->type == PDCP_STATS_V0);
+
+  pdcp_ind_data_t* pdcp = (pdcp_ind_data_t*)data;
+  fill_pdcp_ind_data(pdcp);
+}
+
+void read_pdcp_setup_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == PDCP_AGENT_IF_E2_SETUP_ANS_V0 );
+
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data)
+{
+  assert(data != NULL);
+//  assert(data->type == PDCP_CTRL_REQ_V0 );
+  assert(0 !=0 && "Not supported");
+  sm_ag_if_ans_t ans = {0};
+  return ans;
+}
+
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h
new file mode 100644
index 0000000000000000000000000000000000000000..12dcaaf16b50147db6f26410e79cae321d7e631f
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_pdcp_sm(void*);
+
+void read_pdcp_setup_sm(void* data);
+
+sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a2a661175c559913999b7917ccc68e6dd69fdf5
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c
@@ -0,0 +1,25 @@
+#include "ran_func_rlc.h"
+#include "../../flexric/test/rnd/fill_rnd_data_rlc.h"
+
+void read_rlc_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type ==  RLC_STATS_V0);
+
+  rlc_ind_data_t* rlc = (rlc_ind_data_t*)data;
+  fill_rlc_ind_data(rlc);
+}
+
+void read_rlc_setup_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == RLC_AGENT_IF_E2_SETUP_ANS_V0 );
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data)
+{
+  (void)data;
+  assert(0!=0 && "Not supported");
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h
new file mode 100644
index 0000000000000000000000000000000000000000..c442cd7825209fa8e480a7605c860511f80f3251
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_rlc_sm(void*);
+
+void read_rlc_setup_sm(void* data);
+
+sm_ag_if_ans_t write_ctrl_rlc_sm(void const* data);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c
new file mode 100644
index 0000000000000000000000000000000000000000..764cddf28fccd3b8c35fd630193d681e0987a8ad
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c
@@ -0,0 +1,47 @@
+#include "ran_func_slice.h"
+#include "../../flexric/test/rnd/fill_rnd_data_slice.h"
+#include <assert.h>
+#include <stdio.h>
+
+void read_slice_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == SLICE_STATS_V0);
+
+  slice_ind_data_t* slice = (slice_ind_data_t*)data;
+  fill_slice_ind_data(slice);
+}
+
+void read_slice_setup_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == SLICE_AGENT_IF_E2_SETUP_ANS_V0 );
+
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_slice_sm(void const* data)
+{
+  assert(data != NULL);
+//  assert(data->type == SLICE_CTRL_REQ_V0);
+
+  slice_ctrl_req_data_t const* slice_req_ctrl = (slice_ctrl_req_data_t const* )data; // &data->slice_req_ctrl;
+  slice_ctrl_msg_t const* msg = &slice_req_ctrl->msg;
+
+  if(msg->type == SLICE_CTRL_SM_V0_ADD){
+    printf("[E2 Agent]: SLICE CONTROL ADD rx\n");
+  } else if (msg->type == SLICE_CTRL_SM_V0_DEL){
+    printf("[E2 Agent]: SLICE CONTROL DEL rx\n");
+  } else if (msg->type == SLICE_CTRL_SM_V0_UE_SLICE_ASSOC){
+    printf("[E2 Agent]: SLICE CONTROL ASSOC rx\n");
+  } else {
+    assert(0!=0 && "Unknown msg_type!");
+  }
+
+  sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0};
+  ans.ctrl_out.type = SLICE_AGENT_IF_CTRL_ANS_V0;
+  return ans;
+
+}
+
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c26d631207db9b1b10a84b365f584d2deec61dd
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_slice_sm(void*);
+
+void read_slice_setup_sm(void* data);
+
+sm_ag_if_ans_t write_ctrl_slice_sm(void const* data);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca3997da7b4a04f0536d5bacc17a94d6f95ec5e6
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c
@@ -0,0 +1,39 @@
+#include "ran_func_tc.h"
+#include "../../flexric/test/rnd/fill_rnd_data_tc.h"
+#include <assert.h>
+
+void read_tc_sm(void* data)
+{
+  assert(data != NULL);
+  //assert(data->type == TC_STATS_V0);
+
+  tc_ind_data_t* tc = (tc_ind_data_t*)data;
+  fill_tc_ind_data(tc);
+}
+
+void read_tc_setup_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == TC_AGENT_IF_E2_SETUP_ANS_V0 );
+
+  assert(0 !=0 && "Not supported");
+}
+
+sm_ag_if_ans_t write_ctrl_tc_sm(void const* data)
+{
+  assert(data != NULL);
+//  assert(data->type == TC_CTRL_REQ_V0 );
+
+  tc_ctrl_req_data_t const* ctrl = (tc_ctrl_req_data_t const*)data;
+
+  tc_ctrl_msg_e const t = ctrl->msg.type;
+
+  assert(t == TC_CTRL_SM_V0_CLS || t == TC_CTRL_SM_V0_PLC 
+      || t == TC_CTRL_SM_V0_QUEUE || t ==TC_CTRL_SM_V0_SCH 
+      || t == TC_CTRL_SM_V0_SHP || t == TC_CTRL_SM_V0_PCR);
+
+  sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0};
+  ans.ctrl_out.type = TC_AGENT_IF_CTRL_ANS_V0;
+  return ans;
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h
new file mode 100644
index 0000000000000000000000000000000000000000..526d564b1bb56e65718dec0384ddf3d8b714a4f6
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_tc_sm(void*);
+
+void read_tc_setup_sm(void* data);
+
+sm_ag_if_ans_t write_ctrl_tc_sm(void const* data);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..49624dc3021d076c3bda288bd8dc5eda6359fafe
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(e2_ran_func_oran STATIC 
+          ran_func_kpm.c
+          ran_func_rc.c
+          # For testing purposes 
+  ../../flexric/test/rnd/fill_rnd_data_kpm.c             
+  ../../flexric/test/rnd/fill_rnd_data_rc.c              
+          )
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..358f22a6923c9ce1b2aa5b7688e0c83b214242fb
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/README.md
@@ -0,0 +1,3 @@
+RAN Functions as defined by O-RAN
+
+
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c
new file mode 100644
index 0000000000000000000000000000000000000000..daedef70e716ebc1ede17ba826a0235a57da24de
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c
@@ -0,0 +1,189 @@
+#include "ran_func_kpm.h"
+#include "../../flexric/test/rnd/fill_rnd_data_kpm.h"
+#include "../../flexric/src/util/time_now_us.h"
+#include <assert.h>
+#include <stdio.h>
+
+static 
+gnb_e2sm_t fill_gnb_data(void)
+{
+  gnb_e2sm_t gnb = {0};
+
+  // 6.2.3.16
+  // Mandatory
+  // AMF UE NGAP ID
+  gnb.amf_ue_ngap_id = 112358132134; // % 2^40;
+
+  // Mandatory
+  //GUAMI 6.2.3.17 
+  gnb.guami.plmn_id = (e2sm_plmn_t) {.mcc = 505, .mnc = 1, .mnc_digit_len = 2};
+  
+  gnb.guami.amf_region_id = (rand() % 2^8) + 0;
+  gnb.guami.amf_set_id = (rand() % 2^10) + 0;
+  gnb.guami.amf_ptr = (rand() % 2^6) + 0;
+
+  return gnb;
+}
+
+static 
+ue_id_e2sm_t fill_ue_id_data(void)
+{
+  ue_id_e2sm_t ue_id_data = {0};
+
+  ue_id_data.type = GNB_UE_ID_E2SM;
+  ue_id_data.gnb = fill_gnb_data();
+
+  return ue_id_data;
+}
+
+static 
+kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(void)
+{
+  kpm_ind_msg_format_1_t msg_frm_1 = {0};
+
+  // Measurement Data
+  uint32_t num_drbs = 2;
+  msg_frm_1.meas_data_lst_len = num_drbs;  // (rand() % 65535) + 1;
+  msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst));
+  assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" );
+
+  for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++){
+    // Measurement Record
+    msg_frm_1.meas_data_lst[i].meas_record_len = 1;  // (rand() % 65535) + 1;
+    msg_frm_1.meas_data_lst[i].meas_record_lst = calloc(msg_frm_1.meas_data_lst[i].meas_record_len, sizeof(meas_record_lst_t));
+    assert(msg_frm_1.meas_data_lst[i].meas_record_lst != NULL && "Memory exhausted" );
+
+    for (size_t j = 0; j < msg_frm_1.meas_data_lst[i].meas_record_len; j++){
+      msg_frm_1.meas_data_lst[i].meas_record_lst[j].value = REAL_MEAS_VALUE; // rand()%END_MEAS_VALUE;
+      msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = (rand() % 256) + 0.1;
+    }
+  }
+
+  // Measurement Information - OPTIONAL
+  msg_frm_1.meas_info_lst_len = num_drbs;
+  msg_frm_1.meas_info_lst = calloc(msg_frm_1.meas_info_lst_len, sizeof(meas_info_format_1_lst_t));
+  assert(msg_frm_1.meas_info_lst != NULL && "Memory exhausted" );
+
+  for (size_t i = 0; i < msg_frm_1.meas_info_lst_len; i++) {
+    // Measurement Type
+    msg_frm_1.meas_info_lst[i].meas_type.type = ID_MEAS_TYPE; 
+    // DRB ID
+    msg_frm_1.meas_info_lst[i].meas_type.id = i;
+
+    // Label Information
+    msg_frm_1.meas_info_lst[i].label_info_lst_len = 1;
+    msg_frm_1.meas_info_lst[i].label_info_lst = calloc(msg_frm_1.meas_info_lst[i].label_info_lst_len, sizeof(label_info_lst_t));
+    assert(msg_frm_1.meas_info_lst[i].label_info_lst != NULL && "Memory exhausted" );
+
+    for (size_t j = 0; j < msg_frm_1.meas_info_lst[i].label_info_lst_len; j++) {
+      msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = malloc(sizeof(enum_value_e));
+      *msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = TRUE_ENUM_VALUE;
+    }
+  }
+
+  return msg_frm_1;
+}
+
+static 
+kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_sta(void)
+{
+  kpm_ind_msg_format_3_t msg_frm_3 = {0};
+
+  uint32_t num_ues = 1;
+  msg_frm_3.ue_meas_report_lst_len = num_ues;  // (rand() % 65535) + 1;
+
+  msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t));
+  assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted");
+
+  for (size_t i = 0; i < msg_frm_3.ue_meas_report_lst_len; i++)
+  {
+    msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data();
+    msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1();
+  }
+
+  return msg_frm_3;
+}
+
+static 
+kpm_ric_ind_hdr_format_1_t fill_kpm_ind_hdr_frm_1(void)
+{
+  kpm_ric_ind_hdr_format_1_t hdr_frm_1 = {0};
+
+  hdr_frm_1.collectStartTime = time_now_us();
+  
+  hdr_frm_1.fileformat_version = NULL;
+  
+  hdr_frm_1.sender_name = calloc(1, sizeof(byte_array_t));
+  hdr_frm_1.sender_name->buf = calloc(strlen("My OAI-MONO") + 1, sizeof(char));
+  memcpy(hdr_frm_1.sender_name->buf, "My OAI-MONO", strlen("My OAI-MONO"));
+  hdr_frm_1.sender_name->len = strlen("My OAI-MONO");
+  
+  hdr_frm_1.sender_type = calloc(1, sizeof(byte_array_t));
+  hdr_frm_1.sender_type->buf = calloc(strlen("MONO") + 1, sizeof(char));
+  memcpy(hdr_frm_1.sender_type->buf, "MONO", strlen("MONO"));
+  hdr_frm_1.sender_type->len = strlen("MONO");
+  
+  hdr_frm_1.vendor_name = calloc(1, sizeof(byte_array_t));
+  hdr_frm_1.vendor_name->buf = calloc(strlen("OAI") + 1, sizeof(char));
+  memcpy(hdr_frm_1.vendor_name->buf, "OAI", strlen("OAI"));
+  hdr_frm_1.vendor_name->len = strlen("OAI");
+
+  return hdr_frm_1;
+}
+
+static
+kpm_ind_hdr_t fill_kpm_ind_hdr_sta(void)
+{
+  kpm_ind_hdr_t hdr = {0};
+
+  hdr.type = FORMAT_1_INDICATION_HEADER;
+  hdr.kpm_ric_ind_hdr_format_1 = fill_kpm_ind_hdr_frm_1();
+
+  return hdr;
+}
+
+void read_kpm_sm(void* data)
+{
+  assert(data != NULL);
+  //assert(data->type == KPM_STATS_V3_0);
+
+  kpm_rd_ind_data_t* kpm = (kpm_rd_ind_data_t*)data;
+
+  assert(kpm->act_def!= NULL && "Cannot be NULL");
+  if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){
+
+    if(kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond_type == CQI_TEST_COND_TYPE
+        && *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond == GREATERTHAN_TEST_COND){
+      printf("Matching condition: UEs with CQI greater than %ld \n", *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.int_value );
+    }
+
+    printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst->meas_type.name.buf); 
+
+    kpm->ind.hdr = fill_kpm_ind_hdr_sta(); 
+    // 7.8 Supported RIC Styles and E2SM IE Formats
+    // Format 4 corresponds to indication message 3
+    kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE;
+    kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_sta();
+  } else {
+     kpm->ind.hdr = fill_kpm_ind_hdr(); 
+     kpm->ind.msg = fill_kpm_ind_msg(); 
+  }
+}
+
+void read_kpm_setup_sm(void* e2ap)
+{
+  assert(e2ap != NULL);
+//  assert(e2ap->type == KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0);
+
+  kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap);
+  kpm->ran_func_def = fill_kpm_ran_func_def(); 
+}
+
+sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src)
+{
+  assert(0 !=0 && "Not supported");
+  (void)src;
+  sm_ag_if_ans_t ans = {0};
+  return ans;
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h
new file mode 100644
index 0000000000000000000000000000000000000000..cec10e06add7d9b66a051351a342547e7f86b023
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h
@@ -0,0 +1,13 @@
+#ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_kpm_sm(void*);
+
+void read_kpm_setup_sm(void*);
+
+sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c6777d5a3308355212066e65522e0e383f3ac8b
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c
@@ -0,0 +1,108 @@
+#include "ran_func_rc.h"
+#include "../../flexric/test/rnd/fill_rnd_data_rc.h"
+#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
+#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h"
+#include <assert.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void read_rc_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == RAN_CTRL_STATS_V1_03);
+  assert(0!=0 && "Not implemented");
+}
+
+void read_rc_setup_sm(void* data)
+{
+  assert(data != NULL);
+//  assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0);
+  rc_e2_setup_t* rc = (rc_e2_setup_t*)data;
+  rc->ran_func_def = fill_rc_ran_func_def();
+}
+
+sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
+{
+  assert(data != NULL);
+//  assert(data->type == RAN_CONTROL_CTRL_V1_03 );
+
+  rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data;
+  if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){
+    if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){
+      printf("QoS flow mapping configuration \n");
+      e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1;
+      for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){
+        seq_ran_param_t const* rp = frmt_1->ran_param;
+        if(rp[i].ran_param_id == 1){
+          assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE );
+          printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran);
+        } else if(rp[i].ran_param_id == 2){
+          assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE);
+          printf("List of QoS Flows to be modified \n");
+          for(size_t j = 0; j < ctrl->msg.frmt_1.ran_param[i].ran_param_val.lst->sz_lst_ran_param; ++j){ 
+            lst_ran_param_t const* lrp = rp[i].ran_param_val.lst->lst_ran_param;
+            // The following assertion should be true, but there is a bug in the std
+            // check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984 
+            // assert(lrp[j].ran_param_id == 3); 
+            assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_id == 4) ;
+            assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE);
+
+            int64_t qfi = lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran;
+            assert(qfi > -1 && qfi < 65);
+
+            assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_id == 5);
+            assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE);
+            int64_t dir = lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran;
+            assert(dir == 0 || dir == 1);
+            printf("qfi = %ld dir %ld \n", qfi, dir);
+          }
+        } 
+      }
+    }
+  }
+
+  sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0};
+  ans.ctrl_out.type = RAN_CTRL_V1_3_AGENT_IF_CTRL_ANS_V0;
+  return ans;
+}
+
+static
+void* emulate_rrc_msg(void* ptr)
+{
+  uint32_t* ric_id = (uint32_t*)ptr; 
+  for(size_t i = 0; i < 5; ++i){
+    usleep(rand()%4000);
+    rc_ind_data_t* d = calloc(1, sizeof(rc_ind_data_t)); 
+    assert(d != NULL && "Memory exhausted");
+    *d = fill_rnd_rc_ind_data();
+    async_event_agent_api(*ric_id, d);
+    printf("Event for RIC Req ID %u generated\n", *ric_id);
+  }
+
+  free(ptr);
+  return NULL;
+}
+
+static
+pthread_t t_ran_ctrl;
+
+sm_ag_if_ans_t write_subs_rc_sm(void const* src)
+{
+  assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03);
+
+  wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src;
+  printf("ric req id %d \n", wr_rc->ric_req_id);
+
+  uint32_t* ptr = malloc(sizeof(uint32_t));
+  assert(ptr != NULL);
+  *ptr = wr_rc->ric_req_id;
+
+  int rc = pthread_create(&t_ran_ctrl, NULL, emulate_rrc_msg, ptr);
+  assert(rc == 0);
+
+  sm_ag_if_ans_t ans = {0}; 
+
+  return ans;
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h
new file mode 100644
index 0000000000000000000000000000000000000000..64f11c8068d3c983e2028cb2fea5da8990eef89f
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h
@@ -0,0 +1,15 @@
+#ifndef RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H
+#define RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H
+
+#include "../../flexric/src/agent/e2_agent_api.h"
+
+void read_rc_sm(void *);
+
+void read_rc_setup_sm(void* data);
+
+sm_ag_if_ans_t write_ctrl_rc_sm(void const* data);
+
+sm_ag_if_ans_t write_subs_rc_sm(void const* src);
+
+#endif
+
diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc60d139dec79b3b20a8e6a6e97d5f517b7b956f
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c
@@ -0,0 +1,73 @@
+#include "init_ran_func.h"
+#include "../flexric/src/agent/e2_agent_api.h"
+#include "CUSTOMIZED/ran_func_mac.h"
+#include "CUSTOMIZED/ran_func_rlc.h"
+#include "CUSTOMIZED/ran_func_pdcp.h"
+#include "CUSTOMIZED/ran_func_slice.h"
+#include "CUSTOMIZED/ran_func_tc.h"
+#include "CUSTOMIZED/ran_func_gtp.h"
+#include "O-RAN/ran_func_kpm.h"
+#include "O-RAN/ran_func_rc.h"
+
+static
+void init_read_ind_tbl(read_ind_fp (*read_ind_tbl)[SM_AGENT_IF_READ_V0_END])
+{
+  (*read_ind_tbl)[MAC_STATS_V0] =  read_mac_sm;
+  (*read_ind_tbl)[RLC_STATS_V0] =  read_rlc_sm ;
+  (*read_ind_tbl)[PDCP_STATS_V0] = read_pdcp_sm ;
+  (*read_ind_tbl)[SLICE_STATS_V0] = read_slice_sm ;
+  (*read_ind_tbl)[TC_STATS_V0] = read_tc_sm ;
+  (*read_ind_tbl)[GTP_STATS_V0] = read_gtp_sm ; 
+  (*read_ind_tbl)[KPM_STATS_V3_0] = read_kpm_sm ; 
+  (*read_ind_tbl)[RAN_CTRL_STATS_V1_03] = read_rc_sm;
+}
+
+static
+void init_read_setup_tbl(read_e2_setup_fp (*read_setup_tbl)[SM_AGENT_IF_E2_SETUP_ANS_V0_END])
+{
+  (*read_setup_tbl)[MAC_AGENT_IF_E2_SETUP_ANS_V0] =  read_mac_setup_sm;
+  (*read_setup_tbl)[RLC_AGENT_IF_E2_SETUP_ANS_V0] =  read_rlc_setup_sm ;
+  (*read_setup_tbl)[PDCP_AGENT_IF_E2_SETUP_ANS_V0] = read_pdcp_setup_sm ;
+  (*read_setup_tbl)[SLICE_AGENT_IF_E2_SETUP_ANS_V0] =  read_slice_setup_sm ;
+  (*read_setup_tbl)[TC_AGENT_IF_E2_SETUP_ANS_V0] =  read_tc_setup_sm ;
+  (*read_setup_tbl)[GTP_AGENT_IF_E2_SETUP_ANS_V0] = read_gtp_setup_sm ; 
+  (*read_setup_tbl)[KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0] = read_kpm_setup_sm ; 
+  (*read_setup_tbl)[RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0] = read_rc_setup_sm;
+}
+
+static
+void init_write_ctrl( write_ctrl_fp (*write_ctrl_tbl)[SM_AGENT_IF_WRITE_CTRL_V0_END])
+{
+  (*write_ctrl_tbl)[MAC_CTRL_REQ_V0] = write_ctrl_mac_sm;
+  (*write_ctrl_tbl)[RLC_CTRL_REQ_V0] = write_ctrl_rlc_sm;
+  (*write_ctrl_tbl)[PDCP_CTRL_REQ_V0] = write_ctrl_pdcp_sm;
+  (*write_ctrl_tbl)[SLICE_CTRL_REQ_V0] = write_ctrl_slice_sm;
+  (*write_ctrl_tbl)[TC_CTRL_REQ_V0] = write_ctrl_tc_sm;
+  (*write_ctrl_tbl)[GTP_CTRL_REQ_V0] = write_ctrl_gtp_sm;
+  (*write_ctrl_tbl)[RAN_CONTROL_CTRL_V1_03] = write_ctrl_rc_sm;
+}
+
+static
+void init_write_subs(write_subs_fp (*write_subs_tbl)[SM_AGENT_IF_WRITE_SUBS_V0_END])
+{
+  (*write_subs_tbl)[MAC_SUBS_V0] = NULL;
+  (*write_subs_tbl)[RLC_SUBS_V0] = NULL;
+  (*write_subs_tbl)[PDCP_SUBS_V0] = NULL;
+  (*write_subs_tbl)[SLICE_SUBS_V0] = NULL;
+  (*write_subs_tbl)[TC_SUBS_V0] = NULL;
+  (*write_subs_tbl)[GTP_SUBS_V0] = NULL;
+  (*write_subs_tbl)[KPM_SUBS_V3_0] = NULL;
+  (*write_subs_tbl)[RAN_CTRL_SUBS_V1_03] = write_subs_rc_sm;
+}
+
+sm_io_ag_ran_t init_ran_func_ag(void)
+{
+  sm_io_ag_ran_t io = {0};
+  init_read_ind_tbl(&io.read_ind_tbl);
+  init_read_setup_tbl(&io.read_setup_tbl);
+  init_write_ctrl(&io.write_ctrl_tbl);
+  init_write_subs(&io.write_subs_tbl);
+
+  return io;
+}
+
diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.h b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b7d10f506fdff85554203e4399e0d85954f10c2
--- /dev/null
+++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.h
@@ -0,0 +1,32 @@
+/*
+ * 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:
+ *      contact@openairinterface.org
+ */
+
+
+
+#ifndef RAN_FUNC_INIT_E2_H
+#define RAN_FUNC_INIT_E2_H 
+
+#include "../flexric/src/sm/sm_io.h"
+
+sm_io_ag_ran_t init_ran_func_ag(void);
+
+#endif
+
diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ce8bf0dd7a1644bd721bdd8dea5b676f9b80e668
--- /dev/null
+++ b/openair2/E2AP/README.md
@@ -0,0 +1,153 @@
+<h1 align="center">
+    <a href="https://openairinterface.org/"><img src="https://openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png" alt="OAI" width="550"></a>
+</h1>
+
+<p align="center">
+    <a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-OAI--Public--V1.1-blue" alt="License"></a>
+    <a href="https://releases.ubuntu.com/18.04/"><img src="https://img.shields.io/badge/OS-Ubuntu18-Green" alt="Supported OS Ubuntu 18"></a>
+    <a href="https://releases.ubuntu.com/20.04/"><img src="https://img.shields.io/badge/OS-Ubuntu20-Green" alt="Supported OS Ubuntu 20"></a>
+    <a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
+    <a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL8-Green" alt="Supported OS RHEL8"></a>
+    <a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RELH9"></a>
+    <a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore37-Green" alt="Supported OS Fedora 37"></a>
+</p>
+
+<p align="center">
+    <a href="https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins-oai.eurecom.fr%2Fjob%2FRAN-Container-Parent%2F&label=build%20Images"></a>
+</p>
+
+<p align="center">
+  <a href="https://hub.docker.com/r/oaisoftwarealliance/oai-gnb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-gnb?label=gNB%20docker%20pulls"></a>
+  <a href="https://hub.docker.com/r/oaisoftwarealliance/oai-nr-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-nr-ue?label=NR-UE%20docker%20pulls"></a>
+  <a href="https://hub.docker.com/r/oaisoftwarealliance/oai-enb"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-enb?label=eNB%20docker%20pulls"></a>
+  <a href="https://hub.docker.com/r/oaisoftwarealliance/oai-lte-ue"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/oaisoftwarealliance/oai-lte-ue?label=LTE-UE%20docker%20pulls"></a>
+</p>
+
+
+
+# OpenAirInterface License #
+
+ *  [OAI License Model](http://www.openairinterface.org/?page_id=101)
+ *  [OAI License v1.1 on our website](http://www.openairinterface.org/?page_id=698)
+
+It is distributed under **OAI Public License V1.1**.
+
+The license information is distributed under [LICENSE](LICENSE) file in the same directory.
+
+Please see [NOTICE](NOTICE.md) file for third party software that is included in the sources.
+
+# Overview
+
+This tutorial describes the steps of deployment 5G OAI RAN, with integrated E2 agent, with FlexRIC, O-RAN compliant nearRT-RIC.
+
+# 1. Installation
+
+## 1.1 Install prerequisites
+
+- A *recent* CMake (at least v3.15). 
+
+  On Ubuntu, you might want to use [this PPA](https://apt.kitware.com/) to install an up-to-date version.
+
+- SWIG (at least  v.4.0). 
+
+  We use SWIG as an interface generator to enable the multi-language feature (i.e., C/C++ and Python) for the xApps. Please, check your SWIG version (i.e, `swig
+  -version`) and install it from scratch if necessary as described here: https://swig.org/svn.html or via the code below: 
+  
+  ```bash
+  git clone https://github.com/swig/swig.git
+  cd swig
+  ./autogen.sh
+  ./configure --prefix=/usr/
+  make
+  make install
+  ```
+
+- Flatbuffer encoding(optional). 
+  
+  We also provide a flatbuffers encoding/decoding scheme as alternative to ASN.1. In case that you want to use it  follow the
+  instructions at https://github.com/dvidelabs/flatcc and provide the path for the lib and include when selecting it at `ccmake ..` from the build directory 
+
+## 1.2 Download the required dependencies. 
+
+Below an example of how to install it in ubuntu
+```bash
+sudo apt install libsctp-dev python3.8 cmake-curses-gui libpcre2-dev python-dev
+```
+
+# 2. Deployment
+
+## 2.1 OAI RAN
+
+### 2.1.1 Clone the OAI repository
+```bash
+git clone https://gitlab.eurecom.fr/oai/openairinterface5g oai
+cd oai/
+```
+
+### 2.1.2 Build OAI
+```bash
+cd cmake_targets/
+./build_oai -I -w SIMU --gNB --nrUE --build-e2 --ninja
+```
+If the flexric folder is empty, try manually the following commands
+
+```bash
+git submodule init
+git submodule update
+```
+
+ * -I option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed.
+ * -w option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from liboai_device.so to the true device which will be used at run-time (here the USRP one, liboai_usrpdevif.so). The RF simulatorRF simulator is implemented as a specific device replacing RF hardware, it can be specifically built using -w SIMU option, but is also built during any softmodem build.
+ * --gNB is to build the nr-softmodem and nr-cuup executables and all required shared libraries
+ * --nrUE is to build the nr-uesoftmodem executable and all required shared libraries
+ * --ninja is to use the ninja build tool, which speeds up compilation
+ * --build-e2 option is to use the E2 agent, integrated within gNB.
+
+## 2.2 FlexRIC
+
+### 2.2.1 Clone the FlexRIC repository
+```bash
+git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
+cd flexric/
+git checkout mir_dev
+```
+
+### 2.2.2 Build FlexRIC
+```bash
+mkdir build && cd build && cmake .. && make
+```
+
+### 2.2.3 Installation of Service Models (SMs)
+```bash
+sudo make install
+```
+
+By default the service model libraries will be installed in the path /usr/local/lib/flexric while the configuration file in `/usr/local/etc/flexric`.
+
+ * Note: currently, only xApp KPM v03.00 and RC v01.03 (xapp_kpm_rc) is supported to communicate with the integrated E2 agent in OAI. If you are interested in custom SMs (MAC, RLC, PDCP, GTP, TC and SLICE), please follow the instructions at https://gitlab.eurecom.fr/mosaic5g/flexric.
+
+# 3. Start the process
+
+* start the gNB
+```bash
+cd oai/cmake_targets/ran_build/build
+sudo ./nr-softmodem RFSIMULATOR=server -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa
+```
+
+* start the nrUE
+```bash
+cd oai/cmake_targets/ran_build/build
+sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001
+```
+
+* start the nearRT-RIC
+```bash
+cd flexric
+./build/examples/ric/nearRT-RIC
+```
+
+* start the KPM+RC xApp
+```bash
+cd flexric
+./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
+```
diff --git a/openair2/E2AP/e2_agent_arg.h b/openair2/E2AP/e2_agent_arg.h
new file mode 100644
index 0000000000000000000000000000000000000000..b719c32d97e0ac413031646e6521397885eac6fa
--- /dev/null
+++ b/openair2/E2AP/e2_agent_arg.h
@@ -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:
+ *      contact@openairinterface.org
+ */
+
+#ifndef E2_AGENT_ARGS_H
+#define E2_AGENT_ARGS_H
+
+#include <stdint.h>
+
+// Wrapper for OAI
+typedef struct{
+  const char *ip;
+  const char *sm_dir;
+} e2_agent_args_t;
+
+#endif
+
+
diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric
new file mode 160000
index 0000000000000000000000000000000000000000..ef00d05a3f673d04bbc003f4ae479ead467bd8ea
--- /dev/null
+++ b/openair2/E2AP/flexric
@@ -0,0 +1 @@
+Subproject commit ef00d05a3f673d04bbc003f4ae479ead467bd8ea
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 26606a9c5c48aaea7707ff9a53dd58f38b971d1c..b05dcf4f7681a1118d03f08606caf5581ddd47fe 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -2929,3 +2929,25 @@ void read_config_and_init(void) {
     RCconfig_RRC(enb_id, RC.rrc[enb_id]);
   }
 }
+
+#ifdef E2_AGENT
+
+e2_agent_args_t RCconfig_E2agent(void)
+{
+  paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC;
+  int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT);
+  if (ret < 0) {
+    LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT);
+    return (e2_agent_args_t) {0}; 
+  }
+  return (e2_agent_args_t) {
+    .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr,
+    .port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr,
+    .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr,
+  };
+}
+
+
+#endif
+
+
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 67b4fb45e70258b39230e8c77b7c01e5a8bdfae7..5abb7df2c976d5ad5a65cd981b3eada1eda13a9d 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -116,6 +116,11 @@ void read_config_and_init(void);
 int RCconfig_X2(MessageDef *msg_p, uint32_t i);
 int RCconfig_M2(MessageDef *msg_p, uint32_t i);
 
+#ifdef E2_AGENT
+#include "openair2/E2AP/e2_agent_arg.h"
+e2_agent_args_t RCconfig_E2agent(void);
+#endif
+
 void fill_SL_configuration(RrcConfigurationReq *RRCcfg, ccparams_sidelink_t *SLconfig, int cell_idx, int cc_idx, char *config_fname);
 void fill_eMTC_configuration(RrcConfigurationReq *RRCcfg, ccparams_eMTC_t *eMTCconfig, int cell_idx, int cc_idx, char *config_fname, char *brparamspath);
 
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index e37c5388d01ad992dd434cdccf32965dc9610b41..34fcc6ad2ca91f64fdf145c63aa198c80c9e21d7 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -1317,6 +1317,35 @@ typedef struct srb1_params_s {
 #define CONFIG_HLP_PARALLEL                        "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n"
 /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 
+#ifdef E2_AGENT
+
+/* E2 Agent configuration */
+#define CONFIG_STRING_E2AGENT "e2_agent"
+
+#define E2AGENT_CONFIG_IP    "ip"
+//#define E2AGENT_CONFIG_PORT  "port"
+#define E2AGENT_CONFIG_SMDIR "sm_dir"
+
+static const char* const e2agent_config_ip_default = NULL;
+static const char* const e2agent_config_smdir_default = NULL;
+//static const uint16_t e2agent_config_port_default = 36421;
+
+#define E2AGENT_PARAMS_DESC { \
+  {E2AGENT_CONFIG_IP,    "RIC IP address",             0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default,    TYPE_STRING, 0}, \
+  {E2AGENT_CONFIG_SMDIR, "Directory with SMs to load", 0, strptr:NULL, defstrval:(char*)e2agent_config_smdir_default, TYPE_STRING, 0}, \
+}
+/*
+//  {E2AGENT_CONFIG_PORT,  "RIC port",                   0, u16ptr:NULL, defuintval:e2agent_config_port_default,        TYPE_UINT16, 0}, \
+}
+*/
+
+#define E2AGENT_CONFIG_IP_IDX    0
+#define E2AGENT_CONFIG_SMDIR_IDX 1
+//#define E2AGENT_CONFIG_PORT_IDX  2
+
+#endif // E2_AGENT
+
+
 #include "enb_paramdef_emtc.h"
 #include "enb_paramdef_sidelink.h"
 #include "enb_paramdef_mce.h"
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 9db7cc50675eeb13789c2bd62a916b600bc51b56..87f2c07d2110ba1e6824dcd5e915dab8a4857bec 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -2259,3 +2259,23 @@ void nr_read_config_and_init(void) {
     nr_pdcp_layer_init();
   }
 }
+
+#ifdef E2_AGENT
+
+e2_agent_args_t RCconfig_NR_E2agent(void)
+{
+  paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC;
+  int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT);
+  if (ret < 0) {
+    LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT);
+    return (e2_agent_args_t) { 0 };
+  }
+  e2_agent_args_t dst = {0};
+  if(e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL)
+    dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr;
+  if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL)
+    dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr;
+  return dst;
+}
+
+#endif // E2_AGENT
diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h
index 3089753cff30236714f9550a7b166b174fcfa34a..0a23ebea7446dd60a6d77f2e8cadc3aa2c76233f 100644
--- a/openair2/GNB_APP/gnb_config.h
+++ b/openair2/GNB_APP/gnb_config.h
@@ -110,5 +110,10 @@ void nr_read_config_and_init(void);
 MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process);
 ngran_node_t get_node_type(void);
 
+#ifdef E2_AGENT
+#include "openair2/E2AP/e2_agent_arg.h"
+e2_agent_args_t RCconfig_NR_E2agent(void);
+#endif // E2_AGENT
+
 #endif /* GNB_CONFIG_H_ */
 /** @} */
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
index 7d5d49fe87476d1fd16a25c9577ae8f1a3ebfdf2..01210a0663f7e36956627ed01ef5ca2057e887b8 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
@@ -266,3 +266,8 @@ log_config :
   f1ap_log_level                        ="debug";
 };
 
+e2_agent = {
+  address = "127.0.0.1";
+  #sm_dir = "/path/where/the/SMs/are/located/"
+  sm_dir = "/usr/local/lib/flexric/"
+};