Compare commits

...

17 Commits

Author SHA1 Message Date
mir
cf67061721 Compiling E2 + new bearer + RLC sojourn time 2023-06-07 15:50:58 +02:00
mir
7e9a7d902f Merge branch 'e2_sub' into bearer-control 2023-06-07 12:36:39 +02:00
mir
dd124b72d0 Bug and compilation flag added 2023-06-07 12:33:17 +02:00
mir
1327efeeba Merge branch 'pkt_seg_demo' into bearer-control 2023-06-07 09:26:07 +02:00
mir
09c3eb9ba1 Added printf for RLC sojourn time 2023-06-06 18:33:04 +02:00
mir
af66e9f4f3 RLC packet segmentation demo 2023-06-06 18:31:37 +02:00
mir
fe63f1b164 Naive ICMP classifier added 2023-06-06 15:21:19 +02:00
Robert Schmidt
3b6d9f8a5e Scheduler: sort second bearer before first one 2023-06-06 15:21:19 +02:00
Robert Schmidt
a0dfe34260 Add bearer 2023-06-06 15:21:19 +02:00
mir
ad665b707e Deleted some comments from CMakeLists.txt 2023-06-05 12:38:56 +02:00
mir
10aa33f7b6 Changed submodule init and update CMakeLists.txt 2023-06-05 12:15:57 +02:00
mir
18e03f093a Minors 2023-06-05 11:27:27 +02:00
mir
1bed096f37 Changed E2AP README's file folder to openair2/E2AP/README.md 2023-05-29 09:45:05 +02:00
mir
ce510f14c5 Change -e2 to --e2 2023-05-29 09:45:05 +02:00
Teodora
315e5db0c6 Added tutorial instructions 2023-05-29 09:45:05 +02:00
mir
bc09aeb2ef Replaced path 2023-05-29 09:45:05 +02:00
mir
f625cdd20c First Version. Working CU/DU and configuration file from oai conf 2023-05-29 09:45:03 +02:00
54 changed files with 1782 additions and 142 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 = remotes/origin/mir_dev

View File

@@ -328,6 +328,18 @@ endif()
# asn1c skeletons need this
add_definitions(-DHAVE_NETINET_IN_H)
#########################
##### E2 AGENT
#########################
#add_boolean_option() does not work -- why?
set(E2_AGENT "OFF" CACHE STRING "O-RAN E2 Agent")
set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF")
if(E2_AGENT)
set(E2AP_DIR ${OPENAIR2_DIR}/E2AP)
add_subdirectory ("${E2AP_DIR}")
endif()
##################################################
# ASN.1 grammar C code generation & dependencies #
##################################################
@@ -1567,6 +1579,11 @@ add_library(L2
)
target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap)
target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT)
target_link_libraries(L2 PUBLIC e2_agent e2_ran_func)
target_compile_definitions(L2 PRIVATE E2_AGENT)
endif()
add_library(MAC_NR ${MAC_NR_SRC})
target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
@@ -1583,6 +1600,8 @@ add_library(L2_NR
${GNB_APP_SRC}
)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap)
add_library(e1_if
${NR_RRC_DIR}/cucp_cuup_direct.c
${NR_RRC_DIR}/cucp_cuup_e1ap.c
@@ -1597,6 +1616,10 @@ add_library(e1_pdcp_if
target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap)
if(E2_AGENT)
target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func)
target_compile_definitions(L2_NR PRIVATE E2_AGENT)
endif()
add_library(L2_LTE_NR
${L2_RRC_SRC}
@@ -2174,6 +2197,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
@@ -2262,6 +2289,10 @@ add_executable(nr-softmodem
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${T_SOURCE}
${SHLIB_LOADER_SOURCES}
#L2_NR
${L2_NR_SRC}
${MAC_NR_SRC}
${GNB_APP_SRC}
)
target_link_libraries(nr-softmodem PRIVATE
@@ -2270,7 +2301,7 @@ target_link_libraries(nr-softmodem PRIVATE
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
x2ap f1ap m2ap m3ap e1ap
-Wl,--end-group z dl)
-Wl,--end-group z dl f1ap x2ap s1ap ngap nr_rrc )
target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${ATLAS_LIBRARIES})
target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
@@ -2285,6 +2316,14 @@ 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()
target_compile_definitions(nr-softmodem PRIVATE MIR_FLAG)
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

@@ -59,8 +59,13 @@ add_library(telnetsrv_ci MODULE telnetsrv_ci.c)
target_link_libraries(telnetsrv_ci PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_ci)
message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so")
add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_bearer)
# all libraries should be written to root build dir
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)

View File

