Compare commits

...

50 Commits

Author SHA1 Message Date
Teodora
bb9fca33dc Mini fix for latest commit in oran_jpn branch in flexric 2023-08-01 11:10:04 +02:00
Teodora
d58cb865a3 Updated instructions for E2 agent tutorial 2023-07-31 23:42:16 +02:00
mir
8aff3803ca UDP Classifier activated 2023-06-15 10:36:34 +02:00
Robert Schmidt
44da0814f2 Correctly copy f1ap_ue_context_modification.drbs_to_be_released 2023-06-14 12:58:51 +02:00
mir
9b49be7357 Length bug 2023-06-14 11:42:46 +02:00
Robert Schmidt
ccd635d09f Merge branch 'bearer-control' into oran_jpn 2023-06-14 08:33:29 +02:00
Robert Schmidt
04d981d97b Hacks for UE to keep latency after DRB5 add low 2023-06-14 08:26:53 +02:00
Robert Schmidt
759075a428 Speed up RFsim rfsimulator_write_internal() using SIMD 2023-06-14 08:03:28 +02:00
Robert Schmidt
5e86809bd7 Speed up RFsim rfsimulator_read() using SIMD 2023-06-14 08:03:23 +02:00
Teodora
346ebfff16 Merge remote-tracking branch 'origin/bearer-control' into oran_jpn 2023-06-13 18:40:40 +02:00
mir
87dbdd6e0c F1AP index out of bounds 2023-06-13 16:52:20 +02:00
mir
e17b99067b Restore old RFSim and remove debug printf 2023-06-13 11:54:15 +02:00
Robert Schmidt
71705fb0cf More UBSan 2023-06-13 11:04:30 +02:00
Robert Schmidt
471ee10b14 Fix UB problems found with UBSan 2023-06-13 11:04:38 +02:00
mir
71e019de97 Changed classifier 2023-06-13 09:54:45 +02:00
Robert Schmidt
c218cf14f5 Add newGtpuDeleteOneTunnel() to remove one GTP tunnel 2023-06-12 18:08:10 +02:00
mir
9ec4e23a14 Merge branch 'bearer-control' into oran_jpn 2023-06-12 15:11:02 +02:00
mir
2a3a49b9e8 CU-DU 2023-06-12 14:41:56 +02:00
Robert Schmidt
beadd5109b UE: mark rlc_BearerToReleaseList as NULL if nothing received 2023-06-12 14:20:39 +02:00
Robert Schmidt
dcd0c83b11 Activate SRB2 only once 2023-06-12 14:20:39 +02:00
Robert Schmidt
556b2299b8 fixup 2023-06-12 14:20:39 +02:00
Robert Schmidt
156a49175e rlc_BearerToReleaseList should not be persisted 2023-06-12 12:43:34 +02:00
Robert Schmidt
bc58d63bcf Hacks to make SDAP pass after bearer release 2023-06-12 12:23:29 +02:00
mir
007ae1caa3 SDAP manipulation 2023-06-12 11:44:16 +02:00
Robert Schmidt
457dee8f1c Speed up RFsim rfsimulator_write_internal() using SIMD 2023-06-10 13:42:08 +02:00
Robert Schmidt
31eb6e1b40 Speed up RFsim rfsimulator_read() using SIMD 2023-06-10 13:42:07 +02:00
mir
c0b877704f Merge branch 'bearer-control' into oran_jpn 2023-06-09 09:40:15 +02:00
mir
7e65f31c98 Before merge for OAI UE 2023-06-09 09:33:41 +02:00
Robert Schmidt
8a40be05c1 Make LCID added output debug 2023-06-08 17:31:31 +02:00
Robert Schmidt
f9b4e1a8b4 Make LCID output nicer 2023-06-08 17:31:31 +02:00
Robert Schmidt
cb7b168cdf NAS PDU is optional 2023-06-08 17:15:43 +02:00
mir
720a12bf03 Merge branch 'bearer-control' into oran_jpn 2023-06-08 15:42:24 +02:00
mir
2580b8dc7e Tested with RFSim and simulated events using FlexRIC's oran_jpn branch 2023-06-08 15:18:51 +02:00
Robert Schmidt
5e74a3b64b Add encoding/decoding of UE Ctxt Modif Req DRB Release 2023-06-08 15:16:31 +02:00
Robert Schmidt
f9a0e8a9f9 fix bug (is included in 2023.w22) 2023-06-08 14:40:32 +02:00
Robert Schmidt
c8fbd968e8 Hack to route ping to different bearers 2023-06-08 13:26:53 +02:00
Robert Schmidt
4af29d6420 Basic and crude bearer release 2023-06-08 13:26:52 +02:00
Robert Schmidt
891eaddac8 hack to make classifier work on UE 2023-06-08 13:26:04 +02:00
Robert Schmidt
b76dafac23 Remove RRC handling code from SDAP 2023-06-08 13:26:04 +02:00
mir
2c9b640df9 Naive ICMP classifier added 2023-06-08 13:26:04 +02:00
Robert Schmidt
f5c15847c9 Scheduler: sort second bearer before first one 2023-06-08 13:26:04 +02:00
Robert Schmidt
b1c6a0baba Add bearer 2023-06-08 13:26:03 +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
74 changed files with 2095 additions and 190 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 = oran_jpn

View File

