Compare commits

...

28 Commits
oru ... e2sm

Author SHA1 Message Date
Teodora
f673c16a41 Correctly calculated KPM meas (sojourn time at RLC, DL/UL thp) 2023-07-28 15:23:54 +02:00
Teodora
9e66929379 Corrected the KPM meas names and UE selection criteria changed
to matched criteria as per spec
2023-07-27 11:54:00 +02:00
Teodora
212d698c1b Further cleanup 2023-07-19 10:08:35 +02:00
Teodora
51f44796f2 Added UEs filtering by S-NSSAI criteria; still need some fixes and
cleanup
2023-07-11 17:27:24 +02:00
Teodora
2924ff5303 Added feature of getting multiple UEs for KPM xApp; but needs cleanup 2023-07-07 19:09:06 +02:00
Chieh-Chun Chen
5444a5bb21 Add RAN function for LTE MAC 2023-06-26 18:25:56 +02:00
Chieh-Chun Chen
4ede33ecc9 Add E2 agent and RAN Functions for lte-softmodem 2023-06-26 17:59:58 +02:00
Chieh-Chun Chen
b61adfd371 Fix: rename rlc delete entity 2023-06-26 13:31:27 +02:00
Chieh-Chun Chen
60d0f8c848 Add stop_agent_api() in nr-softmodem.c 2023-06-26 13:03:10 +02:00
Chieh-Chun Chen
12783daf19 Fix: correct cu_du_id 2023-06-26 13:02:52 +02:00
Chieh-Chun Chen
9b90f7fc59 Add the case for handle no UE connected in KPM RF 2023-06-23 18:31:25 +02:00
Chieh-Chun Chen
8c00136d51 Add RLC average SDU waiting time in KPM RF 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
4d2f021b23 Add DL/UL throughput in KPM RF 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
24dfe9eeea Fix KPM RF: get meas info from action definition and add ue info as input to fill kpm ind 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
4893949621 Fix KPM RF: get correct gnb data from RRC UE context 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
e5dc433996 Add more RLC stats (GOL-delay and AVG-soujour) and correct the tx/rxsdu_bytes and tx/rxsdu_occ_bytes 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
4c59901503 Enable RAN function for GTP SM 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
2d1ffc196e Enable RAN function for PDCP SM 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
01a22cab6f Enable RAN function for RLC SM 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
b678c19aef Fix: rename rlc delete entity 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
f681b23916 Enable RAN fcuntion for MAC SM 2023-06-23 17:50:41 +02:00
Chieh-Chun Chen
5973a62606 Set default flexric branch to rebased-mir-dev 2023-06-23 16:05:18 +02:00
Chieh-Chun Chen
1cfd7ee8fb Fix: correct the RAN function CMakeList to include the directories from main CMakeList 2023-06-22 18:13:23 +02:00
mir
cde2fd2bf4 Clang format and warning 2023-06-21 08:21:03 +02:00
mir
0e1aa4e234 near_ric_ip_addr added. The config needs to be defined in OAI's config file 2023-06-19 16:20:22 +02:00
mir
65fb632c70 gitlink to FlexRIC was updated 2023-06-16 14:37:55 +02:00
Robert Schmidt
f2a70d7512 Reference E2 agent tutorial in doc/README.md 2023-06-07 10:46:23 +02:00
mir
6108da45fe Add basic E2 agent through git submodule
- Add E2 agent that leverages FlexRIC e2ap library
- Add documentation in openair2/E2AP/README.md
- Currently, statistics exported are random
2023-06-07 10:46:07 +02:00
75 changed files with 2928 additions and 67 deletions

4
.gitmodules vendored Normal file
View 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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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);

View 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)

View File

@@ -0,0 +1,2 @@
add_subdirectory(LTE)
add_subdirectory(NR)

View File

@@ -0,0 +1,2 @@
add_subdirectory(CUSTOMIZED)
add_subdirectory(O-RAN)

View File

@@ -0,0 +1,2 @@

View 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");
}

View 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

View 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");
}

View 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

View 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;
}

View 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

View 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");
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View File

@@ -0,0 +1,3 @@
RAN Functions as defined by O-RAN

View 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;
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View File

@@ -0,0 +1,2 @@
add_subdirectory(CUSTOMIZED)
add_subdirectory(O-RAN)

View File

@@ -0,0 +1,2 @@

View 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");
}

View 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

View 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");
}

View 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

View 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;
}

View 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

View 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");
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View File

@@ -0,0 +1,3 @@
RAN Functions as defined by O-RAN

View 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;
}

View 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

View 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;
}

View 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

View 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;
}

View 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
View 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
```

View 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

Submodule openair2/E2AP/flexric added at 1b4ed2ff53

View File

@@ -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

View File

@@ -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);

View File

@@ -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"

View File

@@ -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

View File

@@ -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_ */
/** @} */

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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/"
};