@@ -0,0 +1,96 @@
/*
* 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
*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0)
static int get_single_ue_rnti(void)
{
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[0]->rrc_ue_head)) {
return ue_context_p->ue_context.rnti;
}
return -1;
}
int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt)
{
if (buf)
ERROR_MSG_RET("no parameter allowed\n");
int rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("different number of UEs\n");
prnt("single UE RNTI %04x\n", rnti);
return 0;
}
void rrc_gNB_trigger_new_bearer(int rnti);
int add_bearer(char *buf, int debug, telnet_printfunc_t prnt)
{
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("no UE found\n");
} else {
rnti = strtol(buf, NULL, 16);
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti);
if (!rrcue)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
rrc_gNB_trigger_new_bearer(rnti);
prnt("called rrc_gNB_trigger_new_bearer(%04x)\n", rnti);
return 0;
}
static telnetshell_cmddef_t bearercmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"add_bearer", "[rnti(hex,opt)]", add_bearer},
{"", "", NULL},
};
static telnetshell_vardef_t bearervars[] = {
{"", 0, 0, NULL}
};
void add_bearer_cmds(void) {
add_telnetcmd("bearer", bearervars, bearercmds);
}

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/init_ran_func.h"
#endif
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -683,6 +689,53 @@ int main( int argc, char **argv ) {
config_sync_var=0;
#ifdef E2_AGENT
//////////////////////////////////
//////////////////////////////////
//// Init the E2 Agent
sm_io_ag_ran_t io = init_ran_func_ag();
fr_args_t args = init_fr_args(0, NULL);
// OAI Wrapper
e2_agent_args_t oai_args = RCconfig_NR_E2agent();
if(oai_args.sm_dir != NULL)
memcpy(args.libs_dir, oai_args.sm_dir, 128);
sleep(1);
const gNB_RRC_INST* rrc = RC.nrrrc[0];
assert(rrc != NULL && "rrc cannot be NULL");
const int mcc = rrc->configuration.mcc[0];
const int mnc = rrc->configuration.mnc[0];
const int mnc_digit_len = rrc->configuration.mnc_digit_length[0];
const ngran_node_t node_type = rrc->node_type;
int nb_id = 0;
int cu_du_id = 0;
if (node_type == ngran_gNB) {
nb_id = rrc->configuration.cell_identity;
} else if (node_type == ngran_gNB_DU) {
cu_du_id = rrc->node_id + 1; // Hack to avoid been 0
nb_id = rrc->configuration.cell_identity;
} else if (node_type == ngran_gNB_CU) {
cu_du_id = rrc->node_id + 1;
nb_id = rrc->configuration.cell_identity;
} else {
LOG_E(NR_RRC, "not supported ran type detect\n");
}
printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
// }
#endif // E2_AGENT
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}

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,12 @@
add_subdirectory(CUSTOMIZED)
add_subdirectory(O-RAN)
add_library(e2_ran_func STATIC
init_ran_func.c
)
target_link_libraries(e2_ran_func
PUBLIC
e2_ran_func_cust
e2_ran_func_oran
)

View File

@@ -0,0 +1,17 @@
add_library(e2_ran_func_cust STATIC
ran_func_gtp.c
ran_func_mac.c
ran_func_pdcp.c
ran_func_rlc.c
ran_func_slice.c
ran_func_tc.c
# For testing purposes
../../flexric/test/rnd/fill_rnd_data_gtp.c
../../flexric/test/rnd/fill_rnd_data_tc.c
../../flexric/test/rnd/fill_rnd_data_mac.c
../../flexric/test/rnd/fill_rnd_data_rlc.c
../../flexric/test/rnd/fill_rnd_data_pdcp.c
../../flexric/test/rnd/fill_rnd_data_slice.c
../../flexric/src/util/time_now_us.c
)

View File

@@ -0,0 +1,24 @@
#include "ran_func_gtp.h"
#include "../../flexric/test/rnd/fill_rnd_data_gtp.h"
#include <assert.h>
void read_gtp_sm(void * data)
{
assert(data != NULL);
gtp_ind_data_t* gtp = (gtp_ind_data_t*)(data);
fill_gtp_ind_data(gtp);
}
void read_gtp_setup_sm(void* data)
{
assert(data != NULL);
assert(0 !=0 && "Not supported");
}
sm_ag_if_ans_t write_ctrl_gtp_sm(void const* src)
{
assert(src != NULL);
assert(0 !=0 && "Not supported");
}

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 "../../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,24 @@
#include "ran_func_mac.h"
#include "../../flexric/test/rnd/fill_rnd_data_mac.h"
#include <assert.h>
void read_mac_sm(void* data)
{
assert(data != NULL);
mac_ind_data_t* mac = (mac_ind_data_t*)data;
fill_mac_ind_data(mac);
}
void read_mac_setup_sm(void* data)
{
assert(data != NULL);
assert(0 !=0 && "Not supported");
}
sm_ag_if_ans_t write_ctrl_mac_sm(void const* data)
{
assert(data != NULL);
assert(0 !=0 && "Not supported");
}

View File

@@ -0,0 +1,12 @@
#ifndef SM_MAC_READ_WRITE_AGENT_H
#define SM_MAC_READ_WRITE_AGENT_H
#include "../../flexric/src/agent/e2_agent_api.h"
void read_mac_sm(void*);
void read_mac_setup_sm(void*);
sm_ag_if_ans_t write_ctrl_mac_sm(void const*);
#endif

View File

@@ -0,0 +1,31 @@
#include "ran_func_pdcp.h"
#include "../../flexric/test/rnd/fill_rnd_data_pdcp.h"
#include <assert.h>
void read_pdcp_sm(void* data)
{
assert(data != NULL);
//assert(data->type == PDCP_STATS_V0);
pdcp_ind_data_t* pdcp = (pdcp_ind_data_t*)data;
fill_pdcp_ind_data(pdcp);
}
void read_pdcp_setup_sm(void* data)
{
assert(data != NULL);
// assert(data->type == PDCP_AGENT_IF_E2_SETUP_ANS_V0 );
assert(0 !=0 && "Not supported");
}
sm_ag_if_ans_t write_ctrl_pdcp_sm(void const* data)
{
assert(data != NULL);
// assert(data->type == PDCP_CTRL_REQ_V0 );
assert(0 !=0 && "Not supported");
sm_ag_if_ans_t ans = {0};
return ans;
}

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 "../../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 "../../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 "../../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 "../../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 "../../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 "../../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 "../../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,7 @@
add_library(e2_ran_func_oran STATIC
ran_func_kpm.c
ran_func_rc.c
# For testing purposes
../../flexric/test/rnd/fill_rnd_data_kpm.c
../../flexric/test/rnd/fill_rnd_data_rc.c
)

View File

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

View File

@@ -0,0 +1,209 @@
#include "ran_func_kpm.h"
#include "../../flexric/test/rnd/fill_rnd_data_kpm.h"
#include "../../flexric/src/util/time_now_us.h"
#include "../../../LAYER2/nr_rlc/nr_rlc_oai_api.h"
//#include "../../../LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
//#include "../../../RRC/NR/nr_rrc_defs.h"
//#include "../../../RRC/NR/rrc_gNB_UE_context.h"
//#include "../../../../common/ran_context.h"
#include <assert.h>
#include <stdio.h>
static
gnb_e2sm_t fill_gnb_data(void)
{
gnb_e2sm_t gnb = {0};
// 6.2.3.16
// Mandatory
// AMF UE NGAP ID
gnb.amf_ue_ngap_id = 112358132134; // % 2^40;
// Mandatory
//GUAMI 6.2.3.17
gnb.guami.plmn_id = (e2sm_plmn_t) {.mcc = 505, .mnc = 1, .mnc_digit_len = 2};
gnb.guami.amf_region_id = (rand() % 2^8) + 0;
gnb.guami.amf_set_id = (rand() % 2^10) + 0;
gnb.guami.amf_ptr = (rand() % 2^6) + 0;
return gnb;
}
static
ue_id_e2sm_t fill_ue_id_data(void)
{
ue_id_e2sm_t ue_id_data = {0};
ue_id_data.type = GNB_UE_ID_E2SM;
ue_id_data.gnb = fill_gnb_data();
return ue_id_data;
}
// Forward declaration
int get_single_ue_rnti(void);
static
kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(void)
{
kpm_ind_msg_format_1_t msg_frm_1 = {0};
int const rnti = get_single_ue_rnti();
int const srb_flag = 0;
int const rb_id = 4;
nr_rlc_statistics_t out[2] = {0};
bool rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id, &out[0]);
assert(rc == true);
rc = nr_rlc_get_statistics(rnti, srb_flag, rb_id + 1, &out[1]);
assert(rc == false && "At least for one bearer");
// Measurement Data
uint32_t num_drbs = 1 + rc;
msg_frm_1.meas_data_lst_len = num_drbs; // (rand() % 65535) + 1;
msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst));
assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" );
for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++){
// Measurement Record
msg_frm_1.meas_data_lst[i].meas_record_len = num_drbs; // (rand() % 65535) + 1;
msg_frm_1.meas_data_lst[i].meas_record_lst = calloc(msg_frm_1.meas_data_lst[i].meas_record_len, sizeof(meas_record_lst_t));
assert(msg_frm_1.meas_data_lst[i].meas_record_lst != NULL && "Memory exhausted" );
for (size_t j = 0; j < msg_frm_1.meas_data_lst[i].meas_record_len; j++){
msg_frm_1.meas_data_lst[i].meas_record_lst[j].value = REAL_MEAS_VALUE; // rand()%END_MEAS_VALUE;
msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = out[0].txsdu_avg_time_to_tx;
}
}
// Measurement Information - OPTIONAL
msg_frm_1.meas_info_lst_len = num_drbs;
msg_frm_1.meas_info_lst = calloc(msg_frm_1.meas_info_lst_len, sizeof(meas_info_format_1_lst_t));
assert(msg_frm_1.meas_info_lst != NULL && "Memory exhausted" );
for (size_t i = 0; i < msg_frm_1.meas_info_lst_len; i++) {
// Measurement Type
msg_frm_1.meas_info_lst[i].meas_type.type = ID_MEAS_TYPE;
// DRB ID
msg_frm_1.meas_info_lst[i].meas_type.id = i;
// Label Information
msg_frm_1.meas_info_lst[i].label_info_lst_len = 1;
msg_frm_1.meas_info_lst[i].label_info_lst = calloc(msg_frm_1.meas_info_lst[i].label_info_lst_len, sizeof(label_info_lst_t));
assert(msg_frm_1.meas_info_lst[i].label_info_lst != NULL && "Memory exhausted" );
for (size_t j = 0; j < msg_frm_1.meas_info_lst[i].label_info_lst_len; j++) {
msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = malloc(sizeof(enum_value_e));
*msg_frm_1.meas_info_lst[i].label_info_lst[j].noLabel = TRUE_ENUM_VALUE;
}
}
return msg_frm_1;
}
static
kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_sta(void)
{
kpm_ind_msg_format_3_t msg_frm_3 = {0};
uint32_t const num_ues = 1;
msg_frm_3.ue_meas_report_lst_len = num_ues; // (rand() % 65535) + 1;
msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t));
assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted");
for (size_t i = 0; i < msg_frm_3.ue_meas_report_lst_len; i++)
{
msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data();
msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1();
}
return msg_frm_3;
}
static
kpm_ric_ind_hdr_format_1_t fill_kpm_ind_hdr_frm_1(void)
{
kpm_ric_ind_hdr_format_1_t hdr_frm_1 = {0};
hdr_frm_1.collectStartTime = time_now_us();
hdr_frm_1.fileformat_version = NULL;
hdr_frm_1.sender_name = calloc(1, sizeof(byte_array_t));
hdr_frm_1.sender_name->buf = calloc(strlen("My OAI-MONO") + 1, sizeof(char));
memcpy(hdr_frm_1.sender_name->buf, "My OAI-MONO", strlen("My OAI-MONO"));
hdr_frm_1.sender_name->len = strlen("My OAI-MONO");
hdr_frm_1.sender_type = calloc(1, sizeof(byte_array_t));
hdr_frm_1.sender_type->buf = calloc(strlen("MONO") + 1, sizeof(char));
memcpy(hdr_frm_1.sender_type->buf, "MONO", strlen("MONO"));
hdr_frm_1.sender_type->len = strlen("MONO");
hdr_frm_1.vendor_name = calloc(1, sizeof(byte_array_t));
hdr_frm_1.vendor_name->buf = calloc(strlen("OAI") + 1, sizeof(char));
memcpy(hdr_frm_1.vendor_name->buf, "OAI", strlen("OAI"));
hdr_frm_1.vendor_name->len = strlen("OAI");
return hdr_frm_1;
}
static
kpm_ind_hdr_t fill_kpm_ind_hdr_sta(void)
{
kpm_ind_hdr_t hdr = {0};
hdr.type = FORMAT_1_INDICATION_HEADER;
hdr.kpm_ric_ind_hdr_format_1 = fill_kpm_ind_hdr_frm_1();
return hdr;
}
void read_kpm_sm(void* data)
{
assert(data != NULL);
kpm_rd_ind_data_t* kpm = (kpm_rd_ind_data_t*)data;
assert(kpm->act_def!= NULL && "Cannot be NULL");
if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){
if(kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond_type == CQI_TEST_COND_TYPE
&& *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond == GREATERTHAN_TEST_COND){
printf("Matching condition: UEs with CQI greater than %ld \n", *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.int_value );
}
printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst->meas_type.name.buf);
kpm->ind.hdr = fill_kpm_ind_hdr_sta();
// 7.8 Supported RIC Styles and E2SM IE Formats
// Format 4 corresponds to indication message 3
kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE;
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_sta();
} else {
kpm->ind.hdr = fill_kpm_ind_hdr();
kpm->ind.msg = fill_kpm_ind_msg();
}
}
void read_kpm_setup_sm(void* e2ap)
{
assert(e2ap != NULL);
// assert(e2ap->type == KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0);
kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap);
kpm->ran_func_def = fill_kpm_ran_func_def();
}
sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src)
{
assert(0 !=0 && "Not supported");
(void)src;
sm_ag_if_ans_t ans = {0};
return ans;
}

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 "../../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 "../../flexric/test/rnd/fill_rnd_data_rc.h"
#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h"
#include <assert.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void read_rc_sm(void* data)
{
assert(data != NULL);
// assert(data->type == RAN_CTRL_STATS_V1_03);
assert(0!=0 && "Not implemented");
}
void read_rc_setup_sm(void* data)
{
assert(data != NULL);
// assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0);
rc_e2_setup_t* rc = (rc_e2_setup_t*)data;
rc->ran_func_def = fill_rc_ran_func_def();
}
sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
{
assert(data != NULL);
// assert(data->type == RAN_CONTROL_CTRL_V1_03 );
rc_ctrl_req_data_t const* ctrl = (rc_ctrl_req_data_t const*)data;
if(ctrl->hdr.format == FORMAT_1_E2SM_RC_CTRL_HDR){
if(ctrl->hdr.frmt_1.ric_style_type == 1 && ctrl->hdr.frmt_1.ctrl_act_id == 2){
printf("QoS flow mapping configuration \n");
e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1;
for(size_t i = 0; i < frmt_1->sz_ran_param; ++i){
seq_ran_param_t const* rp = frmt_1->ran_param;
if(rp[i].ran_param_id == 1){
assert(rp[i].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE );
printf("DRB ID %ld \n", rp[i].ran_param_val.flag_true->int_ran);
} else if(rp[i].ran_param_id == 2){
assert(rp[i].ran_param_val.type == LIST_RAN_PARAMETER_VAL_TYPE);
printf("List of QoS Flows to be modified \n");
for(size_t j = 0; j < ctrl->msg.frmt_1.ran_param[i].ran_param_val.lst->sz_lst_ran_param; ++j){
lst_ran_param_t const* lrp = rp[i].ran_param_val.lst->lst_ran_param;
// The following assertion should be true, but there is a bug in the std
// check src/sm/rc_sm/enc/rc_enc_asn.c:1085 and src/sm/rc_sm/enc/rc_enc_asn.c:984
// assert(lrp[j].ran_param_id == 3);
assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_id == 4) ;
assert(lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.type == ELEMENT_KEY_FLAG_TRUE_RAN_PARAMETER_VAL_TYPE);
int64_t qfi = lrp[j].ran_param_struct.ran_param_struct[0].ran_param_val.flag_true->int_ran;
assert(qfi > -1 && qfi < 65);
assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_id == 5);
assert(lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.type == ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE);
int64_t dir = lrp[j].ran_param_struct.ran_param_struct[1].ran_param_val.flag_false->int_ran;
assert(dir == 0 || dir == 1);
printf("qfi = %ld dir %ld \n", qfi, dir);
}
}
}
}
}
sm_ag_if_ans_t ans = {.type = CTRL_OUTCOME_SM_AG_IF_ANS_V0};
ans.ctrl_out.type = RAN_CTRL_V1_3_AGENT_IF_CTRL_ANS_V0;
return ans;
}
static
void* emulate_rrc_msg(void* ptr)
{
uint32_t* ric_id = (uint32_t*)ptr;
for(size_t i = 0; i < 5; ++i){
usleep(rand()%4000);
rc_ind_data_t* d = calloc(1, sizeof(rc_ind_data_t));
assert(d != NULL && "Memory exhausted");
*d = fill_rnd_rc_ind_data();
async_event_agent_api(*ric_id, d);
printf("Event for RIC Req ID %u generated\n", *ric_id);
}
free(ptr);
return NULL;
}
static
pthread_t t_ran_ctrl;
sm_ag_if_ans_t write_subs_rc_sm(void const* src)
{
assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03);
wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src;
printf("ric req id %d \n", wr_rc->ric_req_id);
uint32_t* ptr = malloc(sizeof(uint32_t));
assert(ptr != NULL);
*ptr = wr_rc->ric_req_id;
int rc = pthread_create(&t_ran_ctrl, NULL, emulate_rrc_msg, ptr);
assert(rc == 0);
sm_ag_if_ans_t ans = {0};
return ans;
}

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 "../../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 "../flexric/src/agent/e2_agent_api.h"
#include "CUSTOMIZED/ran_func_mac.h"
#include "CUSTOMIZED/ran_func_rlc.h"
#include "CUSTOMIZED/ran_func_pdcp.h"
#include "CUSTOMIZED/ran_func_slice.h"
#include "CUSTOMIZED/ran_func_tc.h"
#include "CUSTOMIZED/ran_func_gtp.h"
#include "O-RAN/ran_func_kpm.h"
#include "O-RAN/ran_func_rc.h"
static
void init_read_ind_tbl(read_ind_fp (*read_ind_tbl)[SM_AGENT_IF_READ_V0_END])
{
(*read_ind_tbl)[MAC_STATS_V0] = read_mac_sm;
(*read_ind_tbl)[RLC_STATS_V0] = read_rlc_sm ;
(*read_ind_tbl)[PDCP_STATS_V0] = read_pdcp_sm ;
(*read_ind_tbl)[SLICE_STATS_V0] = read_slice_sm ;
(*read_ind_tbl)[TC_STATS_V0] = read_tc_sm ;
(*read_ind_tbl)[GTP_STATS_V0] = read_gtp_sm ;
(*read_ind_tbl)[KPM_STATS_V3_0] = read_kpm_sm ;
(*read_ind_tbl)[RAN_CTRL_STATS_V1_03] = read_rc_sm;
}
static
void init_read_setup_tbl(read_e2_setup_fp (*read_setup_tbl)[SM_AGENT_IF_E2_SETUP_ANS_V0_END])
{
(*read_setup_tbl)[MAC_AGENT_IF_E2_SETUP_ANS_V0] = read_mac_setup_sm;
(*read_setup_tbl)[RLC_AGENT_IF_E2_SETUP_ANS_V0] = read_rlc_setup_sm ;
(*read_setup_tbl)[PDCP_AGENT_IF_E2_SETUP_ANS_V0] = read_pdcp_setup_sm ;
(*read_setup_tbl)[SLICE_AGENT_IF_E2_SETUP_ANS_V0] = read_slice_setup_sm ;
(*read_setup_tbl)[TC_AGENT_IF_E2_SETUP_ANS_V0] = read_tc_setup_sm ;
(*read_setup_tbl)[GTP_AGENT_IF_E2_SETUP_ANS_V0] = read_gtp_setup_sm ;
(*read_setup_tbl)[KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0] = read_kpm_setup_sm ;
(*read_setup_tbl)[RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0] = read_rc_setup_sm;
}
static
void init_write_ctrl( write_ctrl_fp (*write_ctrl_tbl)[SM_AGENT_IF_WRITE_CTRL_V0_END])
{
(*write_ctrl_tbl)[MAC_CTRL_REQ_V0] = write_ctrl_mac_sm;
(*write_ctrl_tbl)[RLC_CTRL_REQ_V0] = write_ctrl_rlc_sm;
(*write_ctrl_tbl)[PDCP_CTRL_REQ_V0] = write_ctrl_pdcp_sm;
(*write_ctrl_tbl)[SLICE_CTRL_REQ_V0] = write_ctrl_slice_sm;
(*write_ctrl_tbl)[TC_CTRL_REQ_V0] = write_ctrl_tc_sm;
(*write_ctrl_tbl)[GTP_CTRL_REQ_V0] = write_ctrl_gtp_sm;
(*write_ctrl_tbl)[RAN_CONTROL_CTRL_V1_03] = write_ctrl_rc_sm;
}
static
void init_write_subs(write_subs_fp (*write_subs_tbl)[SM_AGENT_IF_WRITE_SUBS_V0_END])
{
(*write_subs_tbl)[MAC_SUBS_V0] = NULL;
(*write_subs_tbl)[RLC_SUBS_V0] = NULL;
(*write_subs_tbl)[PDCP_SUBS_V0] = NULL;
(*write_subs_tbl)[SLICE_SUBS_V0] = NULL;
(*write_subs_tbl)[TC_SUBS_V0] = NULL;
(*write_subs_tbl)[GTP_SUBS_V0] = NULL;
(*write_subs_tbl)[KPM_SUBS_V3_0] = NULL;
(*write_subs_tbl)[RAN_CTRL_SUBS_V1_03] = write_subs_rc_sm;
}
sm_io_ag_ran_t init_ran_func_ag(void)
{
sm_io_ag_ran_t io = {0};
init_read_ind_tbl(&io.read_ind_tbl);
init_read_setup_tbl(&io.read_setup_tbl);
init_write_ctrl(&io.write_ctrl_tbl);
init_write_subs(&io.write_subs_tbl);
return io;
}

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 RAN_FUNC_INIT_E2_H
#define RAN_FUNC_INIT_E2_H
#include "../flexric/src/sm/sm_io.h"
sm_io_ag_ran_t init_ran_func_ag(void);
#endif

155
openair2/E2AP/README.md Normal file
View File

@@ -0,0 +1,155 @@
<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 ef00d05a3f

View File

@@ -2929,3 +2929,25 @@ void read_config_and_init(void) {
RCconfig_RRC(enb_id, RC.rrc[enb_id]);
}
}
#ifdef E2_AGENT
e2_agent_args_t RCconfig_E2agent(void)
{
paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC;
int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT);
if (ret < 0) {
LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT);
return (e2_agent_args_t) {0};
}
return (e2_agent_args_t) {
.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr,
.port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr,
.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr,
};
}
#endif

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 "ip"
//#define E2AGENT_CONFIG_PORT "port"
#define E2AGENT_CONFIG_SMDIR "sm_dir"
static const char* const e2agent_config_ip_default = NULL;
static const char* const e2agent_config_smdir_default = NULL;
//static const uint16_t e2agent_config_port_default = 36421;
#define E2AGENT_PARAMS_DESC { \
{E2AGENT_CONFIG_IP, "RIC IP address", 0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default, TYPE_STRING, 0}, \
{E2AGENT_CONFIG_SMDIR, "Directory with SMs to load", 0, strptr:NULL, defstrval:(char*)e2agent_config_smdir_default, TYPE_STRING, 0}, \
}
/*
// {E2AGENT_CONFIG_PORT, "RIC port", 0, u16ptr:NULL, defuintval:e2agent_config_port_default, TYPE_UINT16, 0}, \
}
*/
#define E2AGENT_CONFIG_IP_IDX 0
#define E2AGENT_CONFIG_SMDIR_IDX 1
//#define E2AGENT_CONFIG_PORT_IDX 2
#endif // E2_AGENT
#include "enb_paramdef_emtc.h"
#include "enb_paramdef_sidelink.h"
#include "enb_paramdef_mce.h"