@@ -307,6 +307,19 @@ if (DEBUG_ASN1C)
add_definitions(-DHAVE_CONFIG_H)
endif()
#########################
##### 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 #
##################################################
@@ -1547,6 +1560,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)
@@ -1577,6 +1595,11 @@ add_library(e1_pdcp_if
target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap)
if(E2_AGENT)
# target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func)
target_compile_definitions(L2_NR PRIVATE E2_AGENT)
endif()
add_library(L2_LTE_NR
${L2_RRC_SRC}
@@ -2157,6 +2180,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
@@ -2245,8 +2272,19 @@ 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}
)
if(E2_AGENT)
target_link_libraries(nr-softmodem PRIVATE e2_ran_func)
target_link_libraries(nr-softmodem PRIVATE e2_agent)
target_compile_definitions(nr-softmodem PRIVATE E2_AGENT)
target_compile_definitions(nr-softmodem PRIVATE MIR_FLAG)
endif()
target_link_libraries(nr-softmodem PRIVATE
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
@@ -2265,10 +2303,13 @@ if (ENABLE_LDPC_T1)
add_dependencies(nr-softmodem ldpc_t1)
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)
add_executable(nr-cuup
executables/nr-cuup.c
executables/softmodem-common.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,121 @@
/*
* 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;
}
void rrc_gNB_trigger_release_bearer(int rnti);
int release_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_release_bearer(rnti);
prnt("called rrc_gNB_trigger_release_bearer(%04x)\n", rnti);
return 0;
}
static telnetshell_cmddef_t bearercmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"add_bearer", "[rnti(hex,opt)]", add_bearer},
{"release_bearer", "[rnti(hex,opt)]", release_bearer},
{"", "", NULL},
};
static telnetshell_vardef_t bearervars[] = {
{"", 0, 0, NULL}
};
void add_bearer_cmds(void) {
add_telnetcmd("bearer", bearervars, bearercmds);
}

View File

@@ -23,6 +23,7 @@
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "common/utils/LOG/log.h"
@@ -82,6 +83,7 @@ static void remove_old(time_average_t *t, uint64_t time)
void time_average_add(time_average_t *t, uint64_t time, uint64_t value)
{
//printf("Waited pkt value %ld us size before remove %d\n", value, t->r.size );
remove_old(t, time);
if (t->r.size == t->r.maxsize) {
@@ -111,8 +113,9 @@ double time_average_get_average(time_average_t *t, uint64_t time)
{
remove_old(t, time);
if (t->r.size == 0)
return 0;
if (t->r.size == 0){
return 0.0;
}
return (double)t->accumulated_value / t->r.size;
}

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

@@ -346,7 +346,7 @@ typedef struct f1ap_srb_to_be_setup_s {
typedef struct f1ap_rb_failed_to_be_setup_s {
long rb_id;
} f1ap_rb_failed_to_be_setup_t;
} f1ap_rb_failed_to_be_setup_t, f1ap_drb_to_be_released_t;
typedef struct cu_to_du_rrc_information_s {
uint8_t * cG_ConfigInfo;
@@ -404,6 +404,8 @@ typedef struct f1ap_ue_context_setup_s {
f1ap_srb_to_be_setup_t *srbs_to_be_setup;
uint8_t srbs_to_be_setup_length;
uint8_t srbs_failed_to_be_setup_length;
uint8_t drbs_to_be_released_length;
f1ap_drb_to_be_released_t *drbs_to_be_released;
f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup;
ReconfigurationCompl_t ReconfigComplOutcome;
uint8_t *rrc_container;

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 --init --remote.")
execute_process(COMMAND git submodule init)
execute_process(COMMAND git submodule update --init --remote)
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,214 @@
#include "ran_func_kpm.h"
#include "../../flexric/test/rnd/fill_rnd_data_kpm.h"
#include "../../flexric/src/util/time_now_us.h"
#include <assert.h>
#include <stdio.h>
#include "../../../LAYER2/nr_rlc/nr_rlc_oai_api.h"
// Forward declaration
int get_single_ue_rnti(void);
static
gnb_e2sm_t fill_gnb_data(void)
{
gnb_e2sm_t gnb = {0};
// 6.2.3.16
// Mandatory
// AMF UE NGAP ID
int const rnti = nr_rlc_get_rnti();
// assert(rnti > 0);
gnb.amf_ue_ngap_id = rnti > 0 ? rnti : 112358132134; //gnb.amf_ue_ngap_id = 112358132134; // % 2^40;
// Mandatory
//GUAMI 6.2.3.17
gnb.guami.plmn_id = (e2sm_plmn_t) {.mcc = 505, .mnc = 1, .mnc_digit_len = 2};
gnb.guami.amf_region_id = (rand() % 2^8) + 0;
gnb.guami.amf_set_id = (rand() % 2^10) + 0;
gnb.guami.amf_ptr = (rand() % 2^6) + 0;
return gnb;
}
static
ue_id_e2sm_t fill_ue_id_data(void)
{
ue_id_e2sm_t ue_id_data = {0};
ue_id_data.type = GNB_UE_ID_E2SM;
ue_id_data.gnb = fill_gnb_data();
return ue_id_data;
}
static
kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(void)
{
kpm_ind_msg_format_1_t msg_frm_1 = {0};
int rnti = get_single_ue_rnti();
if(rnti == -1){
//printf("Unable to find RNTI in RRC, trying in RLC \n");
rnti = nr_rlc_get_rnti();
}
assert(rnti != -1);
int const srb_flag = 0;
int const rb_id = 1;
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;
msg_frm_1.meas_data_lst_len = num_drbs; // (rand() % 65535) + 1;
msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst));
assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" );
for (size_t i = 0; i < msg_frm_1.meas_data_lst_len; i++){
// Measurement Record
msg_frm_1.meas_data_lst[i].meas_record_len = 1; // (rand() % 65535) + 1;
msg_frm_1.meas_data_lst[i].meas_record_lst = calloc(msg_frm_1.meas_data_lst[i].meas_record_len, sizeof(meas_record_lst_t));
assert(msg_frm_1.meas_data_lst[i].meas_record_lst != NULL && "Memory exhausted" );
for (size_t j = 0; j < msg_frm_1.meas_data_lst[i].meas_record_len; j++){
msg_frm_1.meas_data_lst[i].meas_record_lst[j].value = REAL_MEAS_VALUE; // rand()%END_MEAS_VALUE;
msg_frm_1.meas_data_lst[i].meas_record_lst[j].real_val = 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 num_ues = 1;
msg_frm_3.ue_meas_report_lst_len = num_ues; // (rand() % 65535) + 1;
msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t));
assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted");
for (size_t i = 0; i < msg_frm_3.ue_meas_report_lst_len; i++)
{
msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst = fill_ue_id_data();
msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1();
}
return msg_frm_3;
}
static
kpm_ric_ind_hdr_format_1_t fill_kpm_ind_hdr_frm_1(void)
{
kpm_ric_ind_hdr_format_1_t hdr_frm_1 = {0};
hdr_frm_1.collectStartTime = time_now_us();
hdr_frm_1.fileformat_version = NULL;
hdr_frm_1.sender_name = calloc(1, sizeof(byte_array_t));
hdr_frm_1.sender_name->buf = calloc(strlen("My OAI-MONO") + 1, sizeof(char));
memcpy(hdr_frm_1.sender_name->buf, "My OAI-MONO", strlen("My OAI-MONO"));
hdr_frm_1.sender_name->len = strlen("My OAI-MONO");
hdr_frm_1.sender_type = calloc(1, sizeof(byte_array_t));
hdr_frm_1.sender_type->buf = calloc(strlen("MONO") + 1, sizeof(char));
memcpy(hdr_frm_1.sender_type->buf, "MONO", strlen("MONO"));
hdr_frm_1.sender_type->len = strlen("MONO");
hdr_frm_1.vendor_name = calloc(1, sizeof(byte_array_t));
hdr_frm_1.vendor_name->buf = calloc(strlen("OAI") + 1, sizeof(char));
memcpy(hdr_frm_1.vendor_name->buf, "OAI", strlen("OAI"));
hdr_frm_1.vendor_name->len = strlen("OAI");
return hdr_frm_1;
}
static
kpm_ind_hdr_t fill_kpm_ind_hdr_sta(void)
{
kpm_ind_hdr_t hdr = {0};
hdr.type = FORMAT_1_INDICATION_HEADER;
hdr.kpm_ric_ind_hdr_format_1 = fill_kpm_ind_hdr_frm_1();
return hdr;
}
void read_kpm_sm(void* data)
{
assert(data != NULL);
//assert(data->type == KPM_STATS_V3_0);
kpm_rd_ind_data_t* kpm = (kpm_rd_ind_data_t*)data;
assert(kpm->act_def!= NULL && "Cannot be NULL");
if(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION){
if(kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond_type == CQI_TEST_COND_TYPE
&& *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.test_cond == GREATERTHAN_TEST_COND){
//printf("Matching condition: UEs with CQI greater than %ld \n", *kpm->act_def->frm_4.matching_cond_lst[0].test_info_lst.int_value );
}
//printf("Parameter to report: %s \n", kpm->act_def->frm_4.action_def_format_1.meas_info_lst->meas_type.name.buf);
kpm->ind.hdr = fill_kpm_ind_hdr_sta();
// 7.8 Supported RIC Styles and E2SM IE Formats
// Format 4 corresponds to indication message 3
kpm->ind.msg.type = FORMAT_3_INDICATION_MESSAGE;
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_sta();
} else {
kpm->ind.hdr = fill_kpm_ind_hdr();
kpm->ind.msg = fill_kpm_ind_msg();
}
}
void read_kpm_setup_sm(void* e2ap)
{
assert(e2ap != NULL);
// assert(e2ap->type == KPM_V3_0_AGENT_IF_E2_SETUP_ANS_V0);
kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap);
kpm->ran_func_def = fill_kpm_ran_func_def();
}
sm_ag_if_ans_t write_ctrl_kpm_sm(void const* src)
{
assert(0 !=0 && "Not supported");
(void)src;
sm_ag_if_ans_t ans = {0};
return ans;
}

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,132 @@
#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>
// Forward declaration forget sins
int get_single_ue_rnti(void);
void rrc_gNB_trigger_new_bearer(int rnti);
void rrc_gNB_trigger_release_bearer(int rnti);
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){
//mir
int const rnti = get_single_ue_rnti();
printf("QoS flow mapping configuration with rnti %d \n", rnti);
e2sm_rc_ctrl_msg_frmt_1_t const* frmt_1 = &ctrl->msg.frmt_1;
printf("int_ran %ld \n", frmt_1->ran_param[0].ran_param_val.flag_true->int_ran);
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);
if(rp[i].ran_param_val.flag_true->int_ran == 5){
printf("[O-RAN RC]: Creating a new bearer\n");
fflush(stdout);
rrc_gNB_trigger_new_bearer(rnti);
} else if(rp[i].ran_param_val.flag_true->int_ran == 4){
printf("[O-RAN RC]: Releasing bearer\n");
fflush(stdout);
rrc_gNB_trigger_release_bearer(rnti);
} else{
assert(0!=0 && "Unknown 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

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

@@ -0,0 +1,156 @@
<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/
git checkout oran_jpn
```
### 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 oran_jpn
```
### 2.2.2 Build FlexRIC
```bash
mkdir build && cd build && cmake .. && make -j8
```
### 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 ("DRB.RlcSduDelayDl" measurement from 3GPP TS 28.552) and RC v01.03 (adding/releasing of DRB RAN Function) 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/mono_gnb_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 aad1ed2f21

View File

@@ -2928,3 +2928,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

@@ -37,9 +37,10 @@ static f1ap_cudu_inst_t *f1_cu_inst[NUMBER_OF_gNB_MAX]= {0};
uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_mod_idP) {
static uint8_t transaction_identifier[NUMBER_OF_gNB_MAX];
transaction_identifier[mod_idP+cu_mod_idP] =
(transaction_identifier[mod_idP+cu_mod_idP] + 1) % F1AP_TRANSACTION_IDENTIFIER_NUMBER;
return transaction_identifier[mod_idP+cu_mod_idP];
transaction_identifier[(mod_idP+cu_mod_idP)%NUMBER_OF_gNB_MAX] =
(transaction_identifier[(mod_idP+cu_mod_idP)%NUMBER_OF_gNB_MAX] + 1) % F1AP_TRANSACTION_IDENTIFIER_NUMBER;
return transaction_identifier[(mod_idP+cu_mod_idP)%NUMBER_OF_gNB_MAX];
}
f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP) {

View File

@@ -694,7 +694,7 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst,
f1ap_ue_context_setup_resp->rnti,
(ebi_t)drbs_setup_item_p->dRBID,
@@ -1560,14 +1560,14 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context
}
/* optional */
if(0){
if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) {
/* c15. DRBs_ToBeReleased_List */
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15);
ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List;
ie15->criticality = F1AP_Criticality_reject;
ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List;
for (int i=0; i<1; i++) {
for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) {
//
asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list,
F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies);
@@ -1578,7 +1578,10 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context
F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item=
&drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item;
/* dRBID */
drbs_toBeReleased_item->dRBID = 30L;
drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id;
//mir
LOG_E(F1AP, "releasing bearer %ld\n", f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
newGtpuDeleteOneTunnel(getCxt(CUtype, instance)->gtpInst, f1ap_ue_context_modification_req->rnti, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1655,7 +1658,7 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(CUtype, instance)->gtpInst,
f1ap_ue_context_modification_resp->rnti,
(ebi_t)drbs_setupmod_item_p->dRBID,

View File

@@ -218,7 +218,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instanceP,
ie6->id = F1AP_ProtocolIE_ID_id_TransactionID;
ie6->criticality = F1AP_Criticality_ignore;
ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID;
ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(f1ap_req(false, instanceP)->gNB_DU_id, f1ap_req(false, instanceP)->gNB_DU_id);
ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0);
/* encode */
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {

View File

@@ -162,7 +162,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport;
@@ -878,7 +878,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t asso
F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0];
F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address);
OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid);
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
drb_p->up_ul_tnl[0].port=getCxt(false,instance)->setupReq.CUport;
@@ -915,6 +915,24 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t asso
}
}
}
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container,
F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false);
if (ieDrb != NULL) {
f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count;
f1ap_ue_context_modification_req->drbs_to_be_released =
calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t));
AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released,
"could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n");
for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) {
F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i];
DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID;
newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->rnti, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
/* RRC Reconfiguration Complete indicator */
F1AP_UEContextModificationRequestIEs_t *ieReconf;
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container,

