mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
28 Commits
microamp_E
...
e2sm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f673c16a41 | ||
|
|
9e66929379 | ||
|
|
212d698c1b | ||
|
|
51f44796f2 | ||
|
|
2924ff5303 | ||
|
|
5444a5bb21 | ||
|
|
4ede33ecc9 | ||
|
|
b61adfd371 | ||
|
|
60d0f8c848 | ||
|
|
12783daf19 | ||
|
|
9b90f7fc59 | ||
|
|
8c00136d51 | ||
|
|
4d2f021b23 | ||
|
|
24dfe9eeea | ||
|
|
4893949621 | ||
|
|
e5dc433996 | ||
|
|
4c59901503 | ||
|
|
2d1ffc196e | ||
|
|
01a22cab6f | ||
|
|
b678c19aef | ||
|
|
f681b23916 | ||
|
|
5973a62606 | ||
|
|
1cfd7ee8fb | ||
|
|
cde2fd2bf4 | ||
|
|
0e1aa4e234 | ||
|
|
65fb632c70 | ||
|
|
f2a70d7512 | ||
|
|
6108da45fe |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "openair2/E2AP/flexric"]
|
||||
path = openair2/E2AP/flexric
|
||||
url = https://gitlab.eurecom.fr/mosaic5g/flexric.git
|
||||
branch = rebased-mir-dev
|
||||
@@ -328,6 +328,65 @@ 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 E2 Agent")
|
||||
set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF")
|
||||
|
||||
if(E2_AGENT)
|
||||
set(E2AP_DIR ${OPENAIR2_DIR}/E2AP)
|
||||
add_subdirectory ("${E2AP_DIR}")
|
||||
include_directories ("${E2AP_DIR}")
|
||||
add_library(nr_e2_ran_func
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/init_ran_func.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/NR/O-RAN/ran_func_rc.c
|
||||
# For testing purposes
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_mac.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_rlc.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_pdcp.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_gtp.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_slice.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_tc.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_kpm.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_rc.c
|
||||
${E2AP_DIR}/flexric/src/util/time_now_us.c
|
||||
)
|
||||
target_link_libraries(nr_e2_ran_func PRIVATE nr_rrc asn1_nr_rrc_hdrs lte_rrc asn1_lte_rrc_hdrs)
|
||||
|
||||
add_library(e2_ran_func
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/init_ran_func.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.c
|
||||
${E2AP_DIR}/RAN_FUNCTION/LTE/O-RAN/ran_func_rc.c
|
||||
# For testing purposes
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_mac.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_rlc.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_pdcp.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_gtp.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_slice.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_tc.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_kpm.c
|
||||
${E2AP_DIR}/flexric/test/rnd/fill_rnd_data_rc.c
|
||||
${E2AP_DIR}/flexric/src/util/time_now_us.c
|
||||
)
|
||||
target_link_libraries(e2_ran_func PRIVATE nr_rrc asn1_nr_rrc_hdrs lte_rrc asn1_lte_rrc_hdrs)
|
||||
|
||||
endif()
|
||||
|
||||
##################################################
|
||||
# ASN.1 grammar C code generation & dependencies #
|
||||
##################################################
|
||||
@@ -1567,6 +1626,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 +1661,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 nr_e2_ran_func)
|
||||
target_compile_definitions(L2_NR PRIVATE E2_AGENT)
|
||||
endif()
|
||||
|
||||
|
||||
add_library(L2_LTE_NR
|
||||
${L2_RRC_SRC}
|
||||
@@ -2174,6 +2243,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 +2358,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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -43,6 +43,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
|
||||
- [How to run OAI-VNF and OAI-PNF](./RUN_NR_NFAPI.md) _Note: does not work currently_
|
||||
- [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md)
|
||||
- [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt)
|
||||
- [How to run with E2 agent](../openair2/E2AP/README.md)
|
||||
|
||||
Legacy unmaintained files:
|
||||
- `L2NFAPI_NOS1.md`, `L2NFAPI_S1.md`: old L2simulator, not valid anymore
|
||||
|
||||
@@ -52,6 +52,11 @@
|
||||
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "openair2/E2AP/RAN_FUNCTION/LTE/init_ran_func.h"
|
||||
#endif
|
||||
|
||||
#include <openair1/PHY/phy_extern_ue.h>
|
||||
|
||||
#include "PHY/phy_vars.h"
|
||||
@@ -519,6 +524,40 @@ int main ( int argc, char **argv )
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
|
||||
#ifdef E2_AGENT
|
||||
|
||||
//////////////////////////////////
|
||||
//////////////////////////////////
|
||||
//// Init the E2 Agent
|
||||
sm_io_ag_ran_t io = init_ran_func_ag();
|
||||
|
||||
// OAI Wrapper
|
||||
e2_agent_args_t oai_args = RCconfig_E2agent();
|
||||
AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} ");
|
||||
AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\"");
|
||||
|
||||
fr_args_t args = {.ip = oai_args.ip}; // init_fr_args(0, NULL);
|
||||
memcpy(args.libs_dir, oai_args.sm_dir, 128);
|
||||
|
||||
sleep(1);
|
||||
const eNB_RRC_INST* rrc = RC.rrc[0]; // mod_id = 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 = ngran_eNB;
|
||||
int nb_id = rrc->configuration.cell_identity;
|
||||
int cu_du_id = 0;
|
||||
|
||||
printf("[E2-AGENT]: mcc = %d mnc = %d mnc_digit = %d nd_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
|
||||
|
||||
bool init_agent = false;
|
||||
init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
|
||||
init_agent = true;
|
||||
|
||||
#endif // E2_AGENT
|
||||
|
||||
// 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);
|
||||
@@ -642,6 +681,10 @@ int main ( int argc, char **argv )
|
||||
LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
|
||||
// stop threads
|
||||
|
||||
#ifdef E2_AGENT
|
||||
if (init_agent) stop_agent_api();
|
||||
#endif
|
||||
|
||||
#if 0 //Disable clean up because this tends to crash (and unnecessary)
|
||||
if (RC.nb_inst == 0) {
|
||||
if(IS_SOFTMODEM_DOSCOPE)
|
||||
|
||||
@@ -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/NR/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,56 @@ 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();
|
||||
|
||||
// OAI Wrapper
|
||||
e2_agent_args_t oai_args = RCconfig_NR_E2agent();
|
||||
AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} ");
|
||||
AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\"");
|
||||
|
||||
fr_args_t args = {.ip = oai_args.ip}; // init_fr_args(0, 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) {
|
||||
nb_id = rrc->configuration.cell_identity;
|
||||
cu_du_id = rrc->configuration.cell_identity;
|
||||
} else if (node_type == ngran_gNB_CU) {
|
||||
nb_id = rrc->configuration.cell_identity;
|
||||
cu_du_id = rrc->node_id;
|
||||
} else {
|
||||
LOG_E(NR_RRC, "not supported ran type detect\n");
|
||||
}
|
||||
|
||||
printf("[E2-AGENT]: mcc = %d mnc = %d mnc_digit = %d nd_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
|
||||
|
||||
bool init_agent = false;
|
||||
init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
|
||||
init_agent = true;
|
||||
|
||||
#endif // E2_AGENT
|
||||
|
||||
|
||||
if (NFAPI_MODE==NFAPI_MODE_PNF) {
|
||||
wait_nfapi_init("main?");
|
||||
}
|
||||
@@ -739,6 +795,10 @@ int main( int argc, char **argv ) {
|
||||
oai_exit=1;
|
||||
printf("oai_exit=%d\n",oai_exit);
|
||||
|
||||
#ifdef E2_AGENT
|
||||
if (init_agent) stop_agent_api();
|
||||
#endif
|
||||
|
||||
// cleanup
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
stop_gNB(RC.nb_nr_L1_inst);
|
||||
|
||||
98
openair2/E2AP/CMakeLists.txt
Normal file
98
openair2/E2AP/CMakeLists.txt
Normal file
@@ -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)
|
||||
|
||||
2
openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
Normal file
2
openair2/E2AP/RAN_FUNCTION/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(LTE)
|
||||
add_subdirectory(NR)
|
||||
2
openair2/E2AP/RAN_FUNCTION/LTE/CMakeLists.txt
Normal file
2
openair2/E2AP/RAN_FUNCTION/LTE/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(CUSTOMIZED)
|
||||
add_subdirectory(O-RAN)
|
||||
2
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/CMakeLists.txt
Normal file
2
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
24
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.c
Normal file
24
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "ran_func_gtp.h"
|
||||
#include "openair2/E2AP/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");
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/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
|
||||
|
||||
104
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.c
Normal file
104
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.c
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "ran_func_mac.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_mac.h"
|
||||
#include <assert.h>
|
||||
|
||||
static
|
||||
const int mod_id = 0;
|
||||
static
|
||||
const int CC_id = 0;
|
||||
|
||||
void read_mac_sm(void* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
mac_ind_data_t* mac = (mac_ind_data_t*)data;
|
||||
//fill_mac_ind_data(mac);
|
||||
|
||||
mac->msg.tstamp = time_now_us();
|
||||
|
||||
const size_t num_ues = RC.mac[mod_id]->UE_info.num_UEs;
|
||||
|
||||
mac->msg.len_ue_stats = num_ues;
|
||||
if (mac->msg.len_ue_stats > 0) {
|
||||
mac->msg.ue_stats = calloc(mac->msg.len_ue_stats, sizeof(mac_ue_stats_impl_t));
|
||||
assert(mac->msg.ue_stats != NULL && "Memory exhausted" );
|
||||
}
|
||||
|
||||
const UE_list_t* ue_list = &RC.mac[mod_id]->UE_info.list;
|
||||
size_t i = 0; //TODO
|
||||
for (int ue_id = ue_list->head; ue_id >= 0; ue_id = ue_list->next[ue_id]) {
|
||||
const eNB_UE_STATS* uestats = &RC.mac[mod_id]->UE_info.eNB_UE_stats[CC_id][ue_id];
|
||||
const UE_sched_ctrl_t *sched_ctrl = &RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id];
|
||||
const UE_TEMPLATE *template = &RC.mac[mod_id]->UE_info.UE_template[CC_id][ue_id];
|
||||
mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i];
|
||||
|
||||
rd->frame = 0; // TODO
|
||||
rd->slot = 0; // TODO
|
||||
|
||||
rd->dl_aggr_tbs = uestats->total_pdu_bytes;
|
||||
rd->ul_aggr_tbs = uestats->total_ulsch_TBS;
|
||||
|
||||
rd->dl_curr_tbs = uestats->TBS;
|
||||
rd->dl_sched_rb = uestats->rbs_used;
|
||||
|
||||
rd->ul_curr_tbs = uestats->ulsch_TBS;
|
||||
rd->ul_sched_rb = uestats->rbs_used_rx;
|
||||
|
||||
rd->rnti = uestats->crnti;
|
||||
rd->dl_aggr_prb = uestats->total_rbs_used;
|
||||
rd->ul_aggr_prb = uestats->total_rbs_used_rx;
|
||||
rd->dl_aggr_retx_prb = uestats->rbs_used_retx;
|
||||
rd->ul_aggr_retx_prb = uestats->rbs_used_retx_rx;
|
||||
|
||||
rd->dl_aggr_bytes_sdus = uestats->total_sdu_bytes;
|
||||
uint64_t ul_sdu_bytes = 0;
|
||||
for (int i = 0; i < NB_RB_MAX; ++i)
|
||||
ul_sdu_bytes += uestats->num_bytes_rx[i];
|
||||
rd->ul_aggr_bytes_sdus = ul_sdu_bytes;
|
||||
|
||||
rd->dl_aggr_sdus = uestats->num_mac_sdu_tx;
|
||||
rd->ul_aggr_sdus = uestats->num_mac_sdu_rx;
|
||||
|
||||
rd->pusch_snr = sched_ctrl->pusch_snr[CC_id];
|
||||
rd->pucch_snr = sched_ctrl->pucch1_snr[CC_id];
|
||||
|
||||
rd->wb_cqi = sched_ctrl->dl_cqi[CC_id];
|
||||
rd->dl_mcs1 = uestats->dlsch_mcs1;
|
||||
rd->dl_bler = 0; // TODO
|
||||
rd->ul_mcs1 = uestats->ulsch_mcs1;
|
||||
rd->ul_bler = sched_ctrl->pusch_bler[CC_id];
|
||||
rd->dl_mcs2 = uestats->dlsch_mcs2;
|
||||
rd->ul_mcs2 = uestats->ulsch_mcs2;
|
||||
rd->phr = template->phr_info;
|
||||
|
||||
const uint32_t bufferSize = template->estimated_ul_buffer - template->scheduled_ul_bytes;
|
||||
rd->bsr = bufferSize;
|
||||
|
||||
const size_t numDLHarq = 4;
|
||||
rd->dl_num_harq = numDLHarq;
|
||||
for (uint8_t j = 0; j < numDLHarq; ++j)
|
||||
rd->dl_harq[j] = uestats->dlsch_rounds[j];
|
||||
rd->dl_harq[numDLHarq] = uestats->dlsch_errors;
|
||||
|
||||
const size_t numUlHarq = 4;
|
||||
rd->ul_num_harq = numUlHarq;
|
||||
for (uint8_t j = 0; j < numUlHarq; ++j)
|
||||
rd->ul_harq[j] = uestats->ulsch_rounds[j];
|
||||
rd->ul_harq[numUlHarq] = uestats->ulsch_errors;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
15
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.h
Normal file
15
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef SM_MAC_READ_WRITE_AGENT_H
|
||||
#define SM_MAC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "openair2/LAYER2/MAC/mac.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
|
||||
void read_mac_sm(void*);
|
||||
|
||||
void read_mac_setup_sm(void*);
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_mac_sm(void const*);
|
||||
|
||||
#endif
|
||||
31
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.c
Normal file
31
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "ran_func_pdcp.h"
|
||||
#include "openair2/E2AP/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;
|
||||
}
|
||||
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/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
|
||||
|
||||
25
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.c
Normal file
25
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "ran_func_rlc.h"
|
||||
#include "openair2/E2AP/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");
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/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
|
||||
|
||||
47
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.c
Normal file
47
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "ran_func_slice.h"
|
||||
#include "openair2/E2AP/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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
39
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.c
Normal file
39
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "ran_func_tc.h"
|
||||
#include "E2AP/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;
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
0
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/CMakeLists.txt
Normal file
0
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/CMakeLists.txt
Normal file
3
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/README.md
Normal file
3
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
RAN Functions as defined by O-RAN
|
||||
|
||||
|
||||
222
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.c
Normal file
222
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "ran_func_kpm.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_kpm.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static
|
||||
gnb_e2sm_t fill_rnd_gnb_data(void)
|
||||
{
|
||||
gnb_e2sm_t gnb = {0};
|
||||
gnb.amf_ue_ngap_id = (rand() % 2^40) + 0;
|
||||
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_rnd_ue_id_data()
|
||||
{
|
||||
ue_id_e2sm_t ue_id_data = {0};
|
||||
ue_id_data.type = GNB_UE_ID_E2SM;
|
||||
ue_id_data.gnb = fill_rnd_gnb_data();
|
||||
return ue_id_data;
|
||||
}
|
||||
|
||||
void copy_ba_to_str(const uint8_t* buffer, size_t length, char* str) {
|
||||
memcpy(str, buffer, length);
|
||||
str[length] = '\0';
|
||||
}
|
||||
|
||||
static
|
||||
kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(kpm_act_def_format_1_t const act_def_fr1)
|
||||
{
|
||||
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" );
|
||||
|
||||
|
||||
size_t const rec_data_len = act_def_fr1.meas_info_lst_len; // Recoding Data Length
|
||||
for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++) {
|
||||
|
||||
// Measurement Record
|
||||
meas_data_lst_t* meas_data = &msg_frm_1.meas_data_lst[i];
|
||||
meas_data->meas_record_len = rec_data_len;
|
||||
meas_data->meas_record_lst = calloc(meas_data->meas_record_len, sizeof(meas_record_lst_t));
|
||||
assert(meas_data->meas_record_lst != NULL && "Memory exhausted");
|
||||
for (size_t j = 0; j < meas_data->meas_record_len; j++) {
|
||||
meas_record_lst_t* meas_record = &meas_data->meas_record_lst[j];
|
||||
meas_type_t meas_info_type = act_def_fr1.meas_info_lst[j].meas_type;
|
||||
if (meas_info_type.type == NAME_MEAS_TYPE) {
|
||||
// Get Meas Info Name from Action Definition
|
||||
size_t length = meas_info_type.name.len;
|
||||
char meas_info_name_str[length + 1];
|
||||
copy_ba_to_str(meas_info_type.name.buf, length, meas_info_name_str);
|
||||
|
||||
// Get value based on Meas Info Name
|
||||
if (strcmp(meas_info_name_str, "DRB.IPThpDl.QCI") == 0 ? true : false) {
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
meas_record->real_val = (rand() % 256) + 0;
|
||||
} else if (strcmp(meas_info_name_str, "DRB.IPThpUl.QCI") == 0 ? true : false) {
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
meas_record->real_val = (rand() % 256) + 0;
|
||||
} else if (strcmp(meas_info_name_str, "DRB.RlcSduDelayDl") == 0 ? true : false) {
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
meas_record->real_val = (rand() % 256) + 0;
|
||||
} else {
|
||||
printf("not implement value for measurement name %s\n", meas_info_name_str);
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
meas_record->real_val = 1234;
|
||||
}
|
||||
} else {
|
||||
printf("not implement value for measurement type %d\n", meas_info_type.type);
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
meas_record->real_val = 1234;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Measurement Information - OPTIONAL
|
||||
msg_frm_1.meas_info_lst_len = rec_data_len;
|
||||
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" );
|
||||
|
||||
// Get measInfo from action definition
|
||||
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 = act_def_fr1.meas_info_lst[i].meas_type.type;
|
||||
// Measurement Name
|
||||
if (act_def_fr1.meas_info_lst[i].meas_type.type == NAME_MEAS_TYPE) {
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.buf = calloc(act_def_fr1.meas_info_lst[i].meas_type.name.len, sizeof(uint8_t));
|
||||
memcpy(msg_frm_1.meas_info_lst[i].meas_type.name.buf, act_def_fr1.meas_info_lst[i].meas_type.name.buf, act_def_fr1.meas_info_lst[i].meas_type.name.len);
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.len = act_def_fr1.meas_info_lst[i].meas_type.name.len;
|
||||
} else {
|
||||
msg_frm_1.meas_info_lst[i].meas_type.id = act_def_fr1.meas_info_lst[i].meas_type.id;
|
||||
}
|
||||
|
||||
|
||||
// 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(kpm_act_def_format_1_t const act_def_fr1)
|
||||
{
|
||||
kpm_ind_msg_format_3_t msg_frm_3 = {0};
|
||||
|
||||
msg_frm_3.ue_meas_report_lst_len = 2; // (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_rnd_ue_id_data();
|
||||
msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(act_def_fr1);
|
||||
}
|
||||
|
||||
|
||||
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* const 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 );
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kpm->act_def->frm_4.action_def_format_1.meas_info_lst_len; i++)
|
||||
printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst[i].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(kpm->act_def->frm_4.action_def_format_1);
|
||||
} 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;
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
108
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_rc.c
Normal file
108
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_rc.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "ran_func_rc.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_rc.h"
|
||||
#include "openair2/E2AP/flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
|
||||
#include "openair2/E2AP/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;
|
||||
}
|
||||
|
||||
15
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_rc.h
Normal file
15
openair2/E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_rc.h
Normal file
@@ -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 "E2AP/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
|
||||
|
||||
73
openair2/E2AP/RAN_FUNCTION/LTE/init_ran_func.c
Normal file
73
openair2/E2AP/RAN_FUNCTION/LTE/init_ran_func.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "init_ran_func.h"
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_mac.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_rlc.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_pdcp.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_slice.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_tc.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/CUSTOMIZED/ran_func_gtp.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/O-RAN/ran_func_kpm.h"
|
||||
#include "E2AP/RAN_FUNCTION/LTE/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;
|
||||
}
|
||||
|
||||
32
openair2/E2AP/RAN_FUNCTION/LTE/init_ran_func.h
Normal file
32
openair2/E2AP/RAN_FUNCTION/LTE/init_ran_func.h
Normal file
@@ -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 LTE_RAN_FUNC_INIT_E2_H
|
||||
#define LTE_RAN_FUNC_INIT_E2_H
|
||||
|
||||
#include "E2AP/flexric/src/sm/sm_io.h"
|
||||
|
||||
sm_io_ag_ran_t init_ran_func_ag(void);
|
||||
|
||||
#endif
|
||||
|
||||
2
openair2/E2AP/RAN_FUNCTION/NR/CMakeLists.txt
Normal file
2
openair2/E2AP/RAN_FUNCTION/NR/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(CUSTOMIZED)
|
||||
add_subdirectory(O-RAN)
|
||||
2
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/CMakeLists.txt
Normal file
2
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
68
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.c
Normal file
68
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "ran_func_gtp.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_gtp.h"
|
||||
#include <assert.h>
|
||||
|
||||
static
|
||||
const int mod_id = 0;
|
||||
|
||||
void read_gtp_sm(void * data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
gtp_ind_data_t* gtp = (gtp_ind_data_t*)(data);
|
||||
//fill_gtp_ind_data(gtp);
|
||||
|
||||
gtp->msg.tstamp = time_now_us();
|
||||
|
||||
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
size_t num_ues = 0;
|
||||
UE_iterator(UE_info->list, ue) {
|
||||
if (ue)
|
||||
num_ues += 1;
|
||||
}
|
||||
|
||||
gtp->msg.len = num_ues;
|
||||
if(gtp->msg.len > 0){
|
||||
gtp->msg.ngut = calloc(gtp->msg.len, sizeof(gtp_ngu_t_stats_t) );
|
||||
assert(gtp->msg.ngut != NULL);
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
UE_iterator(UE_info->list, UE)
|
||||
{
|
||||
uint16_t const rnti = UE->rnti;
|
||||
struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[mod_id], rnti);
|
||||
if (ue_context_p != NULL) {
|
||||
gtp->msg.ngut[i].rnti = ue_context_p->ue_context.rnti;
|
||||
int nb_pdu_session = ue_context_p->ue_context.nb_of_pdusessions;
|
||||
if (nb_pdu_session > 0) {
|
||||
int nb_pdu_idx = nb_pdu_session - 1;
|
||||
gtp->msg.ngut[i].teidgnb = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.gNB_teid_N3;
|
||||
gtp->msg.ngut[i].teidupf = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.UPF_teid_N3;
|
||||
// TODO: one PDU session has multiple QoS Flow
|
||||
int nb_qos_flow = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.nb_qos;
|
||||
if (nb_qos_flow > 0) {
|
||||
gtp->msg.ngut[i].qfi = ue_context_p->ue_context.pduSession[nb_pdu_idx].param.qos[nb_qos_flow - 1].qfi;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_W(NR_RRC,"rrc_gNB_get_ue_context return NULL\n");
|
||||
// if (gtp->msg.ngut != NULL) free(gtp->msg.ngut);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
17
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.h
Normal file
17
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
|
||||
void read_gtp_sm(void*);
|
||||
|
||||
void read_gtp_setup_sm(void*);
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_gtp_sm(void const*);
|
||||
|
||||
#endif
|
||||
|
||||
141
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.c
Normal file
141
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.c
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "ran_func_mac.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_mac.h"
|
||||
#include <assert.h>
|
||||
|
||||
static
|
||||
const int mod_id = 0;
|
||||
|
||||
size_t get_number_connected_ues(void)
|
||||
{
|
||||
size_t num_ues = 0;
|
||||
|
||||
for (size_t i = 0; i < RC.nb_nr_macrlc_inst; i++) {
|
||||
UE_iterator(RC.nrmac[i]->UE_info.list, ue)
|
||||
{
|
||||
if (ue) num_ues += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return num_ues;
|
||||
}
|
||||
|
||||
NR_UE_info_t * connected_ues_list(void)
|
||||
{
|
||||
size_t num_ues = get_number_connected_ues();
|
||||
|
||||
NR_UE_info_t * ue_list = calloc(num_ues, sizeof(NR_UE_info_t));
|
||||
assert(ue_list != NULL && "Memory exhausted");
|
||||
|
||||
size_t j = 0;
|
||||
|
||||
for (size_t i = 0; i < RC.nb_nr_macrlc_inst; i++) {
|
||||
UE_iterator(RC.nrmac[i]->UE_info.list, ue)
|
||||
{
|
||||
if (ue)
|
||||
{
|
||||
ue_list[j] = *ue;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ue_list;
|
||||
}
|
||||
|
||||
void read_mac_sm(void* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
mac_ind_data_t* mac = (mac_ind_data_t*)data;
|
||||
//fill_mac_ind_data(mac);
|
||||
|
||||
mac->msg.tstamp = time_now_us();
|
||||
|
||||
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
size_t num_ues = 0;
|
||||
UE_iterator(UE_info->list, ue) {
|
||||
if (ue)
|
||||
num_ues += 1;
|
||||
}
|
||||
|
||||
mac->msg.len_ue_stats = num_ues;
|
||||
if(mac->msg.len_ue_stats > 0){
|
||||
mac->msg.ue_stats = calloc(mac->msg.len_ue_stats, sizeof(mac_ue_stats_impl_t));
|
||||
assert(mac->msg.ue_stats != NULL && "Memory exhausted" );
|
||||
}
|
||||
|
||||
size_t i = 0; //TODO
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
const NR_UE_sched_ctrl_t* sched_ctrl = &UE->UE_sched_ctrl;
|
||||
mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i];
|
||||
|
||||
rd->frame = RC.nrmac[mod_id]->frame;
|
||||
rd->slot = RC.nrmac[mod_id]->slot;
|
||||
|
||||
rd->dl_aggr_tbs = UE->mac_stats.dl.total_bytes;
|
||||
rd->ul_aggr_tbs = UE->mac_stats.ul.total_bytes;
|
||||
|
||||
if (is_xlsch_in_slot(RC.nrmac[mod_id]->dlsch_slot_bitmap[rd->slot / 64], rd->slot)) {
|
||||
rd->dl_curr_tbs = UE->mac_stats.dl.current_bytes;
|
||||
rd->dl_sched_rb = UE->mac_stats.dl.current_rbs;
|
||||
}
|
||||
if (is_xlsch_in_slot(RC.nrmac[mod_id]->ulsch_slot_bitmap[rd->slot / 64], rd->slot)) {
|
||||
rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes;
|
||||
rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize;
|
||||
}
|
||||
|
||||
rd->rnti = UE->rnti;
|
||||
rd->dl_aggr_prb = UE->mac_stats.dl.total_rbs;
|
||||
rd->ul_aggr_prb = UE->mac_stats.ul.total_rbs;
|
||||
rd->dl_aggr_retx_prb = UE->mac_stats.dl.total_rbs_retx;
|
||||
rd->ul_aggr_retx_prb = UE->mac_stats.ul.total_rbs_retx;
|
||||
|
||||
rd->dl_aggr_bytes_sdus = UE->mac_stats.dl.lc_bytes[3];
|
||||
rd->ul_aggr_bytes_sdus = UE->mac_stats.ul.lc_bytes[3];
|
||||
|
||||
rd->dl_aggr_sdus = UE->mac_stats.dl.num_mac_sdu;
|
||||
rd->ul_aggr_sdus = UE->mac_stats.ul.num_mac_sdu;
|
||||
|
||||
rd->pusch_snr = (float) sched_ctrl->pusch_snrx10 / 10; //: float = -64;
|
||||
rd->pucch_snr = (float) sched_ctrl->pucch_snrx10 / 10; //: float = -64;
|
||||
|
||||
rd->wb_cqi = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
|
||||
rd->dl_mcs1 = sched_ctrl->dl_bler_stats.mcs;
|
||||
rd->dl_bler = sched_ctrl->dl_bler_stats.bler;
|
||||
rd->ul_mcs1 = sched_ctrl->ul_bler_stats.mcs;
|
||||
rd->ul_bler = sched_ctrl->ul_bler_stats.bler;
|
||||
rd->dl_mcs2 = 0;
|
||||
rd->ul_mcs2 = 0;
|
||||
rd->phr = sched_ctrl->ph;
|
||||
|
||||
const uint32_t bufferSize = sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes;
|
||||
rd->bsr = bufferSize;
|
||||
|
||||
const size_t numDLHarq = 4;
|
||||
rd->dl_num_harq = numDLHarq;
|
||||
for (uint8_t j = 0; j < numDLHarq; ++j)
|
||||
rd->dl_harq[j] = UE->mac_stats.dl.rounds[j];
|
||||
rd->dl_harq[numDLHarq] = UE->mac_stats.dl.errors;
|
||||
|
||||
const size_t numUlHarq = 4;
|
||||
rd->ul_num_harq = numUlHarq;
|
||||
for (uint8_t j = 0; j < numUlHarq; ++j)
|
||||
rd->ul_harq[j] = UE->mac_stats.ul.rounds[j];
|
||||
rd->ul_harq[numUlHarq] = UE->mac_stats.ul.errors;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
19
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.h
Normal file
19
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef SM_MAC_READ_WRITE_AGENT_H
|
||||
#define SM_MAC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
|
||||
size_t get_number_connected_ues(void);
|
||||
|
||||
NR_UE_info_t * connected_ues_list(void);
|
||||
|
||||
void read_mac_sm(void*);
|
||||
|
||||
void read_mac_setup_sm(void*);
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_mac_sm(void const*);
|
||||
|
||||
#endif
|
||||
167
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.c
Normal file
167
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "ran_func_pdcp.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_pdcp.h"
|
||||
#include <assert.h>
|
||||
|
||||
static
|
||||
const int mod_id = 0;
|
||||
|
||||
static
|
||||
uint32_t num_act_rb(NR_UEs_t* UE_info)
|
||||
{
|
||||
assert(UE_info!= NULL);
|
||||
|
||||
uint32_t act_rb = 0;
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
uint16_t const rnti = UE->rnti;
|
||||
for(int rb_id = 1; rb_id < 6; ++rb_id ){
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rlc);
|
||||
if(rc) ++act_rb;
|
||||
}
|
||||
}
|
||||
return act_rb;
|
||||
}
|
||||
|
||||
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);
|
||||
// TODO: Need to improve, not good
|
||||
if (NODE_IS_CU(RC.nrrrc[mod_id]->node_type)) {
|
||||
|
||||
uint32_t act_rb = 0;
|
||||
struct rrc_gNB_ue_context_s *ue_context_p1 = NULL;
|
||||
RB_FOREACH(ue_context_p1, rrc_nr_ue_tree_s, &RC.nrrrc[mod_id]->rrc_ue_head) {
|
||||
uint16_t const rnti = ue_context_p1->ue_context.rnti;
|
||||
for(int rb_id = 1; rb_id < 6; ++rb_id ){
|
||||
nr_pdcp_statistics_t rb_pdcp = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_pdcp_get_statistics(rnti, srb_flag, rb_id, &rb_pdcp);
|
||||
if(rc) ++act_rb;
|
||||
}
|
||||
}
|
||||
|
||||
pdcp->msg.tstamp = time_now_us();
|
||||
|
||||
pdcp->msg.len = act_rb;
|
||||
if (pdcp->msg.len > 0) {
|
||||
pdcp->msg.rb = calloc(pdcp->msg.len, sizeof(pdcp_radio_bearer_stats_t));
|
||||
assert(pdcp->msg.rb != NULL && "Memory exhausted!");
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
struct rrc_gNB_ue_context_s *ue_context_p2 = NULL;
|
||||
RB_FOREACH(ue_context_p2, rrc_nr_ue_tree_s, &RC.nrrrc[mod_id]->rrc_ue_head) {
|
||||
// TODO: Need to handel multiple UEs
|
||||
uint16_t const rnti = ue_context_p2->ue_context.rnti;
|
||||
|
||||
for (size_t rb_id = 1; rb_id < 6; ++rb_id) {
|
||||
nr_pdcp_statistics_t rb_pdcp = {0};
|
||||
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_pdcp_get_statistics(rnti, srb_flag, rb_id, &rb_pdcp);
|
||||
|
||||
if (!rc) continue;
|
||||
|
||||
pdcp_radio_bearer_stats_t *rd = &pdcp->msg.rb[i];
|
||||
|
||||
rd->txpdu_pkts = rb_pdcp.txpdu_pkts; /* aggregated number of tx packets */
|
||||
rd->txpdu_bytes = rb_pdcp.txpdu_bytes; /* aggregated bytes of tx packets */
|
||||
rd->txpdu_sn = rb_pdcp.txpdu_sn; /* current sequence number of last tx packet (or TX_NEXT) */
|
||||
rd->rxpdu_pkts = rb_pdcp.rxpdu_pkts; /* aggregated number of rx packets */
|
||||
rd->rxpdu_bytes = rb_pdcp.rxpdu_bytes; /* aggregated bytes of rx packets */
|
||||
rd->rxpdu_sn = rb_pdcp.rxpdu_sn; /* current sequence number of last rx packet (or RX_NEXT) */
|
||||
rd->rxpdu_oo_pkts = rb_pdcp.rxpdu_oo_pkts; /* aggregated number of out-of-order rx pkts (or RX_REORD) */
|
||||
rd->rxpdu_oo_bytes = rb_pdcp.rxpdu_oo_bytes; /* aggregated amount of out-of-order rx bytes */
|
||||
rd->rxpdu_dd_pkts = rb_pdcp.rxpdu_dd_pkts; /* aggregated number of duplicated discarded packets (or dropped packets because of other reasons such as integrity failure) (or RX_DELIV) */
|
||||
rd->rxpdu_dd_bytes = rb_pdcp.rxpdu_dd_bytes; /* aggregated amount of discarded packets' bytes */
|
||||
rd->rxpdu_ro_count = rb_pdcp.rxpdu_ro_count; /* this state variable indicates the COUNT value following the COUNT value associated with the PDCP Data PDU which triggered t-Reordering. (RX_REORD) */
|
||||
rd->txsdu_pkts = rb_pdcp.txsdu_pkts; /* number of SDUs delivered */
|
||||
rd->txsdu_bytes = rb_pdcp.txsdu_bytes; /* number of bytes of SDUs delivered */
|
||||
rd->rxsdu_pkts = rb_pdcp.rxsdu_pkts; /* number of SDUs received */
|
||||
rd->rxsdu_bytes = rb_pdcp.rxsdu_bytes; /* number of bytes of SDUs received */
|
||||
rd->rnti = rnti;
|
||||
rd->mode = rb_pdcp.mode; /* 0: PDCP AM, 1: PDCP UM, 2: PDCP TM */
|
||||
rd->rbid = rb_id;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
//assert(0!=0 && "Calling PDCP");
|
||||
// for the moment and while we don't have a split base station, we use the
|
||||
// MAC structures to obtain the RNTIs which we use to query the PDCP
|
||||
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
uint32_t const act_rb = num_act_rb(UE_info);
|
||||
|
||||
pdcp->msg.tstamp = time_now_us();
|
||||
|
||||
pdcp->msg.len = act_rb;
|
||||
if (pdcp->msg.len > 0) {
|
||||
pdcp->msg.rb = calloc(pdcp->msg.len, sizeof(pdcp_radio_bearer_stats_t));
|
||||
assert(pdcp->msg.rb != NULL && "Memory exhausted!");
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
UE_iterator(UE_info->list, UE)
|
||||
{
|
||||
|
||||
const int rnti = UE->rnti;
|
||||
for (size_t rb_id = 1; rb_id < 6; ++rb_id) {
|
||||
nr_pdcp_statistics_t rb_pdcp = {0};
|
||||
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_pdcp_get_statistics(rnti, srb_flag, rb_id, &rb_pdcp);
|
||||
|
||||
if (!rc) continue;
|
||||
|
||||
pdcp_radio_bearer_stats_t *rd = &pdcp->msg.rb[i];
|
||||
|
||||
rd->txpdu_pkts = rb_pdcp.txpdu_pkts; /* aggregated number of tx packets */
|
||||
rd->txpdu_bytes = rb_pdcp.txpdu_bytes; /* aggregated bytes of tx packets */
|
||||
rd->txpdu_sn = rb_pdcp.txpdu_sn; /* current sequence number of last tx packet (or TX_NEXT) */
|
||||
rd->rxpdu_pkts = rb_pdcp.rxpdu_pkts; /* aggregated number of rx packets */
|
||||
rd->rxpdu_bytes = rb_pdcp.rxpdu_bytes; /* aggregated bytes of rx packets */
|
||||
rd->rxpdu_sn = rb_pdcp.rxpdu_sn; /* current sequence number of last rx packet (or RX_NEXT) */
|
||||
rd->rxpdu_oo_pkts = rb_pdcp.rxpdu_oo_pkts; /* aggregated number of out-of-order rx pkts (or RX_REORD) */
|
||||
rd->rxpdu_oo_bytes = rb_pdcp.rxpdu_oo_bytes; /* aggregated amount of out-of-order rx bytes */
|
||||
rd->rxpdu_dd_pkts = rb_pdcp.rxpdu_dd_pkts; /* aggregated number of duplicated discarded packets (or dropped packets because of other reasons such as integrity failure) (or RX_DELIV) */
|
||||
rd->rxpdu_dd_bytes = rb_pdcp.rxpdu_dd_bytes; /* aggregated amount of discarded packets' bytes */
|
||||
rd->rxpdu_ro_count = rb_pdcp.rxpdu_ro_count; /* this state variable indicates the COUNT value following the COUNT value associated with the PDCP Data PDU which triggered t-Reordering. (RX_REORD) */
|
||||
rd->txsdu_pkts = rb_pdcp.txsdu_pkts; /* number of SDUs delivered */
|
||||
rd->txsdu_bytes = rb_pdcp.txsdu_bytes; /* number of bytes of SDUs delivered */
|
||||
rd->rxsdu_pkts = rb_pdcp.rxsdu_pkts; /* number of SDUs received */
|
||||
rd->rxsdu_bytes = rb_pdcp.rxsdu_bytes; /* number of bytes of SDUs received */
|
||||
rd->rnti = rnti;
|
||||
rd->mode = rb_pdcp.mode; /* 0: PDCP AM, 1: PDCP UM, 2: PDCP TM */
|
||||
rd->rbid = rb_id;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
20
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.h
Normal file
20
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "common/ngran_types.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.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
|
||||
|
||||
185
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.c
Normal file
185
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#include <assert.h>
|
||||
#include "ran_func_rlc.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_rlc.h"
|
||||
|
||||
static
|
||||
const int mod_id = 0;
|
||||
|
||||
size_t get_number_drbs_per_ue(NR_UE_info_t * const UE)
|
||||
{
|
||||
size_t num_drbs = 0;
|
||||
|
||||
for (int rb_id = 1; rb_id<6 ; ++rb_id)
|
||||
{
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(UE->rnti, srb_flag, rb_id, &rlc);
|
||||
if(rc)
|
||||
{
|
||||
num_drbs++;
|
||||
printf("DRB ID is %d\n", rb_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return num_drbs;
|
||||
}
|
||||
|
||||
nr_rlc_statistics_t active_avg_to_tx_per_drb(NR_UE_info_t * const UE, int const rb_id)
|
||||
{
|
||||
assert(UE != NULL);
|
||||
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
|
||||
// Get RLC stats for specific DRB
|
||||
const bool rc = nr_rlc_get_statistics(UE->rnti, srb_flag, rb_id, &rlc);
|
||||
assert(rc == true && "Cannot get RLC stats\n");
|
||||
|
||||
// Activate average sojourn time at the RLC buffer for specific DRB
|
||||
nr_rlc_activate_avg_time_to_tx(UE->rnti, rb_id+3, 1);
|
||||
|
||||
return rlc;
|
||||
}
|
||||
|
||||
uint32_t num_act_rb(NR_UEs_t* const UE_info)
|
||||
{
|
||||
assert(UE_info!= NULL);
|
||||
|
||||
uint32_t act_rb = 0;
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
uint16_t const rnti = UE->rnti;
|
||||
for(int rb_id = 1; rb_id < 6; ++rb_id ){
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rlc);
|
||||
if(rc) ++act_rb;
|
||||
}
|
||||
}
|
||||
return act_rb;
|
||||
}
|
||||
|
||||
void active_avg_to_tx(NR_UEs_t* const UE_info)
|
||||
{
|
||||
assert(UE_info!= NULL);
|
||||
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
uint16_t const rnti = UE->rnti;
|
||||
for(int rb_id = 1; rb_id < 6; ++rb_id ){
|
||||
nr_rlc_statistics_t rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rlc);
|
||||
if(rc) nr_rlc_activate_avg_time_to_tx(rnti, rb_id, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
// use MAC structures to get RNTIs
|
||||
NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||
uint32_t const act_rb = num_act_rb(UE_info);
|
||||
|
||||
//assert(0!=0 && "Read RLC called");
|
||||
|
||||
// activate the rlc to calculate the average tx time
|
||||
active_avg_to_tx(UE_info);
|
||||
|
||||
rlc->msg.len = act_rb;
|
||||
if(rlc->msg.len > 0){
|
||||
rlc->msg.rb = calloc(rlc->msg.len, sizeof(rlc_radio_bearer_stats_t));
|
||||
assert(rlc->msg.rb != NULL && "Memory exhausted");
|
||||
}
|
||||
|
||||
rlc->msg.tstamp = time_now_us();
|
||||
|
||||
uint32_t i = 0;
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
uint16_t const rnti = UE->rnti;
|
||||
//for every LC ID
|
||||
for(int rb_id = 1; rb_id < 6; ++rb_id ){
|
||||
|
||||
nr_rlc_statistics_t rb_rlc = {0};
|
||||
const int srb_flag = 0;
|
||||
const bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &rb_rlc);
|
||||
if(!rc) continue;
|
||||
rlc_radio_bearer_stats_t* sm_rb = &rlc->msg.rb[i];
|
||||
|
||||
/* TX */
|
||||
sm_rb->txpdu_pkts = rb_rlc.txpdu_pkts;
|
||||
sm_rb->txpdu_bytes = rb_rlc.txpdu_bytes; /* aggregated amount of transmitted bytes in RLC PDUs */
|
||||
|
||||
/* TODO? */
|
||||
/* (TO BE DISCUSSED) HOL delay of the packet to be transmitted (RLC delay + MAC delay) */
|
||||
// sm_rb->txpdu_wt_ms += rb_rlc.txsdu_avg_time_to_tx;
|
||||
|
||||
sm_rb->txpdu_dd_pkts = rb_rlc.txpdu_dd_pkts; /* aggregated number of dropped or discarded tx packets by RLC */
|
||||
sm_rb->txpdu_dd_bytes = rb_rlc.txpdu_dd_bytes; /* aggregated amount of bytes dropped or discarded tx packets by RLC */
|
||||
sm_rb->txpdu_retx_pkts = rb_rlc.txpdu_retx_pkts; /* aggregated number of tx pdus/pkts to be re-transmitted (only applicable to RLC AM) */
|
||||
sm_rb->txpdu_retx_bytes = rb_rlc.txpdu_retx_bytes; /* aggregated amount of bytes to be re-transmitted (only applicable to RLC AM) */
|
||||
sm_rb->txpdu_segmented = rb_rlc.txpdu_segmented; /* aggregated number of segmentations */
|
||||
sm_rb->txpdu_status_pkts = rb_rlc.txpdu_status_pkts; /* aggregated number of tx status pdus/pkts (only applicable to RLC AM) */
|
||||
sm_rb->txpdu_status_bytes = rb_rlc.txpdu_status_bytes; /* aggregated amount of tx status bytes (only applicable to RLC AM) */
|
||||
sm_rb->txbuf_occ_bytes = rb_rlc.txbuf_occ_bytes; /* (IMPLEMENTED) transmitting bytes currently in buffer */
|
||||
sm_rb->txbuf_occ_pkts = rb_rlc.txbuf_occ_pkts; /* current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
|
||||
/* RX */
|
||||
sm_rb->rxpdu_pkts = rb_rlc.rxpdu_pkts; /* aggregated number of received RLC PDUs */
|
||||
sm_rb->rxpdu_bytes = rb_rlc.rxpdu_bytes; /* amount of bytes received by the RLC */
|
||||
sm_rb->rxpdu_dup_pkts = rb_rlc.rxpdu_dup_pkts; /* aggregated number of duplicate packets */
|
||||
sm_rb->rxpdu_dup_bytes = rb_rlc.rxpdu_dup_bytes; /* aggregated amount of duplicated bytes */
|
||||
sm_rb->rxpdu_dd_pkts = rb_rlc.rxpdu_dd_pkts; /* aggregated number of rx packets dropped or discarded by RLC */
|
||||
sm_rb->rxpdu_dd_bytes = rb_rlc.rxpdu_dd_bytes; /* aggregated amount of rx bytes dropped or discarded by RLC */
|
||||
sm_rb->rxpdu_ow_pkts = rb_rlc.rxpdu_ow_pkts; /* aggregated number of out of window received RLC pdu */
|
||||
sm_rb->rxpdu_ow_bytes = rb_rlc.rxpdu_ow_bytes; /* aggregated number of out of window bytes received RLC pdu */
|
||||
sm_rb->rxpdu_status_pkts = rb_rlc.rxpdu_status_pkts; /* aggregated number of rx status pdus/pkts (only applicable to RLC AM) */
|
||||
sm_rb->rxpdu_status_bytes = rb_rlc.rxpdu_status_bytes; /* aggregated amount of rx status bytes (only applicable to RLC AM) */
|
||||
|
||||
sm_rb->rxbuf_occ_bytes = rb_rlc.rxbuf_occ_bytes; /* (IMPLEMENTED) received bytes currently in buffer */
|
||||
sm_rb->rxbuf_occ_pkts = rb_rlc.rxbuf_occ_pkts; /* current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
|
||||
/* TX */
|
||||
sm_rb->txsdu_pkts = rb_rlc.txsdu_pkts; /* number of SDUs delivered */
|
||||
sm_rb->txsdu_bytes = rb_rlc.txsdu_bytes; /* (UPDATED) number of SDUs bytes successfully transmitted so far (counter) */
|
||||
|
||||
sm_rb->txsdu_avg_time_to_tx = rb_rlc.txsdu_avg_time_to_tx; /* (100ms-windowed) per-packet sojourn (SDU to PDU) in microseconds */
|
||||
sm_rb->txsdu_wt_us = rb_rlc.txsdu_wt_us; /* HOL delay of the current radio bearer */
|
||||
|
||||
/* RX */
|
||||
sm_rb->rxsdu_pkts = rb_rlc.rxsdu_pkts; /* number of SDUs received */
|
||||
sm_rb->rxsdu_bytes = rb_rlc.rxsdu_bytes; /* (UPDATED) number of SDUs bytes arrived so far (counter) */
|
||||
sm_rb->rxsdu_dd_pkts = rb_rlc.rxsdu_dd_pkts; /* number of dropped or discarded SDUs */
|
||||
sm_rb->rxsdu_dd_bytes = rb_rlc.rxsdu_dd_bytes; /* number of bytes of SDUs dropped or discarded */
|
||||
|
||||
sm_rb->mode = rb_rlc.mode; /* 0: RLC AM, 1: RLC UM, 2: RLC TM */
|
||||
sm_rb->rnti = rnti;
|
||||
sm_rb->rbid = rb_id;
|
||||
|
||||
LOG_D(RLC, "[E2-AGENT] SDU Goodput & HOL-waittime/200ms-sojourn: %lu/%lu (bytes) & %u/%f (microsecs);\n\
|
||||
Current Buffer: received %u, transmitting %u (bytes).\n",
|
||||
sm_rb->txsdu_bytes, sm_rb->rxsdu_bytes, sm_rb->txsdu_wt_us, sm_rb->txsdu_avg_time_to_tx,
|
||||
sm_rb->rxbuf_occ_bytes, sm_rb->txbuf_occ_bytes);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
27
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.h
Normal file
27
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
|
||||
size_t get_number_drbs_per_ue(NR_UE_info_t * const UE);
|
||||
|
||||
// nr_rlc_statistics_t** rlc_stat_per_ue(NR_UE_info_t * const UE);
|
||||
nr_rlc_statistics_t active_avg_to_tx_per_drb(NR_UE_info_t * const UE, int const rb_id);
|
||||
|
||||
|
||||
uint32_t num_act_rb(NR_UEs_t* const UE_info);
|
||||
|
||||
void active_avg_to_tx(NR_UEs_t* const UE_info);
|
||||
|
||||
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
|
||||
|
||||
47
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.c
Normal file
47
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "ran_func_slice.h"
|
||||
#include "openair2/E2AP/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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
39
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.c
Normal file
39
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "ran_func_tc.h"
|
||||
#include "E2AP/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;
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
0
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/CMakeLists.txt
Normal file
0
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/CMakeLists.txt
Normal file
3
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/README.md
Normal file
3
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
RAN Functions as defined by O-RAN
|
||||
|
||||
|
||||
424
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.c
Normal file
424
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.c
Normal file
@@ -0,0 +1,424 @@
|
||||
#include "ran_func_kpm.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_kpm.h"
|
||||
#include "openair2/E2AP/flexric/src/util/time_now_us.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
|
||||
#include "openair3/NGAP/ngap_gNB_ue_context.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static
|
||||
gnb_e2sm_t fill_gnb_data(rrc_gNB_ue_context_t * ue_context_p)
|
||||
{
|
||||
gnb_e2sm_t gnb = {0};
|
||||
|
||||
// 6.2.3.16
|
||||
// Mandatory
|
||||
// AMF UE NGAP ID
|
||||
// fill with openair3/NGAP/ngap_gNB_ue_context.h:61
|
||||
gnb.amf_ue_ngap_id = ue_context_p->ue_context.gNB_ue_ngap_id;
|
||||
|
||||
// Mandatory
|
||||
//GUAMI 6.2.3.17
|
||||
gnb.guami.plmn_id = (e2sm_plmn_t) {
|
||||
.mcc = ue_context_p->ue_context.ue_guami.mcc,
|
||||
.mnc = ue_context_p->ue_context.ue_guami.mnc,
|
||||
.mnc_digit_len = ue_context_p->ue_context.ue_guami.mnc_len
|
||||
};
|
||||
|
||||
gnb.guami.amf_region_id = ue_context_p->ue_context.ue_guami.amf_region_id;
|
||||
gnb.guami.amf_set_id = ue_context_p->ue_context.ue_guami.amf_set_id;
|
||||
gnb.guami.amf_ptr = ue_context_p->ue_context.ue_guami.amf_pointer;
|
||||
|
||||
return gnb;
|
||||
}
|
||||
|
||||
static
|
||||
gnb_e2sm_t fill_rnd_gnb_data(void)
|
||||
{
|
||||
gnb_e2sm_t gnb = {0};
|
||||
gnb.amf_ue_ngap_id = (rand() % 2^40) + 0;
|
||||
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(rrc_gNB_ue_context_t * ue_context_p)
|
||||
{
|
||||
ue_id_e2sm_t ue_id_data = {0};
|
||||
|
||||
ue_id_data.type = GNB_UE_ID_E2SM;
|
||||
ue_id_data.gnb = fill_gnb_data(ue_context_p);
|
||||
|
||||
return ue_id_data;
|
||||
}
|
||||
|
||||
static
|
||||
ue_id_e2sm_t fill_rnd_ue_id_data()
|
||||
{
|
||||
ue_id_e2sm_t ue_id_data = {0};
|
||||
ue_id_data.type = GNB_UE_ID_E2SM;
|
||||
ue_id_data.gnb = fill_rnd_gnb_data();
|
||||
return ue_id_data;
|
||||
}
|
||||
|
||||
|
||||
uint32_t last_dl_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
uint32_t last_ul_total_bytes[MAX_MOBILES_PER_GNB] = {0};
|
||||
|
||||
static
|
||||
kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(NR_UE_info_t* const UE, size_t const ue_idx, kpm_act_def_format_1_t const * act_def_fr_1)
|
||||
{
|
||||
kpm_ind_msg_format_1_t msg_frm_1 = {0};
|
||||
|
||||
// Measurement Data contains a set of Meas Records, each collected at each granularity period
|
||||
msg_frm_1.meas_data_lst_len = 1; // (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++)
|
||||
{
|
||||
meas_data_lst_t* meas_data = &msg_frm_1.meas_data_lst[i];
|
||||
|
||||
// Get RLC stats per DRB
|
||||
nr_rlc_statistics_t rlc = active_avg_to_tx_per_drb(UE, i+1);
|
||||
|
||||
// Measurement Record
|
||||
meas_data->meas_record_len = act_def_fr_1->meas_info_lst_len; // record data list length corresponds to info list length from action definition
|
||||
|
||||
meas_data->meas_record_lst = calloc(meas_data->meas_record_len, sizeof(meas_record_lst_t));
|
||||
assert(meas_data->meas_record_lst != NULL && "Memory exhausted");
|
||||
|
||||
for (size_t j = 0; j < meas_data->meas_record_len; j++) // each meas record corresponds to one meas type
|
||||
{
|
||||
meas_record_lst_t* meas_record = &meas_data->meas_record_lst[j];
|
||||
|
||||
// Measurement Type as requested in Action Definition
|
||||
meas_type_t const meas_info_type = act_def_fr_1->meas_info_lst[j].meas_type;
|
||||
|
||||
switch (meas_info_type.type)
|
||||
{
|
||||
case NAME_MEAS_TYPE:
|
||||
{
|
||||
char meas_info_name_str[meas_info_type.name.len + 1];
|
||||
memcpy(meas_info_name_str, meas_info_type.name.buf, meas_info_type.name.len);
|
||||
meas_info_name_str[meas_info_type.name.len] = '\0';
|
||||
|
||||
if (strcmp(meas_info_name_str, "DRB.UEThpDl") == 0) // 3GPP TS 28.522 - section 5.1.1.3.1
|
||||
{
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate DL Thp
|
||||
meas_record->real_val = (double)(rlc.txpdu_bytes - last_dl_total_bytes[ue_idx])*8/act_def_fr_1->gran_period_ms; // [kbps]
|
||||
last_dl_total_bytes[ue_idx] = rlc.txpdu_bytes;
|
||||
}
|
||||
else if (strcmp(meas_info_name_str, "DRB.UEThpUl") == 0) // 3GPP TS 28.522 - section 5.1.1.3.3
|
||||
{
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
|
||||
// Calculate UL Thp
|
||||
meas_record->real_val = (double)(rlc.rxpdu_bytes - last_ul_total_bytes[ue_idx])*8/act_def_fr_1->gran_period_ms; // [kbps]
|
||||
last_ul_total_bytes[ue_idx] = rlc.rxpdu_bytes;
|
||||
}
|
||||
else if (strcmp(meas_info_name_str, "DRB.RlcSduDelayDl") == 0) // 3GPP TS 28.522 - section 5.1.3.3.3
|
||||
{
|
||||
meas_record->value = REAL_MEAS_VALUE;
|
||||
|
||||
// Get the value of sojourn time at the RLC buffer
|
||||
if (act_def_fr_1->gran_period_ms == 100)
|
||||
{
|
||||
meas_record->real_val = rlc.txsdu_avg_time_to_tx; // [μs]
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false && "Update the time window per packet sojourn time");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_MEAS_TYPE:
|
||||
assert(false && "ID Measurement Type not yet implemented");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false && "Measurement Type not recognized");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Measurement Information - OPTIONAL
|
||||
msg_frm_1.meas_info_lst_len = act_def_fr_1->meas_info_lst_len;
|
||||
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" );
|
||||
|
||||
// Get measInfo from action definition
|
||||
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 = act_def_fr_1->meas_info_lst[i].meas_type.type;
|
||||
// Measurement Name
|
||||
if (act_def_fr_1->meas_info_lst[i].meas_type.type == NAME_MEAS_TYPE) {
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.buf = calloc(act_def_fr_1->meas_info_lst[i].meas_type.name.len, sizeof(uint8_t));
|
||||
memcpy(msg_frm_1.meas_info_lst[i].meas_type.name.buf, act_def_fr_1->meas_info_lst[i].meas_type.name.buf, act_def_fr_1->meas_info_lst[i].meas_type.name.len);
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.len = act_def_fr_1->meas_info_lst[i].meas_type.name.len;
|
||||
} else {
|
||||
msg_frm_1.meas_info_lst[i].meas_type.id = act_def_fr_1->meas_info_lst[i].meas_type.id;
|
||||
}
|
||||
|
||||
|
||||
// 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_1_t fill_rnd_kpm_ind_msg_frm_1(void)
|
||||
{
|
||||
kpm_ind_msg_format_1_t msg_frm_1 = {0};
|
||||
|
||||
// Measurement Data
|
||||
msg_frm_1.meas_data_lst_len = 1; // (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++)
|
||||
{
|
||||
// Incomplete Flag
|
||||
msg_frm_1.meas_data_lst[i].incomplete_flag = calloc(1, sizeof(enum_value_e));
|
||||
assert(msg_frm_1.meas_data_lst[i].incomplete_flag != NULL && "Memory exhausted");
|
||||
*msg_frm_1.meas_data_lst[i].incomplete_flag = TRUE_ENUM_VALUE;
|
||||
|
||||
// Measurement Record
|
||||
msg_frm_1.meas_data_lst[i].meas_record_len = 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;
|
||||
msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = time_now_us();
|
||||
}
|
||||
}
|
||||
|
||||
// Measurement Information - OPTIONAL
|
||||
msg_frm_1.meas_info_lst_len = 1;
|
||||
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
|
||||
char* s = "timestamp";
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.len = strlen(s) + 1;
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.buf = malloc(strlen(s) + 1);
|
||||
assert(msg_frm_1.meas_info_lst[i].meas_type.name.buf != NULL && "memory exhausted");
|
||||
memcpy(msg_frm_1.meas_info_lst[i].meas_type.name.buf, s, strlen(s));
|
||||
msg_frm_1.meas_info_lst[i].meas_type.name.buf[strlen(s)] = '\0';
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
NR_UE_info_t *ue_list;
|
||||
size_t num_ues;
|
||||
} matched_ues_t;
|
||||
|
||||
static
|
||||
matched_ues_t filter_ues_by_s_nssai_criteria(test_cond_e const * condition, int64_t const value, NR_UE_info_t * ue_list, size_t const num_connected_ues)
|
||||
{
|
||||
matched_ues_t matched_ues = {.num_ues = 0, .ue_list = calloc(num_connected_ues, sizeof(NR_UE_info_t))};
|
||||
assert(matched_ues.ue_list != NULL && "Memory exhausted");
|
||||
|
||||
assert(RC.nb_nr_inst == 1 && "Number of RRC instances greater than 1 not yet implemented");
|
||||
|
||||
// Check if each UE satisfies the given S-NSSAI criteria
|
||||
for (size_t i = 0; i<num_connected_ues; i++)
|
||||
{
|
||||
rrc_gNB_ue_context_t *rrc_ue_context_list = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], ue_list[i].rnti);
|
||||
ngap_gNB_ue_context_t *ngap_ue_context_list = ngap_get_ue_context(rrc_ue_context_list->ue_context.gNB_ue_ngap_id);
|
||||
|
||||
switch (*condition)
|
||||
{
|
||||
case EQUAL_TEST_COND:
|
||||
printf("Condition is SST equal to %lu\r", value);
|
||||
assert(ngap_ue_context_list->gNB_instance[0].s_nssai[0][0].sST == value && "Please, check the condition for S-NSSAI. At the moment, OAI supports eMBB");
|
||||
matched_ues.ue_list[matched_ues.num_ues] = ue_list[i];
|
||||
matched_ues.num_ues++;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false && "Condition not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
return matched_ues;
|
||||
}
|
||||
|
||||
static
|
||||
kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3(const kpm_act_def_format_4_t * act_def_fr_4)
|
||||
{
|
||||
kpm_ind_msg_format_3_t msg_frm_3 = {0};
|
||||
|
||||
// Get the number of connected UEs and its info (RNTI)
|
||||
msg_frm_3.ue_meas_report_lst_len = get_number_connected_ues(); // (rand() % 65535) + 1;
|
||||
assert(msg_frm_3.ue_meas_report_lst_len != 0 && "Number of UEs to report must be greater than 0");
|
||||
|
||||
printf("Number of connected UEs is %lu\n", msg_frm_3.ue_meas_report_lst_len);
|
||||
NR_UE_info_t * ue_list = connected_ues_list();
|
||||
|
||||
|
||||
// Filter the UE by the test condition criteria
|
||||
matched_ues_t matched_ues;
|
||||
|
||||
for (size_t j = 0; j<act_def_fr_4->matching_cond_lst_len; j++)
|
||||
{
|
||||
switch (act_def_fr_4->matching_cond_lst[j].test_info_lst.test_cond_type)
|
||||
{
|
||||
case S_NSSAI_TEST_COND_TYPE:
|
||||
assert(act_def_fr_4->matching_cond_lst[j].test_info_lst.S_NSSAI == TRUE_TEST_COND_TYPE && "Must be true");
|
||||
|
||||
printf("Condition for filtering matching UEs is S-NSSAI\n");
|
||||
matched_ues = filter_ues_by_s_nssai_criteria(act_def_fr_4->matching_cond_lst[j].test_info_lst.test_cond, *act_def_fr_4->matching_cond_lst[j].test_info_lst.int_value, ue_list, msg_frm_3.ue_meas_report_lst_len);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false && "Test condition type not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Fill UE Measurement Reports
|
||||
assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1");
|
||||
msg_frm_3.meas_report_per_ue = calloc(matched_ues.num_ues, sizeof(meas_report_per_ue_t));
|
||||
assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted");
|
||||
|
||||
for (size_t i = 0; i<matched_ues.num_ues; i++)
|
||||
{
|
||||
// Fill UE ID data
|
||||
rrc_gNB_ue_context_t *rrc_ue_context_list = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], matched_ues.ue_list[i].rnti);
|
||||
msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data(rrc_ue_context_list);
|
||||
|
||||
// Fill UE related info
|
||||
msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(&matched_ues.ue_list[i], i, &act_def_fr_4->action_def_format_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* const kpm = (kpm_rd_ind_data_t*)data;
|
||||
|
||||
assert(kpm->act_def!= NULL && "Cannot be NULL");
|
||||
if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){
|
||||
|
||||
for (size_t i = 0; i < kpm->act_def->frm_4.action_def_format_1.meas_info_lst_len; i++)
|
||||
printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst[i].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 = fill_ind_msg();
|
||||
|
||||
kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE;
|
||||
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3(&kpm->act_def->frm_4);
|
||||
} 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;
|
||||
}
|
||||
|
||||
13
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.h
Normal file
13
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
|
||||
#define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H
|
||||
|
||||
#include "E2AP/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
|
||||
|
||||
108
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_rc.c
Normal file
108
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_rc.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "ran_func_rc.h"
|
||||
#include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_rc.h"
|
||||
#include "openair2/E2AP/flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
|
||||
#include "openair2/E2AP/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;
|
||||
}
|
||||
|
||||
15
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_rc.h
Normal file
15
openair2/E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_rc.h
Normal file
@@ -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 "E2AP/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
|
||||
|
||||
73
openair2/E2AP/RAN_FUNCTION/NR/init_ran_func.c
Normal file
73
openair2/E2AP/RAN_FUNCTION/NR/init_ran_func.c
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "init_ran_func.h"
|
||||
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_mac.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_rlc.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_pdcp.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_slice.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_tc.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/CUSTOMIZED/ran_func_gtp.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/O-RAN/ran_func_kpm.h"
|
||||
#include "E2AP/RAN_FUNCTION/NR/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;
|
||||
}
|
||||
|
||||
32
openair2/E2AP/RAN_FUNCTION/NR/init_ran_func.h
Normal file
32
openair2/E2AP/RAN_FUNCTION/NR/init_ran_func.h
Normal file
@@ -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 NR_RAN_FUNC_INIT_E2_H
|
||||
#define NR_RAN_FUNC_INIT_E2_H
|
||||
|
||||
#include "E2AP/flexric/src/sm/sm_io.h"
|
||||
|
||||
sm_io_ag_ran_t init_ran_func_ag(void);
|
||||
|
||||
#endif
|
||||
|
||||
153
openair2/E2AP/README.md
Normal file
153
openair2/E2AP/README.md
Normal file
@@ -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
|
||||
```
|
||||
35
openair2/E2AP/e2_agent_arg.h
Normal file
35
openair2/E2AP/e2_agent_arg.h
Normal file
@@ -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
|
||||
|
||||
|
||||
1
openair2/E2AP/flexric
Submodule
1
openair2/E2AP/flexric
Submodule
Submodule openair2/E2AP/flexric added at 1b4ed2ff53
@@ -2929,3 +2929,29 @@ 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(ENB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT);
|
||||
return (e2_agent_args_t) {0};
|
||||
}
|
||||
e2_agent_args_t dst = {0};
|
||||
|
||||
if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL)
|
||||
dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr;
|
||||
|
||||
if (e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL)
|
||||
dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 "near_ric_ip_addr"
|
||||
//#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"
|
||||
|
||||
@@ -2259,3 +2259,26 @@ 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_SMDIR_IDX].strptr != NULL)
|
||||
dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr;
|
||||
|
||||
if (e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL)
|
||||
dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#endif // E2_AGENT
|
||||
|
||||
@@ -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_ */
|
||||
/** @} */
|
||||
|
||||
@@ -36,10 +36,36 @@ static void nr_rlc_entity_get_stats(
|
||||
nr_rlc_statistics_t *out)
|
||||
{
|
||||
// printf("Stats from the RLC entity asked\n");
|
||||
uint64_t time_now = time_average_now();
|
||||
*out = entity->stats;
|
||||
|
||||
// Get the correct HOL RLC-SDU
|
||||
nr_rlc_sdu_segment_t* sdu;
|
||||
if (entity->stats.mode == NR_RLC_AM) {
|
||||
nr_rlc_entity_am_t* am_entity = (nr_rlc_entity_am_t *) entity;
|
||||
if (am_entity->retransmit_list != NULL) {
|
||||
sdu = am_entity->retransmit_list;
|
||||
} else {
|
||||
sdu = am_entity->tx_list;
|
||||
}
|
||||
} else if (entity->stats.mode == NR_RLC_UM) {
|
||||
nr_rlc_entity_um_t* um_entity = (nr_rlc_entity_um_t *) entity;
|
||||
sdu = um_entity->tx_list;
|
||||
} else {
|
||||
nr_rlc_entity_tm_t* tm_entity = (nr_rlc_entity_tm_t *) entity;
|
||||
sdu = tm_entity->tx_list;
|
||||
}
|
||||
|
||||
// Compute HOL waittime, make sure that segmented packets don't have 'zero' time-of-arrival
|
||||
if (sdu != NULL) {
|
||||
out->txsdu_wt_us = time_now - sdu->sdu->time_of_arrival;
|
||||
} else {
|
||||
// No HOL packets --> wait-time == 0
|
||||
out->txsdu_wt_us = 0;
|
||||
}
|
||||
|
||||
if (entity->avg_time_is_on)
|
||||
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx,
|
||||
time_average_now());
|
||||
out->txsdu_avg_time_to_tx = time_average_get_average(entity->txsdu_avg_time_to_tx, time_now);
|
||||
else
|
||||
out->txsdu_avg_time_to_tx = 0;
|
||||
}
|
||||
@@ -99,7 +125,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
|
||||
ret->common.set_time = nr_rlc_entity_am_set_time;
|
||||
ret->common.discard_sdu = nr_rlc_entity_am_discard_sdu;
|
||||
ret->common.reestablishment = nr_rlc_entity_am_reestablishment;
|
||||
ret->common.delete = nr_rlc_entity_am_delete;
|
||||
ret->common.delete_entity = nr_rlc_entity_am_delete;
|
||||
ret->common.available_tx_space = nr_rlc_entity_am_available_tx_space;
|
||||
ret->common.get_stats = nr_rlc_entity_get_stats;
|
||||
|
||||
@@ -112,8 +138,11 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
|
||||
|
||||
ret->common.stats.mode = NR_RLC_AM;
|
||||
|
||||
ret->common.stats.rxsdu_bytes = 0; // init default arrivals (SDU) counter
|
||||
ret->common.stats.txsdu_bytes = 0; // init default transmits (SDU) counter
|
||||
|
||||
/* let's take average over the last 100 milliseconds
|
||||
* initial_size of 1024 is arbitrary
|
||||
* initial_size of 1024 (packets) is arbitrary
|
||||
*/
|
||||
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
|
||||
|
||||
@@ -158,7 +187,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
|
||||
ret->common.set_time = nr_rlc_entity_um_set_time;
|
||||
ret->common.discard_sdu = nr_rlc_entity_um_discard_sdu;
|
||||
ret->common.reestablishment = nr_rlc_entity_um_reestablishment;
|
||||
ret->common.delete = nr_rlc_entity_um_delete;
|
||||
ret->common.delete_entity = nr_rlc_entity_um_delete;
|
||||
ret->common.available_tx_space = nr_rlc_entity_um_available_tx_space;
|
||||
ret->common.get_stats = nr_rlc_entity_get_stats;
|
||||
|
||||
@@ -198,7 +227,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_tm(
|
||||
ret->common.set_time = nr_rlc_entity_tm_set_time;
|
||||
ret->common.discard_sdu = nr_rlc_entity_tm_discard_sdu;
|
||||
ret->common.reestablishment = nr_rlc_entity_tm_reestablishment;
|
||||
ret->common.delete = nr_rlc_entity_tm_delete;
|
||||
ret->common.delete_entity = nr_rlc_entity_tm_delete;
|
||||
ret->common.available_tx_space = nr_rlc_entity_tm_available_tx_space;
|
||||
ret->common.get_stats = nr_rlc_entity_get_stats;
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ typedef struct {
|
||||
/* TX */
|
||||
uint32_t txpdu_pkts; /* aggregated number of transmitted RLC PDUs */
|
||||
uint32_t txpdu_bytes; /* aggregated amount of transmitted bytes in RLC PDUs */
|
||||
/* TODO? */
|
||||
uint32_t txpdu_wt_ms; /* aggregated head-of-line tx packet waiting time to be transmitted (i.e. send to the MAC layer) */
|
||||
uint32_t txpdu_wt_ms; /* TODO: aggregated head-of-line tx packet waiting time to be transmitted (i.e. send to the MAC layer) */
|
||||
uint32_t txpdu_dd_pkts; /* aggregated number of dropped or discarded tx packets by RLC */
|
||||
uint32_t txpdu_dd_bytes; /* aggregated amount of bytes dropped or discarded tx packets by RLC */
|
||||
uint32_t txpdu_retx_pkts; /* aggregated number of tx pdus/pkts to be re-transmitted (only applicable to RLC AM) */
|
||||
@@ -51,10 +50,8 @@ typedef struct {
|
||||
uint32_t txpdu_segmented; /* aggregated number of segmentations */
|
||||
uint32_t txpdu_status_pkts; /* aggregated number of tx status pdus/pkts (only applicable to RLC AM) */
|
||||
uint32_t txpdu_status_bytes; /* aggregated amount of tx status bytes (only applicable to RLC AM) */
|
||||
/* TODO? */
|
||||
uint32_t txbuf_occ_bytes; /* current tx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
||||
/* TODO? */
|
||||
uint32_t txbuf_occ_pkts; /* current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
uint32_t txbuf_occ_bytes; /* (IMPLEMENTED) transmitting bytes currently in buffer */
|
||||
uint32_t txbuf_occ_pkts; /* TODO: current tx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
/* txbuf_wd_ms: the time window for which the txbuf occupancy value is obtained - NOT IMPLEMENTED */
|
||||
|
||||
/* RX */
|
||||
@@ -71,31 +68,28 @@ typedef struct {
|
||||
/* rxpdu_rotout_ms: flag indicating rx reordering timeout in ms - NOT IMPLEMENTED */
|
||||
/* rxpdu_potout_ms: flag indicating the poll retransmit time out in ms - NOT IMPLEMENTED */
|
||||
/* rxpdu_sptout_ms: flag indicating status prohibit timeout in ms - NOT IMPLEMENTED */
|
||||
/* TODO? */
|
||||
uint32_t rxbuf_occ_bytes; /* current rx buffer occupancy in terms of amount of bytes (average: NOT IMPLEMENTED) */
|
||||
/* TODO? */
|
||||
uint32_t rxbuf_occ_pkts; /* current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
uint32_t rxbuf_occ_bytes; /* (IMPLEMENTED) received bytes currently in buffer */
|
||||
uint32_t rxbuf_occ_pkts; /* TODO: current rx buffer occupancy in terms of number of packets (average: NOT IMPLEMENTED) */
|
||||
|
||||
/* SDU stats */
|
||||
/* TX */
|
||||
uint32_t txsdu_pkts; /* number of SDUs delivered */
|
||||
uint32_t txsdu_bytes; /* number of bytes of SDUs delivered */
|
||||
uint64_t txsdu_bytes; /* (UPDATED) number of SDUs bytes successfully transmitted so far (counter) */
|
||||
/* Average time for an SDU to be passed to MAC:
|
||||
* Actually measures the time it takes for THE FULL SDU to be passed to MAC FOR THE FIRST TIME.
|
||||
* Since the MAC schedules in advance, it does not measure the time of
|
||||
* transmission over the air, just the time to reach the MAC layer.
|
||||
* => to control it, 'txsdu_wt_us' that measures the current HOL-delay is added.
|
||||
*/
|
||||
double txsdu_avg_time_to_tx; /* (100ms-windowed) per-packet sojourn (SDU to PDU) in microseconds */
|
||||
uint32_t txsdu_wt_us; /* HOL delay of the current radio bearer, in microseconds */
|
||||
|
||||
/* RX */
|
||||
uint32_t rxsdu_pkts; /* number of SDUs received */
|
||||
uint32_t rxsdu_bytes; /* number of bytes of SDUs received */
|
||||
uint64_t rxsdu_bytes; /* (UPDATED) number of SDUs bytes arrived so far (counter) */
|
||||
uint32_t rxsdu_dd_pkts; /* number of dropped or discarded SDUs */
|
||||
uint32_t rxsdu_dd_bytes; /* number of bytes of SDUs dropped or discarded */
|
||||
|
||||
/* Average time for an SDU to be passed to MAC.
|
||||
* Actually measures the time it takes for any part of an SDU to be
|
||||
* passed to MAC for the first time, that is: the first TX of (part of) the
|
||||
* SDU.
|
||||
* Since the MAC schedules in advance, it does not measure the time of
|
||||
* transmission over the air, just the time to reach the MAC layer.
|
||||
*/
|
||||
double txsdu_avg_time_to_tx;
|
||||
|
||||
} nr_rlc_statistics_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -120,7 +114,7 @@ typedef struct nr_rlc_entity_t {
|
||||
|
||||
void (*reestablishment)(struct nr_rlc_entity_t *entity);
|
||||
|
||||
void (*delete)(struct nr_rlc_entity_t *entity);
|
||||
void (*delete_entity)(struct nr_rlc_entity_t *entity);
|
||||
|
||||
int (*available_tx_space)(struct nr_rlc_entity_t *entity);
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn)
|
||||
sdu, so);
|
||||
|
||||
entity->common.stats.txsdu_pkts++;
|
||||
entity->common.stats.txsdu_bytes += so;
|
||||
/* AM 'txsdu_bytes' now only count successfully transmitted bytes */
|
||||
// entity->common.stats.txsdu_bytes += so;
|
||||
}
|
||||
|
||||
static void reception_actions(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *pdu)
|
||||
@@ -484,6 +485,8 @@ process_wait_list_head:
|
||||
end_wait_list = prev_wait_list;
|
||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Wait-ACK: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -546,6 +549,8 @@ process_retransmit_list_head:
|
||||
+ cur->size;
|
||||
if (nr_rlc_free_sdu_segment(cur)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Retransmit-ACK: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -604,6 +609,8 @@ nacks_done:
|
||||
end_wait_list = prev_wait_list;
|
||||
if (nr_rlc_free_sdu_segment(cur_wait_list)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Wait-NACK done: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -625,6 +632,8 @@ nacks_done:
|
||||
+ cur->size;
|
||||
if (nr_rlc_free_sdu_segment(cur)) {
|
||||
entity->tx_size -= sdu_size;
|
||||
// Retransmit-NACK done: count as successfully transmitted bytes
|
||||
entity->common.stats.txsdu_bytes += sdu_size;
|
||||
entity->common.sdu_successful_delivery(
|
||||
entity->common.sdu_successful_delivery_data,
|
||||
(nr_rlc_entity_t *)entity, upper_layer_id);
|
||||
@@ -1619,13 +1628,11 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += ret_size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
|
||||
return ret_size;
|
||||
// return serialize_sdu(entity, sdu, buffer, size, p);
|
||||
@@ -1681,7 +1688,6 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
nr_rlc_sdu_segment_t *sdu;
|
||||
|
||||
entity->common.stats.rxsdu_pkts++;
|
||||
entity->common.stats.rxsdu_bytes += size;
|
||||
|
||||
if (size > NR_SDU_MAX) {
|
||||
LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
|
||||
@@ -1705,6 +1711,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
|
||||
}
|
||||
|
||||
entity->tx_size += size;
|
||||
// SDU received: Count as arrival bytes
|
||||
entity->common.stats.rxsdu_bytes += size;
|
||||
|
||||
sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
|
||||
|
||||
@@ -1893,6 +1901,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
|
||||
+ cur->size;
|
||||
|
||||
entity->tx_size -= cur->sdu->size;
|
||||
|
||||
/* Uncomment to assert if SDU are ever discarded */
|
||||
// assert(0 != 0 && "[RLC-TRAP] SDU discard should never be reached!");
|
||||
|
||||
nr_rlc_free_sdu_segment(cur);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,13 +79,11 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
|
||||
/* update buffer status */
|
||||
entity->common.bstatus.tx_size -= sdu->size;
|
||||
|
||||
@@ -521,13 +521,11 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
|
||||
entity->common.stats.txpdu_pkts++;
|
||||
entity->common.stats.txpdu_bytes += size;
|
||||
|
||||
if (sdu->sdu->time_of_arrival) {
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
/* set time_of_arrival to 0 so as to update stats only once */
|
||||
sdu->sdu->time_of_arrival = 0;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
}
|
||||
/* No need to 'zero' time-of-arrival;
|
||||
Segmented packets do need to be duplicated in time-sensitive use cases */
|
||||
uint64_t time_now = time_average_now();
|
||||
uint64_t waited_time = time_now - sdu->sdu->time_of_arrival;
|
||||
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
|
||||
|
||||
nr_rlc_free_sdu_segment(sdu);
|
||||
|
||||
|
||||
@@ -960,13 +960,13 @@ rlc_op_status_t rrc_rlc_config_req (
|
||||
ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ctxt_pP->rntiMaybeUEid);
|
||||
if (srb_flagP) {
|
||||
if (ue->srb[rb_idP-1] != NULL) {
|
||||
ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]);
|
||||
ue->srb[rb_idP-1]->delete_entity(ue->srb[rb_idP-1]);
|
||||
ue->srb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated SRB %ld, do nothing\n", rb_idP);
|
||||
} else {
|
||||
if (ue->drb[rb_idP-1] != NULL) {
|
||||
ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]);
|
||||
ue->drb[rb_idP-1]->delete_entity(ue->drb[rb_idP-1]);
|
||||
ue->drb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated DRB %ld, do nothing\n", rb_idP);
|
||||
@@ -1074,6 +1074,12 @@ const bool nr_rlc_get_statistics(
|
||||
if (rb != NULL) {
|
||||
rb->get_stats(rb, out);
|
||||
ret = true;
|
||||
|
||||
// Patch buffer status using OAI results (no need to change anything in the RB)
|
||||
// rb->set_time(rb, nr_rlc_current_time);
|
||||
nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 1000*1000);
|
||||
out->rxbuf_occ_bytes = oai_stat.status_size;
|
||||
out->txbuf_occ_bytes = oai_stat.tx_size + oai_stat.retx_size;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "NR_RadioBearerConfig.h"
|
||||
#include "NR_CellGroupConfig.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_proto.h"
|
||||
#include "nr_rlc_ue_manager.h"
|
||||
|
||||
struct NR_RLC_Config;
|
||||
struct NR_LogicalChannelConfig;
|
||||
@@ -63,3 +64,5 @@ void nr_rlc_activate_srb0(int rnti, struct gNB_MAC_INST_s *mac, void *rawUE,
|
||||
const uint8_t *sdu,
|
||||
sdu_size_t sdu_len,
|
||||
void *rawUE));
|
||||
|
||||
const bool nr_rlc_get_statistics(int rnti, int srb_flag, int rb_id, nr_rlc_statistics_t *out);
|
||||
|
||||
@@ -128,16 +128,16 @@ void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *_m, int rnti)
|
||||
if (ue->srb0 != NULL) {
|
||||
/* deliver_sdu_data for srb0 is allocated, needs a free() */
|
||||
free(ue->srb0->deliver_sdu_data);
|
||||
ue->srb0->delete(ue->srb0);
|
||||
ue->srb0->delete_entity(ue->srb0);
|
||||
}
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
if (ue->srb[j] != NULL)
|
||||
ue->srb[j]->delete(ue->srb[j]);
|
||||
ue->srb[j]->delete_entity(ue->srb[j]);
|
||||
|
||||
for (j = 0; j < MAX_DRBS_PER_UE; j++)
|
||||
if (ue->drb[j] != NULL)
|
||||
ue->drb[j]->delete(ue->drb[j]);
|
||||
ue->drb[j]->delete_entity(ue->drb[j]);
|
||||
|
||||
free(ue);
|
||||
|
||||
|
||||
@@ -418,8 +418,8 @@ int test_main(void)
|
||||
}
|
||||
}
|
||||
|
||||
gnb->delete(gnb);
|
||||
ue->delete(ue);
|
||||
gnb->delete_entity(gnb);
|
||||
ue->delete_entity(ue);
|
||||
|
||||
free(sdu);
|
||||
free(pdu);
|
||||
|
||||
@@ -68,7 +68,7 @@ rlc_entity_t *new_rlc_entity_am(
|
||||
|
||||
ret->common.reestablishment = rlc_entity_am_reestablishment;
|
||||
|
||||
ret->common.delete = rlc_entity_am_delete;
|
||||
ret->common.delete_entity = rlc_entity_am_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
@@ -120,7 +120,7 @@ rlc_entity_t *new_rlc_entity_um(
|
||||
|
||||
ret->common.reestablishment = rlc_entity_um_reestablishment;
|
||||
|
||||
ret->common.delete = rlc_entity_um_delete;
|
||||
ret->common.delete_entity = rlc_entity_um_delete;
|
||||
|
||||
ret->common.deliver_sdu = deliver_sdu;
|
||||
ret->common.deliver_sdu_data = deliver_sdu_data;
|
||||
|
||||
@@ -48,7 +48,7 @@ typedef struct rlc_entity_t {
|
||||
|
||||
void (*reestablishment)(struct rlc_entity_t *entity);
|
||||
|
||||
void (*delete)(struct rlc_entity_t *entity);
|
||||
void (*delete_entity)(struct rlc_entity_t *entity);
|
||||
|
||||
/* callbacks provided to the RLC module */
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity,
|
||||
|
||||
@@ -950,13 +950,13 @@ rlc_op_status_t rrc_rlc_config_req (
|
||||
ue = rlc_manager_get_ue(rlc_ue_manager, ctxt_pP->rntiMaybeUEid);
|
||||
if (srb_flagP) {
|
||||
if (ue->srb[rb_idP-1] != NULL) {
|
||||
ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]);
|
||||
ue->srb[rb_idP-1]->delete_entity(ue->srb[rb_idP-1]);
|
||||
ue->srb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", (int)rb_idP);
|
||||
} else {
|
||||
if (ue->drb[rb_idP-1] != NULL) {
|
||||
ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]);
|
||||
ue->drb[rb_idP-1]->delete_entity(ue->drb[rb_idP-1]);
|
||||
ue->drb[rb_idP-1] = NULL;
|
||||
} else
|
||||
LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", (int)rb_idP);
|
||||
|
||||
@@ -127,11 +127,11 @@ void rlc_manager_remove_ue(rlc_ue_manager_t *_m, int rnti)
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
if (ue->srb[j] != NULL)
|
||||
ue->srb[j]->delete(ue->srb[j]);
|
||||
ue->srb[j]->delete_entity(ue->srb[j]);
|
||||
|
||||
for (j = 0; j < 5; j++)
|
||||
if (ue->drb[j] != NULL)
|
||||
ue->drb[j]->delete(ue->drb[j]);
|
||||
ue->drb[j]->delete_entity(ue->drb[j]);
|
||||
|
||||
free(ue);
|
||||
|
||||
|
||||
@@ -368,8 +368,8 @@ int test_main(void)
|
||||
}
|
||||
}
|
||||
|
||||
enb->delete(enb);
|
||||
ue->delete(ue);
|
||||
enb->delete_entity(enb);
|
||||
ue->delete_entity(ue);
|
||||
|
||||
free(sdu);
|
||||
free(pdu);
|
||||
|
||||
@@ -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/"
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user