View File

@@ -1188,7 +1188,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
rrc->um_on_default_drb = 1; // *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
} else if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "cudu") == 0) {
@@ -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_IP_IDX].strptr != NULL)
dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr;
if(e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL)
dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr;
return dst;
}
#endif // E2_AGENT

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

@@ -62,10 +62,12 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
if (rlc_bearer2release_list) {
for (int i = 0; i < rlc_bearer2release_list->list.count; i++) {
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) {
const int lcid = *rlc_bearer2release_list->list.array[i];
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1;
memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs);
sched_ctrl->dl_lc_num--;
LOG_I(NR_MAC, "remove LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
break;
}
}
@@ -75,7 +77,7 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
if (rlc_bearer2add_list) {
// keep lcids
for (int i = 0; i < rlc_bearer2add_list->list.count; i++) {
const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
const uint8_t lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
bool found = false;
for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
if (sched_ctrl->dl_lc_ids[idx] == lcid) {
@@ -85,9 +87,21 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo
}
if (!found) {
/* we assume that the first two are SRB bearers, and we add before
* other DRB */
uint8_t i = 0;
/* go beyond all SRBs */
while (i < sched_ctrl->dl_lc_num && sched_ctrl->dl_lc_ids[i] < 4)
i++;
uint8_t remaining_lcs = sched_ctrl->dl_lc_num - i;
memmove(&sched_ctrl->dl_lc_ids[i + 1], &sched_ctrl->dl_lc_ids[i], sizeof(sched_ctrl->dl_lc_ids[i]) * remaining_lcs);
sched_ctrl->dl_lc_ids[i] = lcid;
sched_ctrl->dl_lc_num++;
sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
LOG_I(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
for (i = 0; i < sched_ctrl->dl_lc_num; ++i)
LOG_E(NR_MAC, "bearer %d LCID %s %d\n", i, lcid < 4 ? "SRB" : "DRB", sched_ctrl->dl_lc_ids[i]);
}
}
}

View File

@@ -44,6 +44,7 @@
/* rlc */
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/RRC/NR/nr_rrc_defs.h"
#include <executables/softmodem-common.h>
extern RAN_CONTEXT_t RC;

View File

@@ -329,7 +329,7 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram
const int lcid = sched_ctrl->dl_lc_ids[i];
const uint16_t rnti = UE->rnti;
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
if (lcid >= DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
continue;
}
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
@@ -626,7 +626,11 @@ static void pf_dl(module_id_t module_id,
/* Calculate coeff */
const NR_bler_options_t *bo = &mac->dl_bler;
const int max_mcs_table = current_BWP->mcsTableIdx == 1 ? 27 : 28;
const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table);
int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table);
if(max_mcs > 10)
max_mcs = 10;
if (bo->harq_round_max == 1)
sched_pdsch->mcs = max_mcs;
else