View File

@@ -2257,3 +2257,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

@@ -61,10 +61,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;
}
}
@@ -74,7 +76,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) {
@@ -84,9 +86,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_D(NR_MAC, "bearer %d LCID %s %d\n", i, lcid < 4 ? "SRB" : "DRB", sched_ctrl->dl_lc_ids[i]);
}
}
}

View File

@@ -43,6 +43,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);

View File

@@ -90,6 +90,44 @@ static int handle_ue_context_drbs_setup(int rnti,
return drbs_len;
}
static int handle_ue_context_drbs_release(int rnti,
int drbs_len,
const f1ap_drb_to_be_released_t *req_drbs,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
/* Note: the actual GTP tunnels are already removed in the F1AP message
* decoding */
for (int i = 0; i < drbs_len; i++) {
const f1ap_drb_to_be_released_t *drb = &req_drbs[i];
long *lcid = malloc(sizeof(*lcid));
AssertFatal(lcid != NULL, "out of memory\n");
*lcid = drb->rb_id + 3; /* LCID is DRB + 3 */
int idx = 0;
while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx];
if (bc->logicalChannelIdentity == *lcid)
break;
++idx;
}
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
nr_rlc_remove_drb(rnti, drb->rb_id);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToReleaseList->list, lcid);
DevAssert(ret == 0);
}
}
assert(cellGroupConfig->rlc_BearerToReleaseList->list.count > 0 && "Something went wrong");
return drbs_len;
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
{
gNB_MAC_INST *mac = RC.nrmac[0];
@@ -196,6 +234,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
UE->CellGroup);
}
if (req->drbs_to_be_released_length > 0) {
resp.drbs_to_be_released_length =
handle_ue_context_drbs_release(req->rnti, req->drbs_to_be_released_length, req->drbs_to_be_released, UE->CellGroup);
}
if (req->rrc_container != NULL)
nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length);
@@ -204,7 +247,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
}
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0) {
/* TODO: if we change e.g. BWP or MCS table, need to automatically call
* configure_UE_BWP() (form nr_mac_update_timers()) after some time? */
@@ -222,6 +265,15 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
/* works? */
nr_mac_update_cellgroup(RC.nrmac[0], req->rnti, UE->CellGroup);
/* remove the rlc_BearerToReleaseList, we don't need it anymore */
if (UE->CellGroup->rlc_BearerToReleaseList != NULL) {
//for (int i = 0; UE->CellGroup->rlc_BearerToReleaseList->list.count; ++i)
// free(UE->CellGroup->rlc_BearerToReleaseList->list.array[i]);
free(UE->CellGroup->rlc_BearerToReleaseList->list.array);
free(UE->CellGroup->rlc_BearerToReleaseList);
UE->CellGroup->rlc_BearerToReleaseList = NULL;
}
}
NR_SCHED_UNLOCK(&mac->sched_lock);

View File

@@ -164,21 +164,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
UE->rnti,
stats->ulsch_total_bytes_scheduled, stats->ul.total_bytes);
for (int lc_id = 0; lc_id < 63; lc_id++) {
if (stats->dl.lc_bytes[lc_id] > 0)
output += snprintf(output,
end - output,
"UE %04x: LCID %d: %"PRIu64" bytes TX\n",
UE->rnti,
lc_id,
stats->dl.lc_bytes[lc_id]);
if (stats->ul.lc_bytes[lc_id] > 0)
output += snprintf(output,
end - output,
"UE %04x: LCID %d: %"PRIu64" bytes RX\n",
UE->rnti,
lc_id,
stats->ul.lc_bytes[lc_id]);
for (int i = 0; i < sched_ctrl->dl_lc_num; i++) {
const int lc_id = sched_ctrl->dl_lc_ids[i];
output += snprintf(output,
end - output,
"UE %04x: LCID %d: TX %9"PRIu64" RX %9"PRIu64" bytes\n",
UE->rnti,
lc_id,
stats->dl.lc_bytes[lc_id],
stats->ul.lc_bytes[lc_id]);
}
}
NR_SCHED_UNLOCK(&gNB->UE_info.mutex);

View File

@@ -908,7 +908,7 @@ static void add_drb(int is_gnb,
__FILE__, __LINE__, __FUNCTION__);
exit(1);
}
LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID/RNTI %ld\n", __FILE__, __FUNCTION__, __LINE__, rntiMaybeUEid);
LOG_I(PDCP, "%s:%s:%d: added DRB %ld for UE ID/RNTI %ld\n", __FILE__, __FUNCTION__, __LINE__, s->drb_Identity, rntiMaybeUEid);
}
void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint)
@@ -938,6 +938,30 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
}
void nr_pdcp_remove_drb(ue_id_t ue_id, int drb_id, int pdu_session_id)
{
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
if (ue && ue->drb[drb_id-1] != NULL) {
ue->drb[drb_id-1]->delete_entity(ue->drb[drb_id-1]);
ue->drb[drb_id-1] = NULL;
nr_sdap_entity_t *sdap = nr_sdap_get_entity(ue_id, pdu_session_id);
if (sdap) {
if (1) {
NR_QFI_t qfi = 6;
nr_sdap_ue_qfi2drb_config(sdap, 0, ue_id, &qfi, 1, 1, false, false);
}
sdap->has_second_bearer = 0;
}
LOG_I(PDCP, "%s:%d:%s: removed drb %d from UE %ld and set SDAP\n", __FILE__, __LINE__, __FUNCTION__, drb_id, ue_id);
} else if (ue) {
LOG_W(PDCP, "%s:%d:%s: error: UE %ld has no DRB %d\n", __FILE__, __LINE__, __FUNCTION__, ue_id, drb_id);
} else {
LOG_E(PDCP, "%s:%d:%s: error: no such UE %ld\n", __FILE__, __LINE__, __FUNCTION__, ue_id);
}
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
}
/* Dummy function due to dependency from LTE libraries */
bool rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP,
LTE_SRB_ToAddModList_t *const srb2add_list,

View File

@@ -55,6 +55,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
uint8_t *const kUPint,
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list);
void nr_pdcp_remove_drb(ue_id_t ue_id, int drb_id, int pdu_session_id);
void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid);
bool nr_pdcp_remove_UE(ue_id_t ue_id);