View File

@@ -32,6 +32,14 @@
#include "openair2/RRC/NR/nr_rrc_proto.h"
#include <stdint.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
/* from OAI */
#include "oai_asn1.h"
#include "nr_pdcp_oai_api.h"
@@ -932,6 +940,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
{
if (drb2add_list != NULL) {
for (int i = 0; i < drb2add_list->list.count; i++) {
// assert(drb2add_list->list.count == rlc_bearer2add_list->list.count );
add_drb(enb_flag, rntiMaybeUEid, reestablish_ue_id, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config, security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, kUPenc, kUPint);
}
} else

View File

@@ -37,11 +37,11 @@ static void nr_rlc_entity_get_stats(
{
// printf("Stats from the RLC entity asked\n");
*out = entity->stats;
if (entity->avg_time_is_on)
// 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());
else
out->txsdu_avg_time_to_tx = 0;
// else
// out->txsdu_avg_time_to_tx = 0;
}
nr_rlc_entity_t *new_nr_rlc_entity_am(

View File

@@ -23,81 +23,13 @@
#define _NR_RLC_ENTITY_H_
#include <stdint.h>
#include "openair2/RRC/NR/rrc_gNB_radio_bearers.h"
#include "../../../openair2/RRC/NR/rrc_gNB_radio_bearers.h"
#include "../../../openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "common/utils/time_stat.h"
#define NR_SDU_MAX 16000 /* max NR PDCP SDU size is 9000, let's take more */
typedef enum {
NR_RLC_AM,
NR_RLC_UM,
NR_RLC_TM,
} nr_rlc_mode_t;
typedef struct {
nr_rlc_mode_t mode; /* AM, UM, or TM */
/* PDU stats */
/* 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_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) */
uint32_t txpdu_retx_bytes; /* aggregated amount of bytes to be re-transmitted (only applicable to RLC AM) */
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) */
/* txbuf_wd_ms: the time window for which the txbuf occupancy value is obtained - NOT IMPLEMENTED */
/* RX */
uint32_t rxpdu_pkts; /* aggregated number of received RLC PDUs */
uint32_t rxpdu_bytes; /* amount of bytes received by the RLC */
uint32_t rxpdu_dup_pkts; /* aggregated number of duplicate packets */
uint32_t rxpdu_dup_bytes; /* aggregated amount of duplicated bytes */
uint32_t rxpdu_dd_pkts; /* aggregated number of rx packets dropped or discarded by RLC */
uint32_t rxpdu_dd_bytes; /* aggregated amount of rx bytes dropped or discarded by RLC */
uint32_t rxpdu_ow_pkts; /* aggregated number of out of window received RLC pdu */
uint32_t rxpdu_ow_bytes; /* aggregated number of out of window bytes received RLC pdu */
uint32_t rxpdu_status_pkts; /* aggregated number of rx status pdus/pkts (only applicable to RLC AM) */
uint32_t rxpdu_status_bytes; /* aggregated amount of rx status bytes (only applicable to RLC AM) */
/* 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) */
/* SDU stats */
/* TX */
uint32_t txsdu_pkts; /* number of SDUs delivered */
uint32_t txsdu_bytes; /* number of bytes of SDUs delivered */
/* RX */
uint32_t rxsdu_pkts; /* number of SDUs received */
uint32_t rxsdu_bytes; /* number of bytes of SDUs received */
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 {
int status_size;
int tx_size;

View File

@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "nr_rlc_pdu.h"
@@ -480,6 +481,12 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
if (pdu_header_size + 1 > size)
return 0;
// mir Save BW when using TCP Cubic
if(pdu_header_size + sdu->size > size ){
return 0;
}
entity->tx_list = entity->tx_list->next;
if (entity->tx_list == NULL)
entity->tx_end = NULL;
@@ -496,8 +503,11 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
if (pdu_size > size) {
nr_rlc_sdu_segment_t *next_sdu;
next_sdu = resegment(sdu, entity, size);
if (next_sdu == NULL)
printf("resegmenting \n");
if (next_sdu == NULL){
printf("next_sdu == NULL \n");
return 0;
}
/* put the second SDU back at the head of the TX list */
next_sdu->next = entity->tx_list;
entity->tx_list = next_sdu;
@@ -511,11 +521,20 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
}
/* update tx_next if the SDU is an SDU segment and is the last */
if (!sdu->is_first && sdu->is_last)
if (!sdu->is_first && sdu->is_last){
printf("Updating the SN \n");
entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus;
}
ret = serialize_sdu(entity, sdu, buffer, size);
//uint8_t* a = (uint8_t*) buffer;
//uint8_t* b = (uint8_t*)(buffer+1);
//uint8_t* c = (uint8_t*)(buffer+2);
//uint8_t* d = (uint8_t*)(buffer+3);
//printf("a %u b %u c %u d %u \n",*a, *b, *c, *d);
entity->tx_size -= sdu->size;
entity->common.stats.txpdu_pkts++;
@@ -525,8 +544,11 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
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;
// sdu->sdu->time_of_arrival = 0;
time_average_add(entity->common.txsdu_avg_time_to_tx, time_now, waited_time);
// double av = time_average_get_average(entity->common.txsdu_avg_time_to_tx, time_average_now() );
// printf("Average time in the RLC SDU %lf us \n", av);
}
nr_rlc_free_sdu_segment(sdu);
@@ -555,6 +577,14 @@ int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity,
return generate_tx_pdu(entity, buffer, size);
}
double nr_rlc_entity_um_sojourn_time(nr_rlc_entity_um_t const *entity)
{
double const av = time_average_get_average(entity->common.txsdu_avg_time_to_tx, time_average_now() );
return av;
}
/*************************************************************************/
/* SDU RX functions */
/*************************************************************************/
@@ -595,8 +625,8 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu)
+ sdu->size;
if (entity->common.avg_time_is_on)
sdu->sdu->time_of_arrival = time_average_now();
// if (entity->common.avg_time_is_on)
sdu->sdu->time_of_arrival = time_average_now();
}
/*************************************************************************/