View File

@@ -30,18 +30,18 @@
#include "LOG/log.h"
#include "common/utils/time_stat.h"
#include <stdio.h>
static void nr_rlc_entity_get_stats(
nr_rlc_entity_t *entity,
nr_rlc_statistics_t *out)
{
// printf("Stats from the RLC entity asked\n");
*out = entity->stats;
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;
// 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());
//printf("txsdu_avg_time_to_tx %lf \n", out->txsdu_avg_time_to_tx );
// else
// out->txsdu_avg_time_to_tx = 0;
}
nr_rlc_entity_t *new_nr_rlc_entity_am(
@@ -112,10 +112,10 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
ret->common.stats.mode = NR_RLC_AM;
/* let's take average over the last 100 milliseconds
/* let's take average over the last 1000 milliseconds
* initial_size of 1024 is arbitrary
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
ret->common.txsdu_avg_time_to_tx = time_average_new(1000 * 1000, 1024);
return (nr_rlc_entity_t *)ret;
}
@@ -167,10 +167,10 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
ret->common.stats.mode = NR_RLC_UM;
/* let's take average over the last 100 milliseconds
/* let's take average over the last 1000 milliseconds
* initial_size of 1024 is arbitrary
*/
ret->common.txsdu_avg_time_to_tx = time_average_new(100 * 1000, 1024);
ret->common.txsdu_avg_time_to_tx = time_average_new(1000 * 1000, 1024);
return (nr_rlc_entity_t *)ret;
}

View File

@@ -24,80 +24,12 @@
#include <stdint.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;
@@ -179,8 +111,7 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
nr_rlc_entity_t *new_nr_rlc_entity_tm(
int tx_maxsize,
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
char *buf, int size),
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity, char *buf, int size),
void *deliver_sdu_data);
#endif /* _NR_RLC_ENTITY_H_ */

View File

@@ -1619,13 +1619,13 @@ 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) {
// 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;
// sdu->sdu->time_of_arrival = 0;
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);
@@ -1716,7 +1716,7 @@ void nr_rlc_entity_am_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)
// if (entity->common.avg_time_is_on)
sdu->sdu->time_of_arrival = time_average_now();
}

View File

@@ -78,14 +78,15 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
entity->tx_size -= sdu->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 */
// 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);
}
*/
/* update buffer status */
entity->common.bstatus.tx_size -= sdu->size;

View File

@@ -521,13 +521,15 @@ 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 */
// 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);
}
*/
nr_rlc_free_sdu_segment(sdu);

View File

@@ -860,6 +860,22 @@ void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Beare
LOG_I(RLC, "%s:%s:%d: added DRB to UE with RNTI 0x%x\n", __FILE__, __FUNCTION__, __LINE__, rnti);
}
void nr_rlc_remove_drb(int rnti, int drb_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
if (ue && ue->drb[drb_id-1] != NULL) {
ue->drb[drb_id-1]->delete(ue->drb[drb_id-1]);
ue->drb[drb_id-1] = NULL;
LOG_I(RLC, "%s:%d:%s: removed drb %d from UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else if (ue) {
LOG_W(RLC, "%s:%d:%s: error: UE %04x has no DRB %d\n", __FILE__, __LINE__, __FUNCTION__, rnti, drb_id);
} else {
LOG_E(RLC, "%s:%d:%s: error: no such UE %04x\n", __FILE__, __LINE__, __FUNCTION__, rnti);
}
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
/* Dummy function due to dependency from LTE libraries */
rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP,
const LTE_SRB_ToAddModList_t * const srb2add_listP,
@@ -1047,6 +1063,16 @@ void nr_rlc_activate_avg_time_to_tx(
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
// mir: Only hacks...
int nr_rlc_get_rnti(void)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
int const rnti = nr_rlc_manager_get_first_ue_rnti(nr_rlc_ue_manager);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return rnti;
}
/* returns false in case of error, true if everything ok */
const bool nr_rlc_get_statistics(
int rnti,
@@ -1067,10 +1093,13 @@ const bool nr_rlc_get_statistics(
if (rb_id >= 1 && rb_id <= 2)
rb = ue->srb[rb_id - 1];
} else {
if (rb_id >= 1 && rb_id <= 5)
if (rb_id >= 1 && rb_id <= 5){
rb = ue->drb[rb_id - 1];
assert(rb != NULL);
}
}
assert(rb != NULL);
if (rb != NULL) {
rb->get_stats(rb, out);
ret = true;

View File

@@ -29,18 +29,102 @@
*/
#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
//#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"
#include <stdbool.h>
#include <stdint.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;
struct NR_RLC_Config;
struct NR_LogicalChannelConfig;
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);
void nr_rlc_remove_drb(int rnti, int drb_id);
void nr_rlc_remove_ue(int rnti);
@@ -63,3 +147,14 @@ 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);
int nr_rlc_get_rnti(void);
#endif

View File

@@ -74,6 +74,18 @@ void nr_rlc_manager_unlock(nr_rlc_ue_manager_t *_m)
}
}
// mir: hack
/* must be called with lock acquired */
int nr_rlc_manager_get_first_ue_rnti(nr_rlc_ue_manager_t *_m)
{
assert(_m != NULL);
nr_rlc_ue_manager_internal_t *m = _m;
int const rnti = m->ue_count > 0 ? m->ue_list[0]->rnti: -1;
return rnti;
}
/* must be called with lock acquired */
nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *_m, int rnti)
{

View File

@@ -48,6 +48,9 @@ void nr_rlc_manager_unlock(nr_rlc_ue_manager_t *m);
nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *m, int rnti);
void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *m, int rnti);
// mir
int nr_rlc_manager_get_first_ue_rnti(nr_rlc_ue_manager_t *_m);
/***********************************************************************/
/* ue functions */
/***********************************************************************/

View File

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

@@ -85,16 +85,13 @@ void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t insta
for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) {
DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j;
transport_layer_addr_t newRemoteAddr;
newRemoteAddr.length = 32; // IPv4
memcpy(newRemoteAddr.buffer,
&drb_p->DlUpParamList[0].tlAddress,
sizeof(in_addr_t));
in_addr_t addr = {0};
memcpy(&addr, &drb_p->DlUpParamList[0].tlAddress, sizeof(in_addr_t));
GtpuUpdateTunnelOutgoingAddressAndTeid(instance,
(ue_id & 0xFFFF),
(ebi_t)drb_p->id,
*(in_addr_t*)&newRemoteAddr.buffer,
addr,
drb_p->DlUpParamList[0].teId);
}
}

View File

@@ -62,6 +62,13 @@ static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
}
if (req->drbs_to_be_released_length > 0) {
int n = req->drbs_to_be_released_length;
f1ap_msg->drbs_to_be_released_length = n;
f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released));
AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n");
memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released));
}
if (req->rrc_container_length > 0) {
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");

View File

@@ -240,6 +240,7 @@ typedef struct gNB_RRC_UE_s {
NR_SRB_ToAddModList_t *SRB_configList;
NR_SRB_ToAddModList_t *SRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
NR_DRB_ToAddModList_t *DRB_configList;
NR_DRB_ToReleaseList_t *DRB_ReleaseList;
NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
drb_t established_drbs[NGAP_MAX_DRBS_PER_UE];

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"
@@ -568,12 +569,8 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_contex
if (!ue_p->DRB_configList)
ue_p->DRB_configList = CALLOC(1, sizeof(*ue_p->DRB_configList));
else
memset(ue_p->DRB_configList, 0, sizeof(*ue_p->DRB_configList));
if (!ue_p->DRB_configList2[xid])
ue_p->DRB_configList2[xid] = CALLOC(1, sizeof(**ue_p->DRB_configList2));
else
memset(ue_p->DRB_configList2[xid], 0, sizeof(**ue_p->DRB_configList2));
for (i = 0; i < ue_p->nb_of_pdusessions; i++) {
if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) {
continue;
@@ -680,7 +677,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
xid,
SRB_configList2,
DRB_configList,
NULL,
ue_p->DRB_ReleaseList,
NULL,
NULL,
NULL,
@@ -691,6 +688,8 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
NULL,
cellGroupConfig);
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n");
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList);
ue_p->DRB_ReleaseList = NULL;
/* Free all NAS PDUs */
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
@@ -1007,20 +1006,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_pdcp_add_srbs(ctxt_pP->enb_flag, ctxt_pP->rntiMaybeUEid, SRB_configList, (ue_p->integrity_algorithm << 4) | ue_p->ciphering_algorithm, kRRCenc, kRRCint);
@@ -2649,10 +2649,14 @@ void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_contex
}
/* Instruction towards the DU for SRB2 configuration */
int nb_srb = 1;
f1ap_srb_to_be_setup_t srbs[nb_srb];
srbs[0].srb_id = 2;
srbs[0].lcid = 2;
int nb_srb = 0;
f1ap_srb_to_be_setup_t srbs[1] = {0};
if (UE->Srb[2].Active == 0) {
UE->Srb[2].Active = 1;
nb_srb = 1;
srbs[0].srb_id = 2;
srbs[0].lcid = 2;
}
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
@@ -3036,6 +3040,154 @@ 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);
}
void rrc_gNB_trigger_release_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;
if (ue->established_drbs[1].status == DRB_INACTIVE) {
LOG_E(RRC, "no second bearer, aborting\n");
return;
}
// don't use E1: bearer release is not implemented, call directly
// into PDCP/SDAP and then send corresponding message via F1
int drb_id = 2;
ue->established_drbs[1].status = DRB_INACTIVE;
ue->DRB_ReleaseList = calloc(1, sizeof(*ue->DRB_ReleaseList));
AssertFatal(ue->DRB_ReleaseList != NULL, "out of memory\n");
NR_DRB_Identity_t *asn1_drb = calloc(1, sizeof(*asn1_drb));
AssertFatal(asn1_drb != NULL, "out of memory\n");
int idx = 0;
while (idx < ue->DRB_configList->list.count) {
const NR_DRB_ToAddMod_t *drbc = ue->DRB_configList->list.array[idx];
if (drbc->drb_Identity == drb_id)
break;
++idx;
}
if (idx < ue->DRB_configList->list.count) {
nr_pdcp_remove_drb(rnti, drb_id, ue->pduSession[0].param.pdusession_id);
asn_sequence_del(&ue->DRB_configList->list, idx, 1);
}
*asn1_drb = drb_id;
asn1cSeqAdd(&ue->DRB_ReleaseList->list, asn1_drb);
f1ap_drb_to_be_released_t drbs_to_be_released = {.rb_id = drb_id};
LOG_E(RRC, "releasing bearer %d\n", drb_id);
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.rnti = ue->rnti,
.mcc = rrc->configuration.mcc[0],
.mnc = rrc->configuration.mnc[0],
.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
.nr_cellid = rrc->nr_cellid,
.servCellId = 0, /* TODO: correct value? */
.srbs_to_be_setup_length = 0,
.srbs_to_be_setup = NULL,
.drbs_to_be_setup_length = 0,
.drbs_to_be_setup = NULL,
.drbs_to_be_released_length = 1,
.drbs_to_be_released = &drbs_to_be_released,
};
assert(ue_context_modif_req.drbs_to_be_released->rb_id < 6 && "Debug assert");
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
}
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