View File

@@ -77,4 +77,6 @@ void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity);
void nr_rlc_entity_um_delete(nr_rlc_entity_t *entity);
int nr_rlc_entity_um_available_tx_space(nr_rlc_entity_t *entity);
double nr_rlc_entity_um_sojourn_time(nr_rlc_entity_um_t const *entity);
#endif /* _NR_RLC_ENTITY_UM_H_ */

View File

@@ -1048,7 +1048,7 @@ void nr_rlc_activate_avg_time_to_tx(
}
/* returns false in case of error, true if everything ok */
const bool nr_rlc_get_statistics(
bool nr_rlc_get_statistics(
int rnti,
int srb_flag,
int rb_id,

View File

@@ -29,15 +29,100 @@
*/
#include "NR_RLC-BearerConfig.h"
#include "NR_RLC-Config.h"
#include "NR_LogicalChannelIdentity.h"
#include "NR_RadioBearerConfig.h"
#include "NR_CellGroupConfig.h"
#include "openair2/RRC/NR/nr_rrc_proto.h"
#ifndef NR_RLC_OAI_API_H_MIR
#define NR_RLC_OAI_API_H_MIR
struct NR_RLC_Config;
struct NR_LogicalChannelConfig;
//#include "../../../openair2/RRC/NR/nr_rrc_proto.h"
//#include "openair2/../cmake_targets/ran_build/build/openair2/RRC/NR/MESSAGES/NR_RLC-BearerConfig.h"
//#include "NR_RLC-Config.h"
//#include "NR_LogicalChannelIdentity.h"
//#include "NR_RadioBearerConfig.h"
//#include "NR_CellGroupConfig.h"
//#include "openair2/LAYER2/nr_rlc/nr_rlc_entity.h"
#include <stdint.h>
#include <stdbool.h>
typedef int32_t sdu_size_t;
typedef unsigned int logical_chan_id_t;
typedef uint16_t rnti_t;
typedef enum {
NR_RLC_AM,
NR_RLC_UM,
NR_RLC_TM,
} nr_rlc_mode_t;
typedef struct {
nr_rlc_mode_t mode; /* AM, UM, or TM */
/* PDU stats */
/* 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_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) */
uint32_t txpdu_retx_bytes; /* aggregated amount of bytes to be re-transmitted (only applicable to RLC AM) */
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) */
/* txbuf_wd_ms: the time window for which the txbuf occupancy value is obtained - NOT IMPLEMENTED */
/* RX */
uint32_t rxpdu_pkts; /* aggregated number of received RLC PDUs */
uint32_t rxpdu_bytes; /* amount of bytes received by the RLC */
uint32_t rxpdu_dup_pkts; /* aggregated number of duplicate packets */
uint32_t rxpdu_dup_bytes; /* aggregated amount of duplicated bytes */
uint32_t rxpdu_dd_pkts; /* aggregated number of rx packets dropped or discarded by RLC */
uint32_t rxpdu_dd_bytes; /* aggregated amount of rx bytes dropped or discarded by RLC */
uint32_t rxpdu_ow_pkts; /* aggregated number of out of window received RLC pdu */
uint32_t rxpdu_ow_bytes; /* aggregated number of out of window bytes received RLC pdu */
uint32_t rxpdu_status_pkts; /* aggregated number of rx status pdus/pkts (only applicable to RLC AM) */
uint32_t rxpdu_status_bytes; /* aggregated amount of rx status bytes (only applicable to RLC AM) */
/* 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) */
/* SDU stats */
/* TX */
uint32_t txsdu_pkts; /* number of SDUs delivered */
uint32_t txsdu_bytes; /* number of bytes of SDUs delivered */
/* RX */
uint32_t rxsdu_pkts; /* number of SDUs received */
uint32_t rxsdu_bytes; /* number of bytes of SDUs received */
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;
//struct NR_RLC_Config;
//struct NR_LogicalChannelConfig;
typedef struct NR_RLC_BearerConfig NR_RLC_BearerConfig_t;
void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
@@ -63,3 +148,10 @@ 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));
bool nr_rlc_get_statistics(
int rnti,
int srb_flag,
int rb_id,
nr_rlc_statistics_t *out);
#endif

View File

@@ -803,7 +803,7 @@ int16_t do_RRCReconfiguration(
dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie;
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
if (true) {
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
}

View File

@@ -100,8 +100,9 @@ void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t insta
}
}
static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
rrc_gNB_ue_context_t *ue_context_p,
static
int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
rrc_gNB_ue_context_t *ue_context_p,
e1ap_bearer_setup_req_t *const req,
NR_DRB_ToAddModList_t *DRB_configList,
instance_t instance)
@@ -110,6 +111,7 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0};
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
LOG_W(NR_RRC, "recreate existing tunnels, while adding new ones\n");
printf("UE->nb_of_pdusessions %d\n ", UE->nb_of_pdusessions );
for (int i = 0; i < UE->nb_of_pdusessions; i++) {
rrc_pdu_session_param_t *pdu = UE->pduSession + i;
create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id;
@@ -122,14 +124,14 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
create_tunnel_req.num_tunnels = UE->nb_of_pdusessions;
create_tunnel_req.ue_id = UE->rnti;
int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3,
&create_tunnel_req,
&create_tunnel_resp,
nr_pdcp_data_req_drb,
sdap_data_req);
&create_tunnel_req,
&create_tunnel_resp,
nr_pdcp_data_req_drb,
sdap_data_req);
if (ret != 0) {
LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE rnti %ld\n",
create_tunnel_req.ue_id);
create_tunnel_req.ue_id);
return ret;
}
@@ -152,38 +154,81 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
LOG_D(NR_RRC, "Configuring PDCP DRBs for UE %x\n", UE->rnti);
nr_pdcp_add_drbs(ctxt_p->enb_flag,
ctxt_p->rntiMaybeUEid,
0,
DRB_configList,
(UE->integrity_algorithm << 4) | UE->ciphering_algorithm,
kUPenc,
kUPint,
get_softmodem_params()->sa ? UE->masterCellGroup->rlc_BearerToAddModList : NULL);
ctxt_p->rntiMaybeUEid,
0,
DRB_configList,
(UE->integrity_algorithm << 4) | UE->ciphering_algorithm,
kUPenc,
kUPint,
get_softmodem_params()->sa ? UE->masterCellGroup->rlc_BearerToAddModList : NULL);
return ret;
}
static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid)
/*
static NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, NR_SRB_ToAddModList_t *SRB_configList, uint8_t xid)
{
NR_SRB_ToAddModList_t **SRB_configList2 = NULL;
SRB_configList2 = &ue->SRB_configList2[xid];
if (*SRB_configList2 == NULL) {
*SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2));
NR_SRB_ToAddMod_t *SRB2_config = CALLOC(1, sizeof(*SRB2_config));
SRB2_config->srb_Identity = 2;
asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config);
asn1cSeqAdd(&SRB_configList->list, SRB2_config);
}
return SRB_configList2;
}
*/
static
void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid)
{
/*
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
protocol_ctxt_t ctxt = {0};
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
fill_DRB_configList(&ctxt, ue_context_p, xid);
e1ap_bearer_setup_resp_t resp = {0};
resp.numPDUSessions = req->numPDUSessions;
for (int i = 0; i < resp.numPDUSessions; ++i) {
resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
resp_drb->id = req_drb->id;
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
}
// mir
if(UE->DRB_configList != NULL && get_softmodem_params()->sa){
assert(UE->DRB_configList->list.count == UE->masterCellGroup->rlc_BearerToAddModList->list.count);
}
fill_DRB_configList(&ctxt, ue_context_p, xid);
// mir
if(UE->DRB_configList != NULL && get_softmodem_params()->sa){
assert(UE->DRB_configList->list.count == UE->masterCellGroup->rlc_BearerToAddModList->list.count);
}
*/
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[instance], req->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
protocol_ctxt_t ctxt = {0};
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
fill_DRB_configList(&ctxt, ue_context_p, xid);
e1ap_bearer_setup_resp_t resp = {0};
resp.numPDUSessions = req->numPDUSessions;
for (int i = 0; i < resp.numPDUSessions; ++i) {
resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
resp_drb->id = req_drb->id;
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
}
}
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
// GTP tunnel for UL