@@ -86,6 +86,18 @@ rrc_gNB_ue_context_t *rrc_gNB_get_ue_context(gNB_RRC_INST *rrc_instance_pP, ue_i
return RB_FIND(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp);
}
// mir
int rrc_gNB_get_first_ue_rnti(gNB_RRC_INST* rrc_instance_pP)
{
assert(rrc_instance_pP != NULL);
rrc_gNB_ue_context_t *ue_context_p;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(rrc_instance_pP->rrc_ue_head))
{
return ue_context_p->ue_context.rnti;
}
return -1;
}
rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_by_rnti(gNB_RRC_INST *rrc_instance_pP, rnti_t rntiP)
{
rrc_gNB_ue_context_t *ue_context_p;

View File

@@ -1197,6 +1197,20 @@ void nr_rrc_ue_process_masterCellGroup(const protocol_ctxt_t *const ctxt_pP,
sizeof(struct NR_CellGroupConfig__rlc_BearerToAddModList));
}
if( cellGroupConfig->rlc_BearerToReleaseList != NULL){
//TODO (perform the RLC bearer addition/modification as specified in 5.3.5.5.4)
if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList != NULL){
// Laurent: there are cases where the not NULL value is also not coming from a previous malloc
// so it is better to let the potential memory leak than corrupting the heap //free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList);
}
NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList = calloc(1, sizeof(struct NR_CellGroupConfig__rlc_BearerToReleaseList));
memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList,cellGroupConfig->rlc_BearerToReleaseList,
sizeof(struct NR_CellGroupConfig__rlc_BearerToReleaseList));
} else {
free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList);
NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList = NULL;
}
if( cellGroupConfig->mac_CellGroupConfig != NULL){
//TODO (configure the MAC entity of this cell group as specified in 5.3.5.5.5)
LOG_I(RRC, "Received mac_CellGroupConfig from gNB\n");
@@ -1948,9 +1962,9 @@ nr_rrc_ue_establish_srb2(
for (cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) {
DRB_id = radioBearerConfig->drb_ToAddModList->list.array[cnt]->drb_Identity;
if (NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]) {
memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1],
radioBearerConfig->drb_ToAddModList->list.array[cnt], sizeof(NR_DRB_ToAddMod_t));
} else {
free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
}
{
//LOG_D(NR_RRC, "Adding DRB %ld %p\n", DRB_id-1, radioBearerConfig->drb_ToAddModList->list.array[cnt]);
NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1] = radioBearerConfig->drb_ToAddModList->list.array[cnt];
int j;
@@ -2001,13 +2015,17 @@ nr_rrc_ue_establish_srb2(
if (radioBearerConfig->drb_ToReleaseList != NULL) {
for (i = 0; i < radioBearerConfig->drb_ToReleaseList->list.count; i++) {
DRB_id = *radioBearerConfig->drb_ToReleaseList->list.array[i];
free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
LOG_W(RRC, "trigger PDCP remove DRB, PDU session is hardcoded to 10!\n");
nr_pdcp_remove_drb(ctxt_pP->rntiMaybeUEid, DRB_id, 10);
//free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]);
}
}
if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList != NULL) {
for (i = 0; i < NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.count; i++) {
NR_LogicalChannelIdentity_t lcid = *NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.array[i];
/* the RLC handles DRB IDs, and not using the LCID! */
nr_rlc_remove_drb(ctxt_pP->rntiMaybeUEid, lcid - 3);
LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (RB lcid %ld gNB %d release) --->][MAC_UE][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id, lcid, 0, ctxt_pP->module_id);
nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,0,lcid,false); //todo handle mac_LogicalChannelConfig

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,20 @@ 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
//static_assert(0!=0 , "Compiling");
int rrc_gNB_get_first_ue_rnti(gNB_RRC_INST* rrc_instance_pP);
int get_single_ue_rnti(void)
{
int rnti = rrc_gNB_get_first_ue_rnti(RC.nrrrc[0]);
return 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 +116,43 @@ 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,
// Flag only for the gNB defined
#ifdef MIR_FLAG
// mir
// Naive L4/L3 packet classifier
struct iphdr* hdr = (struct iphdr*)sdu_buffer;
if(hdr->protocol == IPPROTO_TCP){
struct tcphdr* tcp = (struct tcphdr*)((uint32_t*)hdr + hdr->ihl);
//uint16_t const src_port = ntohs(tcp->source);
uint16_t const dst_port = ntohs(tcp->dest);
//printf("TCP pkt src_port %d dst_port %d \n", src_port, dst_port);
if (entity->is_gnb && entity->has_second_bearer && dst_port != 10101) {
sdap_drb_id += 1;
}
} else if(hdr->protocol == IPPROTO_UDP){
struct udphdr *udp = (struct udphdr *)((uint32_t*)hdr + hdr->ihl);
uint16_t const src_port = ntohs(udp->source);
uint16_t const dst_port = ntohs(udp->dest);
// printf("UDP pkt src_port %d dst_port %d \n", src_port, dst_port);
if (entity->is_gnb && entity->has_second_bearer && dst_port != 10101) {
sdap_drb_id += 1;
}
} else if(hdr->protocol == IPPROTO_ICMP){
//printf("Ping packet detected \n");
if (entity->is_gnb && entity->has_second_bearer) {
sdap_drb_id += 1;
}
printf("ping to bearer %ld\n", sdap_drb_id);
}
#endif
//label:
ret = nr_pdcp_data_req_drb(ctxt_p,
srb_flag,
sdap_drb_id,
mui,
@@ -103,6 +163,11 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity,
sourceL2Id,
destinationL2Id);
// if(!ret && sdap_drb_id == 2){
// sdap_drb_id = 1;
// goto label;
// }
if(!ret)
LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__);
@@ -407,11 +472,12 @@ void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity, rb_id_t p
nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap_tx, ue_id_t ue_id, int pdusession_id, bool is_defaultDRB, uint8_t drb_identity, NR_QFI_t *mapped_qfi_2_add, uint8_t mappedQFIs2AddCount)
{
if (nr_sdap_get_entity(ue_id, pdusession_id)) {
LOG_E(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
LOG_I(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id);
nr_sdap_entity_t *existing_sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id);
rb_id_t pdcp_entity = existing_sdap_entity->default_drb;
if(!is_gnb)
nr_sdap_ue_qfi2drb_config(existing_sdap_entity, pdcp_entity, ue_id, mapped_qfi_2_add, mappedQFIs2AddCount, drb_identity, has_sdap_rx, has_sdap_tx);
existing_sdap_entity->has_second_bearer = 1;
return existing_sdap_entity;
}
@@ -425,6 +491,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap
sdap_entity->ue_id = ue_id;
sdap_entity->pdusession_id = pdusession_id;
sdap_entity->is_gnb = is_gnb;
sdap_entity->tx_entity = nr_sdap_tx_entity;
sdap_entity->rx_entity = nr_sdap_rx_entity;

View File

@@ -77,6 +77,8 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s
typedef struct nr_sdap_entity_s {
ue_id_t ue_id;
rb_id_t default_drb;
int is_gnb;
int has_second_bearer;
int pdusession_id;
qfi2drb_t qfi2drb_table[SDAP_MAX_QFI];
@@ -170,4 +172,7 @@ 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

@@ -763,7 +763,8 @@ static int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, uint32_t s
NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
if (item_p->nAS_PDU)
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
}
}

View File

@@ -119,10 +119,10 @@ do { \
/* Convert an array of char containing vALUE to x */
#define BUFFER_TO_UINT32(buf, x) \
do { \
x = (((uint32_t)(buf)[0] << 24) | \
(uint32_t)((buf)[1] << 16) | \
(uint32_t)((buf)[2] << 8) | \
(uint32_t)((buf)[3]); \
x = (((uint32_t)((buf)[0])) << 24) | \
(((uint32_t)((buf)[1])) << 16) | \
(((uint32_t)((buf)[2])) << 8) | \
(((uint32_t)((buf)[3]))); \
} while (0)
/* Convert an integer on 32 bits to an octet string from aSN1c tool */

View File

@@ -803,6 +803,32 @@ int gtpv1u_create_x2u_tunnel(
AssertFatal( false, "to be developped\n");
}
int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id)
{
pthread_mutex_lock(&globGtp.gtp_lock);
getInstRetInt(compatInst(instance));
auto ue_it = inst->ue2te_mapping.find(ue_id);
if (ue_it == inst->ue2te_mapping.end()) {
LOG_E(GTPU, "%s() no such UE %ld\n", __func__, ue_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return !GTPNOK;
}
auto rb_it = ue_it->second.bearers.find(rb_id);
if (rb_it == ue_it->second.bearers.end()) {
LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return !GTPNOK;
}
int teid = rb_it->second.teid_incoming;
globGtp.te2ue_mapping.erase(teid);
ue_it->second.bearers.erase(rb_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id);
for (auto b: ue_it->second.bearers)
LOG_I(GTPU, "bearer %ld\n", b.first);
return !GTPNOK;
}
int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) {
LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n",
instance, ue_id);

View File

@@ -100,6 +100,7 @@ extern "C" {
in_addr_t newOutgoingAddr,
teid_t newOutgoingTeid);
int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id);
int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id);
int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdusessionid_t *pdusession_id);
instance_t gtpv1Init(openAddr_t context);

View File

@@ -41,6 +41,8 @@
#include <sys/epoll.h>
#include <string.h>
#include <simde/x86/avx2.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include <common/utils/load_module_shlib.h>
@@ -54,7 +56,7 @@
#include "rfsimulator.h"
#define PORT 4043 //default TCP port for this simulator
#define CirSize 6144000 // 100ms is enough
#define CirSize 6144000 // 100ms is enough, needs to be 32 byte-aligned for SIMD
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
@@ -148,7 +150,8 @@ typedef struct {
static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock];
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
int rc = posix_memalign((void**)&ptr->circularBuf, 32, sampleToByte(CirSize,1));
AssertFatal(rc == 0, "posix_memalign(): rc %d, errno %d, %s", rc, errno, strerror(errno));
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
ptr->lastReceivedTS=0;
@@ -620,12 +623,19 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(b->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt];
AssertFatal(nbAnt == 1, "nbAnt %d not handled yet\n", nbAnt);
for(int a=0; a<nbAnt; a++) {
sample_t *in=(sample_t *)samplesVoid[a];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
int s = 0;
for (; s < nsamps - 7; s += 8) {
simde__m256i sample = simde_mm256_loadu_si256(&in[s]);
simde_mm256_storeu_si256(&tmpSamples[s][a], sample);
}
for (; s < nsamps; s++)
tmpSamples[s][a] = in[s];
}
if (b->conn_sock >= 0 ) {
@@ -886,22 +896,49 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
CirSize);
}
else { // no channel modeling
double H_awgn_mimo[4][4] ={{1.0, 0.2, 0.1, 0.05}, //rx 0
{0.2, 1.0, 0.2, 0.1}, //rx 1
{0.1, 0.2, 1.0, 0.2}, //rx 2
{0.05, 0.1, 0.2, 1.0}};//rx 3
// this matrice corresponds to weights as indicated
const unsigned H_awgn_mimo[4][4] = {
{32, 8, 4, 1}, //rx 0: 1.0000, 0.2500, 0.1250, 0.0625
{8, 32, 8, 4}, //rx 1: 0.2500, 1.0000, 0.2500, 0.1250
{4, 8, 32, 8}, //rx 2: 0.1250, 0.2500, 1.0000, 0.2500
{1, 4, 8, 32} //rx 3: 0.0625, 0.1250, 0.2500, 1.0000
};
sample_t *out=(sample_t *)samplesVoid[a];
int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas
int nbAnt_tx = ptr->th.nbAnt > 0 ? ptr->th.nbAnt : 1;
//LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx);
for (int i=0; i < nsamps; i++) {//loop over nsamps
const unsigned h0 = H_awgn_mimo[a][0], h1 = H_awgn_mimo[a][1], h2 = H_awgn_mimo[a][2], h3 = H_awgn_mimo[a][3];
const simde__m256i factor = nbAnt_tx == 1
? simde_mm256_set_epi16(h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0, h0)
: (nbAnt_tx == 2
? simde_mm256_set_epi16(h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1, h0, h1)
: simde_mm256_set_epi16(h0, h1, h2, h3, h0, h1, h2, h3, h0, h1, h2, h3, h0, h1, h2, h3));
int i = 0;
for (; i < nsamps && ((t->nextRxTstamp + i) % 8) != 0; ++i) {
for (int a_tx=0; a_tx<nbAnt_tx; a_tx++) { //sum up signals from nbAnt_tx antennas
out[i].r += (short)(ptr->circularBuf[((t->nextRxTstamp+i)*nbAnt_tx+a_tx)%CirSize].r*H_awgn_mimo[a][a_tx]);
out[i].i += (short)(ptr->circularBuf[((t->nextRxTstamp+i)*nbAnt_tx+a_tx)%CirSize].i*H_awgn_mimo[a][a_tx]);
} // end for a_tx
const sample_t sample = ptr->circularBuf[((t->nextRxTstamp + i) * nbAnt_tx + a_tx) % CirSize];
const unsigned factor = H_awgn_mimo[a][a_tx];
out[i].r += sample.r * factor >> 5;
out[i].i += sample.i * factor >> 5;
}
}
//LOG_I(HW, "nbAnt_tx %d nsamps %d (nextRxTstamp+i) %ld CirSize %d\n",nbAnt_tx, nsamps, t->nextRxTstamp + i, CirSize);
for (; i < nsamps - 7; i+=8) {//loop over nsamps
simde__m256i sample = simde_mm256_loadu_si256(&ptr->circularBuf[(t->nextRxTstamp + i) % CirSize]);
simde__m256i reslo = simde_mm256_srli_epi16(simde_mm256_mullo_epi16(sample, factor), 5);
simde__m256i reshi = simde_mm256_slli_epi16(simde_mm256_mulhi_epi16(sample, factor), 11);
simde__m256i res = simde_mm256_or_si256(reslo, reshi);
simde__m256i out256 = simde_mm256_loadu_si256(&out[i]);
simde_mm256_storeu_si256(&out[i], simde_mm256_adds_epi16(out256, res));
} // end for i (number of samps)
for (; i < nsamps; ++i) {
for (int a_tx=0; a_tx<nbAnt_tx; a_tx++) { //sum up signals from nbAnt_tx antennas
const sample_t sample = ptr->circularBuf[((t->nextRxTstamp + i) * nbAnt_tx + a_tx) % CirSize];
const unsigned factor = H_awgn_mimo[a][a_tx];
out[i].r += sample.r * factor >> 5;
out[i].i += sample.i * factor >> 5;
}
}
} // end of no channel modeling
} // end for a (number of rx antennas)
}

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