View File

@@ -48,6 +48,7 @@
#include "common/utils/LOG/log.h"
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "openair2/E1AP/e1ap_asnc.h"
#include "NR_BCCH-BCH-Message.h"
#include "NR_UL-DCCH-Message.h"
@@ -1036,20 +1037,21 @@ static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *co
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti);
ue_id_t reestablish_ue_id = 0;
if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i];
if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++;
reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti;
LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti);
// clear current C-RNTI from map
nr_reestablish_rnti_map->ue_id = 0;
nr_reestablish_rnti_map->c_rnti = 0;
break;
}
}
}
// we don't consider Reestablishment right now, uncomment to prevent segfault
//if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
// for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
// nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &(RC.nrrrc[ctxt_pP->module_id])->nr_reestablish_rnti_map[i];
// if (nr_reestablish_rnti_map->ue_id == ctxt_pP->rntiMaybeUEid) {
// ue_context_pP->ue_context.ue_reconfiguration_after_reestablishment_counter++;
// reestablish_ue_id = nr_reestablish_rnti_map[i].c_rnti;
// LOG_D(NR_RRC, "Removing reestablish_rnti_map[%d] UEid %lx, RNTI %04x\n", i, nr_reestablish_rnti_map->ue_id, nr_reestablish_rnti_map->c_rnti);
// // clear current C-RNTI from map
// nr_reestablish_rnti_map->ue_id = 0;
// nr_reestablish_rnti_map->c_rnti = 0;
// break;
// }
// }
//}
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
nr_pdcp_add_srbs(ctxt_pP->enb_flag,
@@ -2979,6 +2981,93 @@ rrc_gNB_generate_RRCRelease(
/* UE will be freed after UE context release complete */
}
void rrc_gNB_trigger_new_bearer(int rnti)
{
/* get RRC and UE */
gNB_RRC_INST *rrc = RC.nrrrc[0];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, rnti);
if (ue_context_p == NULL) {
LOG_E(RRC, "unknown UE RNTI %04x\n", rnti);
return;
}
gNB_RRC_UE_t *ue = &ue_context_p->ue_context;
/* get the existing PDU sessoin */
if (ue->nb_of_pdusessions < 1) {
LOG_E(RRC, "no PDU session set up yet, cannot create additional bearer\n");
return;
}
if (ue->established_drbs[0].status != DRB_INACTIVE
&& ue->established_drbs[1].status != DRB_INACTIVE) {
LOG_E(RRC, "already have two established bearers, aborting\n");
return;
}
e1ap_bearer_setup_req_t bearer_req = {0};
bearer_req.gNB_cu_cp_ue_id = ue->gNB_ue_ngap_id;
bearer_req.rnti = ue->rnti;
bearer_req.cipheringAlgorithm = ue->ciphering_algorithm;
memcpy(bearer_req.encryptionKey, ue->kgnb, sizeof(ue->kgnb));
bearer_req.integrityProtectionAlgorithm = ue->integrity_algorithm;
memcpy(bearer_req.integrityProtectionKey, ue->kgnb, sizeof(ue->kgnb));
bearer_req.ueDlAggMaxBitRate = 10000; /* probably does not matter */
pdu_session_to_setup_t *pdu = &bearer_req.pduSession[0];
//bearer_req.numPDUSessions++;
bearer_req.numPDUSessions = 1;
//pdu->sessionId = session->pdusession_id;
//pdu->sst = msg->allowed_nssai[i].sST;
//pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
//pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
//pdu->teId = session->gtp_teid;
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
DRB_nGRAN_to_setup_t *drb = &pdu->DRBnGRanList[0];
int drb_id = 2;
drb->id = drb_id;
drb->defaultDRB = E1AP_DefaultDRB_false;
drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap);
drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap);
drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18;
drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18;
drb->discardTimer = E1AP_DiscardTimer_infinity;
drb->reorderingTimer = E1AP_T_Reordering_ms0;
drb->rLC_Mode = E1AP_RLC_Mode_rlc_am;
drb->numCellGroups = 1; // assume one cell group associated with a DRB
for (int k=0; k < drb->numCellGroups; k++) {
cell_group_t *cellGroup = drb->cellGroupList + k;
cellGroup->id = 0; // MCG
}
int xid = rrc_gNB_get_next_transaction_identifier(0);
/* GIGANTIC HACK: DRBs would be added internally in fill_DRB_configList(),
* but it checks and will skip our request because the PDU session is up.
* Below, simply add the new bearer to DRB_configList so the reconfiguration
* will have all bearers */
generateDRB(ue,
drb_id,
&ue->pduSession[0],
rrc->configuration.enable_sdap,
rrc->security.do_drb_integrity,
rrc->security.do_drb_ciphering);
NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue->established_drbs[drb_id - 1]);
asn1cSeqAdd(&ue->DRB_configList->list, DRB_config);
//asn1cSeqAdd(&ue->DRB_configList2[xid]->list, DRB_config);
/* associate the new bearer to it */
ue->xids[xid] = RRC_PDUSESSION_MODIFY;
ue->pduSession[0].xid = xid; // hack: fake xid for ongoing PDU session
LOG_W(RRC, "trigger new bearer %ld for UE %04x xid %d\n", drb->id, ue->rnti, xid);
rrc->cucp_cuup.bearer_context_setup(&bearer_req, 0, xid);
}
int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){
const unsigned int Ttab[4] = {32,64,128,256};
uint8_t Tc;

View File

@@ -731,7 +731,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
{
protocol_ctxt_t ctxt={0};
ngap_pdusession_setup_req_t* msg=&NGAP_PDUSESSION_SETUP_REQ(msg_p);
ngap_pdusession_setup_req_t* msg = &NGAP_PDUSESSION_SETUP_REQ(msg_p);
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], msg->gNB_ue_ngap_id);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
@@ -777,7 +777,7 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
pdu->teId = session->gtp_teid;
memcpy(&pdu->tlAddress, session->upf_addr.buffer, 4); // Fixme: dirty IPv4 target
pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding
pdu->numDRB2Setup = 2; // One DRB per PDU Session. TODO: Remove hardcoding
for (int j=0; j < pdu->numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j;

View File

@@ -25,6 +25,16 @@
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h"
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
@@ -56,6 +66,57 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
return;
}
#ifdef MIR_FLAG
int get_single_ue_rnti(void)
{
NR_UE_info_t *ue = NULL;
UE_iterator(RC.nrmac[0]->UE_info.list, it) {
if (it && ue)
return -1;
if (it)
ue = it;
}
if (!ue)
return -1;
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], ue->rnti);
if (!rrcue)
return -1;
return ue->rnti;
}
//static_assert(0!=0, "Compiled");
static
pthread_once_t once_bearer = PTHREAD_ONCE_INIT;
// Forward declaration. Forget my sins.
void rrc_gNB_trigger_new_bearer(int rnti);
static
uint64_t cnt = 0;
static
void create_bearer(void)
{
int const rnti = get_single_ue_rnti();
assert(rnti > 0 && "Error finding the rnti");
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[0], rnti);
if(!rrcue)
printf("Could not find the UE in RRC \n");
// assert(!rrcue && "Could not find UE");
rrc_gNB_trigger_new_bearer(rnti);
}
#endif
static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
protocol_ctxt_t *ctxt_p,
const srb_flag_t srb_flag,
@@ -92,7 +153,25 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
if(!pdcp_ent_has_sdap){
LOG_D(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id);
ret = nr_pdcp_data_req_drb(ctxt_p,
#ifdef MIR_FLAG
// mir
// Naive L4/L3 packet classifier
struct iphdr* hdr = (struct iphdr*)sdu_buffer;
if(hdr->protocol == IPPROTO_TCP){
printf("TCP packet detected \n");
} else if(hdr->protocol == IPPROTO_UDP){
printf("UDP packet detected \n");
} else if(hdr->protocol == IPPROTO_ICMP){
printf("Ping packet detected \n");
pthread_once(&once_bearer, create_bearer);
sdap_drb_id += 1; //cnt%2;
//cnt++;
}
#endif
ret = nr_pdcp_data_req_drb(ctxt_p,
srb_flag,
sdap_drb_id,
mui,

View File

@@ -170,4 +170,8 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id);
/* Entity Handling Related Functions */
void delete_nr_sdap_entity(ue_id_t ue_id);
// mir hack
int get_single_ue_rnti(void);
#endif

View File

@@ -14,6 +14,7 @@ gNBs =
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
min_rxtxtime=6;
////////// Physical parameters:
@@ -266,3 +267,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/"
};