Commit 469d58f9 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge branch 'integration_2024_w36' into 'develop'

Integration Branch : 2024 Week 36

See merge request oai/openairinterface5g!2956
parents 69a84825 1691c607
......@@ -23,6 +23,7 @@
cmake_minimum_required (VERSION 3.16)
project (OpenAirInterface LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
#########################################################
# Base directories, compatible with legacy OAI building #
......@@ -30,6 +31,10 @@ project (OpenAirInterface LANGUAGES C CXX)
set (OPENAIR_DIR ${CMAKE_SOURCE_DIR})
include("cmake_targets/macros.cmake")
if(NOT DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_SOURCE_CACHE ~/.cache/cpm/)
endif()
include("cmake_targets/CPM.cmake")
##############################
### CCache: reduce compilation time
......@@ -288,6 +293,8 @@ set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00")
message(STATUS "Selected KPM Version: ${KPM_VERSION}")
add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" ON)
##################################################
# ASN.1 grammar C code generation & dependencies #
##################################################
......@@ -1066,7 +1073,6 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
......@@ -2340,30 +2346,24 @@ if(ENABLE_TESTS)
find_package(GTest)
if (NOT GTest_FOUND)
message(STATUS "GTest package not found, will download googletest automatically. To prevent that install google test on your system (libgtest-dev)")
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG 58d77fa8070e8cec2dc1ed015d66b454c8d78850 # 1.12.1
CPMAddPackage(
NAME googletest
GITHUB_REPOSITORY google/googletest
GIT_TAG release-1.12.1
VERSION 1.12.1
OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" "BUILD_GMOCK OFF"
)
set(BUILD_GMOCK OFF)
set(INSTALL_GTEST OFF)
FetchContent_MakeAvailable(googletest)
add_library(GTest::gtest ALIAS gtest)
add_library(GTest::gtest_main ALIAS gtest_main)
endif()
find_package(benchmark)
if (NOT benchmark_FOUND)
message(STATUS "benchmark package not found, will download benchmark automatically. To prevent that install google benchmark on your system (libbenchmark-dev)")
include(FetchContent)
set(BENCHMARK_ENABLE_TESTING OFF)
FetchContent_Declare(
benchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG v1.9.0
CPMAddPackage(
NAME benchmark
GITHUB_REPOSITORY google/benchmark
VERSION 1.9.0
OPTIONS "BENCHMARK_ENABLE_TESTING OFF"
)
FetchContent_MakeAvailable(benchmark)
endif()
endif()
......
......@@ -450,9 +450,7 @@ class Containerize():
cmd.cd(lSourcePath)
# if asterix, copy the entitlement and subscription manager configurations
if self.host == 'Red Hat':
cmd.run('mkdir -p ./etc-pki-entitlement ./rhsm-conf ./rhsm-ca')
cmd.run('cp /etc/rhsm/rhsm.conf ./rhsm-conf/')
cmd.run('cp /etc/rhsm/ca/redhat-uep.pem ./rhsm-ca/')
cmd.run('mkdir -p ./etc-pki-entitlement')
cmd.run('cp /etc/pki/entitlement/*.pem ./etc-pki-entitlement/')
baseImage = 'ran-base'
......
......@@ -62,12 +62,12 @@ nr_measurement_configuration = {
};
A3 = ({
cell_id = -1; #Default
physCellId = -1; #Default
offset = 10;
hysteresis = 0;
timeToTrigger = 1
}, {
cell_id = 2;
physCellId = 2;
offset = 5;
hysteresis = 1;
timeToTrigger = 2
......
uicc0:
imsi: 208990100001100
key: fec86ba6eb707ed08905757b1bb44b8f
opc: C42449363BBAD02B66D16BC975D77CC1
dnn: oai
nssai_sst: 1
#/* configuration for channel modelisation */
#/* To be included in main config file when */
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
channelmod:
max_chan: 10;
modellist: modellist_rfsimu_1
modellist_rfsimu_1:
- model_name: rfsimu_channel_enB0
type: AWGN
ploss_dB: 20
noise_power_dB: -4
forgetfact: 0
offset: 0
ds_tdl: 0
- model_name: rfsimu_channel_ue0
type: AWGN
ploss_dB: 20
nose_power_dB: -2
forgetfact: 0
offset: 0
ds_tdl: 0
......@@ -30,7 +30,8 @@ FROM ran-base:develop AS ran-tests
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \
DEBIAN_FRONTEND=noninteractive apt-get install --yes \
libgtest-dev
libgtest-dev \
libyaml-cpp-dev
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
......
......@@ -118,7 +118,7 @@ services:
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
- ../../conf_files/nrue.uicc.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
......
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.40.1)
set(CPM_HASH_SUM "117cbf2711572f113bab262933eb5187b08cfc06dce0714a1ee94f2183ddc3ec")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)
include(${CPM_DOWNLOAD_LOCATION})
......@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
DISABLE_HARDWARE_DEPENDENCY="False"
CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CMD="$CMAKE"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer imscope"
TARGET_LIST=""
function print_help() {
......@@ -497,7 +497,7 @@ function main() {
# add some default libraries that should always be built
# for eNB, gNB, UEs, simulators
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts"
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml"
fi
mkdir -p $DIR/$BUILD_DIR/build
......
......@@ -128,6 +128,7 @@ check_supported_distribution() {
"rocky9.1") return 0 ;;
"rocky9.2") return 0 ;;
"rocky9.3") return 0 ;;
"rocky9.4") return 0 ;;
esac
return 1
}
......@@ -589,8 +590,9 @@ check_install_oai_software() {
libtool \
patch \
openssl \
zlib1g-dev \
xxd
zlib1g-dev \
xxd \
libyaml-cpp-dev
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]] || [[ "$OS_DISTRO" == "rocky" ]]; then
......@@ -625,7 +627,8 @@ check_install_oai_software() {
blas \
blas-devel \
vim-common \
zlib-devel
zlib-devel \
yaml-cpp-devel
fi
install_asn1c_from_source $1
......
add_subdirectory(utils)
add_subdirectory(config/yaml)
configure_file(oai_version.h.in oai_version.h @ONLY)
......@@ -293,8 +293,12 @@ configmodule_interface_t *load_configmodule(int argc,
} else if ( i == 1 ) {
/* -O argument doesn't contain ":" separator, assume -O <conf file> option, default cfgmode to libconfig
with one parameter, the path to the configuration file cfgmode must not be NULL */
modeparams=cfgmode;
cfgmode=strdup(CONFIG_LIBCONFIGFILE);
modeparams = cfgmode;
if (strstr(modeparams, ".yaml") != NULL || strstr(modeparams, ".yml") != NULL) {
cfgmode = strdup("yaml");
} else {
cfgmode = strdup(CONFIG_LIBCONFIGFILE);
}
}
static configmodule_interface_t *cfgptr;
if (cfgptr)
......
find_package(yaml-cpp REQUIRED PATHS /usr/lib/aarch64-linux-gnu/pkgconfig/)
# include(FetchContent)
# FetchContent_Declare(
# yaml-cpp
# GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
# GIT_TAG 0.8.0
# )
# FetchContent_GetProperties(yaml-cpp)
# if(NOT yaml-cpp_POPULATED)
# message(STATUS "Fetching yaml-cpp...")
# FetchContent_Populate(yaml-cpp)
# add_subdirectory(${yaml-cpp_SOURCE_DIR} ${yaml-cpp_BINARY_DIR})
# endif()
add_library(params_yaml_static config_yaml.cpp)
target_link_libraries(params_yaml_static PUBLIC UTIL yaml-cpp)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
add_library(params_yaml MODULE config_yaml.cpp)
target_link_libraries(params_yaml PUBLIC UTIL yaml-cpp)
set_target_properties(params_yaml PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
This diff is collapsed.
add_executable(test_yaml_config test_yaml_config.cpp)
target_link_libraries(test_yaml_config PRIVATE params_yaml_static GTest::gtest)
add_dependencies(tests test_yaml_config)
add_test(NAME test_yaml_config
COMMAND ./test_yaml_config)
configure_file(test1.yaml test1.yaml COPYONLY)
configure_file(test_recursion.yaml test_recursion.yaml COPYONLY)
configure_file(test_list.yaml test_list.yaml COPYONLY)
configure_file(test_string.yaml test_string.yaml COPYONLY)
configure_file(test_list_of_mappings.yml test_list_of_mappings.yml COPYONLY)
configure_file(test_int_array.yaml test_int_array.yaml COPYONLY)
test:
value1: 1
value2: 2
value3: 3
test:
array: [1, 2, 3, 4]
array2:
- 1
- 2
- 3
test:
-
value1: 1
value2: 2
value3: 3
-
value1: 4
value2: 5
value3: 6
-
value1: 7
value2: 8
value3: 9
test:
list:
- value1: 1
value2: 3
list:
- value1
- value2
- value3
- value: 2
value2: 6
list:
- value4
- value5
- value6
test:
test1:
test2:
test3:
test4:
value1: 1
value2: 2
value3: 3
test:
stringvalue: testvalue
stringlist:
- testvalue1
- testvalue2
- testvalue3
This diff is collapsed.
## configuring the logging facility
The logging facility is fully configurable and it uses the [config module](../../../config/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify the logging facility behavior
The logging facility is fully configurable and it uses the [config module](../../../../common/config/DOC/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify the logging facility behavior
All logging facility parameters are defined in the log_config section. Some parameters are global to the logging facility, they modify the way messages are printed to stdout. Conversely, some parameters are specific to a component and only modify the behavior for messages issued by a given component. A third type of parameters can be used to activate conditional debug code or dump messages or buffers.
......
......@@ -103,7 +103,7 @@ of wireshark. Adapt as necessary.
2) Then, in the menu, choose `Edit->Preferences`.
3) In the preference window, unroll `Protocols` and configure the following:
**MAC**
**MAC-NR**
Go to `MAC-NR`. Select:
......@@ -117,7 +117,7 @@ For `Source of LCID -> drb channel settings`:
Type `AM, SN Len=18`, same thing for DL RLC Bearer Type.
* Click OK.
**RLC**
**RLC-NR**
Now, go to `RLC-NR`. Select:
......@@ -129,7 +129,7 @@ Now, go to `RLC-NR`. Select:
You don't need to select `May see RLC headers only` and
`Try to reassemble UM frames`.
**PDCP**
**PDCP-NR**
Now, go to `PDCP-NR`. Select what you need in there.
......@@ -146,6 +146,12 @@ You are done with the preferences. You can click OK.
4) Then, in the menu `Analyze`, choose `Enabled Protocols...`.
5) In the new window search for `nr` and select `mac_nr_udp` to have `MAC-NR over UDP`.
**NAS-5GS**
Under `NAS-5GS`, select:
* `Try to detect and decode 5G-EA0 ciphered messages`
And that's it. Maybe other settings can be changed, but those steps should be
enough for a start.
......
......@@ -1161,9 +1161,9 @@ void nr_timer_stop(NR_timer_t *timer)
timer->counter = 0;
}
bool is_nr_timer_active(NR_timer_t timer)
bool nr_timer_is_active(const NR_timer_t *timer)
{
return timer.active;
return timer->active;
}
bool nr_timer_tick(NR_timer_t *timer)
......@@ -1173,23 +1173,23 @@ bool nr_timer_tick(NR_timer_t *timer)
timer->counter += timer->step;
if (timer->target == UINT_MAX) // infinite target, never expires
return false;
expired = nr_timer_expired(*timer);
expired = nr_timer_expired(timer);
if (expired)
timer->active = false;
}
return expired;
}
bool nr_timer_expired(NR_timer_t timer)
bool nr_timer_expired(const NR_timer_t *timer)
{
if (timer.target == UINT_MAX) // infinite target, never expires
if (timer->target == UINT_MAX) // infinite target, never expires
return false;
return (timer.counter >= timer.target);
return timer->counter >= timer->target;
}
uint32_t nr_timer_elapsed_time(NR_timer_t timer)
uint32_t nr_timer_elapsed_time(const NR_timer_t *timer)
{
return timer.counter;
return timer->counter;
}
void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
......
......@@ -163,19 +163,19 @@ void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t ste
* @param timer Timer to be checked
* @return Indication if the timer is expired or not
*/
bool nr_timer_expired(NR_timer_t timer);
bool nr_timer_expired(const NR_timer_t *timer);
/**
* @brief To check if a timer is active
* @param timer Timer to be checked
* @return Indication if the timer is active or not
*/
bool is_nr_timer_active(NR_timer_t timer);
bool nr_timer_is_active(const NR_timer_t *timer);
/**
* @brief To return how much time has passed since start of timer
* @param timer Timer to be checked
* @return Time passed since start of timer
*/
uint32_t nr_timer_elapsed_time(NR_timer_t timer);
uint32_t nr_timer_elapsed_time(const NR_timer_t *timer);
extern const nr_bandentry_t nr_bandtable[];
......@@ -254,6 +254,9 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
// Align up to a multiple of 16
#define ALIGN_UP_16(a) ((a + 15) & ~15)
#ifdef __cplusplus
#ifdef min
#undef min
......
......@@ -29,13 +29,13 @@ TEST(nr_common, nr_timer) {
NR_timer_t timer;
nr_timer_setup(&timer, 10, 1);
nr_timer_start(&timer);
EXPECT_TRUE(is_nr_timer_active(timer));
EXPECT_FALSE(nr_timer_expired(timer));
EXPECT_TRUE(nr_timer_is_active(&timer));
EXPECT_FALSE(nr_timer_expired(&timer));
for (auto i = 0; i < 10; i++) {
nr_timer_tick(&timer);
}
EXPECT_FALSE(is_nr_timer_active(timer));
EXPECT_TRUE(nr_timer_expired(timer));
EXPECT_FALSE(nr_timer_is_active(&timer));
EXPECT_TRUE(nr_timer_expired(&timer));
}
......
......@@ -320,7 +320,7 @@ typedef struct timer_elm_s {
(char *)itti_get_task_name(task_id),
-1,
OAI_PRIORITY_RT);
LOG_I(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
LOG_D(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
return 0;
}
......
......@@ -42,6 +42,8 @@ Running the [build_oai](../cmake_targets/build_oai) script also generates some
The build system for OAI uses [cmake](https://cmake.org/) which is a tool to generate makefiles. The `build_oai` script is a wrapper using `cmake` and `make`/`ninja` to ease the oai build and use. It logs the `cmake` and `ninja`/`make` commands it executes. The file describing how to build the executables from source files is the [CMakeLists.txt](../CMakeLists.txt), it is used as input by cmake to generate the makefiles.
cmake is further extended by using [CPM](https://github.com/cpm-cmake/CPM.cmake). CPM is a cmake script that handles external code dependencies. It is setup to cache downloaded code in `~/.cache/cpm`. While most external dependencies should be handled by system package managers, CPM has the advantage of using any code that is available in a public git repository.
The oai softmodem supports many use cases, and new ones are regularly added. Most of them are accessible using the configuration file or the command line options and continuous effort is done to avoid introducing build options as it makes tests and usage more complicated than run-time options. The following functionalities, originally requiring a specific build are now accessible by configuration or command line options:
- s1, noS1
......
......@@ -2256,7 +2256,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/sss_nr.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/dci_nr.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_prach.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c \
......
......@@ -18,38 +18,58 @@
The F1 interface is the functional split of 3GPP between the CU (centralized
unit: PDCP, RRC, SDAP) and the DU (distributed unit: RLC, MAC, PHY). It is
standardized in TS 38.470 - 38.473 for 5G NR. No equivalent for 4G exists.
standardized in TS 38.470 - 38.473 for 5G NR.
We assume that each DU handles only one cell. Multiple DUs connected to one CU
are supported. Mobility over F1 is not yet supported.
F1 specs:
* 3GPP TS 38.470 F1 general aspects and principles
* 3GPP TS 38.471 F1 layer 1
# Control plane status (F1-C)
F1-C:
* 3GPP TS 38.472 F1 signalling transport
* 3GPP TS 38.473 F1 Application Protocol (F1AP)
## Implementation Status
F1-U:
* 3GPP TS 38.474 F1 Data Transport
Note that OAI uses F1 "internally". That means, that even **if you run a
monolithic gNB, the internal information exchange uses F1**. You can therefore
expect that everything working in a monolithic deployment should also work in
F1. The current implementation is based on R16.3.
No equivalent for 4G exists.
Note that NSA does NOT follow this logic yet, and does not work with F1.
## Control plane (F1-C)
The following messages are currently implemented:
The interface F1-C is designed for the exchange of signalling messages between the
Radio Network Layer (RNL) and the Transport Network Layer (TNL). It
consists of F1 Application Protocol messages (F1-AP) exchanged over SCTP.
- F1 Setup Request and F1 Setup Response/Failure
- Initial UL RRC, UL/DL RRC Message Transfer
- F1 UE Context management messages for the "good case"
* Setup Request/Response
* Modification Request/Response
* Release Request/Command/Complete
## Data plane (F1-U)
All other messages are not implemented or not working reliably:
F1-U uses GTP-U for information exchange.
- F1 CU/DU configuration updade
- Paging messages
- Warning Message transmissions
# OAI Implementation Status
## High-level F1-C code structure
The implementation of F1AP messages is seamlessly integrated into OAI, supporting both Monolithic SA
and CU/DU functional split modes. The F1 code is therefore always compiled with nr-softmodem.
This architecture ensures that even *when operating a monolithic gNB, internal information exchange
always utilizes F1AP messages*.
The major difference lies in the CU/DU split scenario, where ASN.1-encoded F1AP messages (F1-C) are
exchanges over SCTP, via a socket interface.
This is the current status:
- gNB-CU/gNB-DU split
- Supported deployments:
* SA
* Single cell per DU
* Multiple DUs connected to one CU (both CP and UP)
- Not supported:
* Mobility
* NSA
## F1-C
### F1AP messages
Refer to [FEATURE_SET.md](FEATURE_SET.md#gNB-F1AP) to learn about the current F1AP implementation status.
### High-level F1-C code structure
The F1 interface is used internally between CU (mostly RRC) and DU (mostly MAC)
to exchange information. In DL, the CU sends messages as defined by the
......@@ -69,38 +89,94 @@ dedicated handler). In F1, the DU task receives the ITTI message, encodes using
ASN.1, and sends it over a network socket. The CU task decodes, and sends the
same ITTI message to the RRC task as done directly in the monolithic case.
Summary of callbacks and handlers:
| Entity | Callback definition | Callback F1 Implementation | Callback Monolithic SA Implementation | Handler |
|--------|---------------------|----------------------------|---------------------------------------|----------------------|
| CU/RRC | `mac_rrc_dl.h` | `mac_rrc_dl_f1ap.c` | `mac_rrc_dl_direct.c` |No handler (use ITTI) |
| DU/MAC | `mac_rrc_ul.h` | `mac_rrc_ul_f1ap.c` | `mac_rrc_ul_direct.c` |`mac_rrc_dl_handler.c`|
A sequence diagram for downlink F1AP messages over the OAI CU/DU functional split:
```mermaid
sequenceDiagram
box rgba(17,158,189,255) CU/RRC
participant TASK_RRC_GNB
participant TASK_CU_F1
end
Note over TASK_RRC_GNB: MAC/RRC callback
TASK_RRC_GNB->>+TASK_CU_F1: F1AP message (ITTI)
Note over TASK_CU_F1: F1 message encoding
Note over TASK_CU_F1: ASN.1 encoding
box Grey DU/MAC
participant TASK_DU_F1
participant MAC
end
Note over TASK_DU_F1: F1AP DL message handler
TASK_CU_F1->>+TASK_DU_F1: SCTP (ITTI)
Note over TASK_DU_F1: F1 message decoding
Note over TASK_DU_F1: ASN.1 decoding
TASK_DU_F1->>+MAC: F1AP message (function call)
Note over MAC: MAC DL message handler
```
+-------------+
| |
| CU/RRC |
| |
+-------------+
| ^
Callback def: mac_rrc_dl.h | | No handler needed:
F1 impl: mac_rrc_dl_f1ap.c | | RRC has ITTI
Monolithic: mac_rrc_dl_direct.c | |
| |
DL | | UL
| |
| | Callback def: mac_rrc_ul.h
Message handler: | | F1 impl: mac_rrc_ul_f1ap.c
mac_rrc_dl_handler.c | | Monolithic: mac_rrc_ul_direct.c
v |
+-------------+
| |
| DU/MAC |
| |
+-------------+
and for the uplink F1AP messages:
```mermaid
sequenceDiagram
box rgba(17,158,189,255) CU/RRC
participant TASK_RRC_GNB
participant TASK_CU_F1
end
box Grey DU/MAC
participant TASK_DU_F1
participant TASK_MAC_GNB
end
Note over TASK_MAC_GNB: MAC/RRC callback
TASK_MAC_GNB->>+TASK_DU_F1: F1AP message (ITTI)
Note over TASK_DU_F1: F1 message encoding
Note over TASK_DU_F1: ASN.1 encoding
Note over TASK_CU_F1: F1AP UL message handler
TASK_DU_F1->>+TASK_CU_F1: SCTP (ITTI)
Note over TASK_CU_F1: F1 message decoding
Note over TASK_CU_F1: ASN.1 decoding
TASK_CU_F1->>+TASK_RRC_GNB: F1AP message (ITTI)
```
Alternative sequence handling (e.g. Monolithic), for downlink:
```mermaid
sequenceDiagram
box rgba(17,158,189,255) RRC
participant TASK_RRC_GNB
end
Note over TASK_RRC_GNB: mac_rrc_dl_direct.c callback
box Grey MAC
participant TASK_MAC_GNB
end
TASK_RRC_GNB->>+TASK_MAC_GNB: raw F1AP message
Note over TASK_MAC_GNB: mac_rrc_dl_handler.c
```
and for the uplink:
```mermaid
sequenceDiagram
box rgba(17,158,189,255) RRC
participant TASK_RRC_GNB
end
box Grey MAC
participant TASK_MAC_GNB
end
Note over TASK_MAC_GNB: mac_rrc_ul_direct.c callback
TASK_MAC_GNB->>+TASK_RRC_GNB: raw F1AP message (ITTI)
```
# Data plane status (F1-U)
## F1-U
F1-U uses GTP-U for information exchange. The GTP protocol uses some extensions
for NR-U protocol to report buffer status, but this is not properly tested and
might malfunction. One limitation is that the current implementation
acknowledges each packet individually.
Current status:
Multiple DUs at one CU are supported in the data plane (as in the control plane).
* Buffer status report over GTP-U
* Each packet is acknowledged individually
* Support of multiple DUs per CU
# How to run
......
......@@ -197,13 +197,17 @@ These modes of operation are supported:
## gNB F1AP
- Integration of F1AP messages and procedures for the control plane exchanges between the CU and DU entities according to 38.473 Rel. 16
- F1 Setup request/response/failure
- F1 DL/UL RRC message transfer
- F1 Initial UL RRC message transfer
- F1 UE Context setup request/response
- F1 UE Context modification request/response
- F1 UE Context modification required
- F1 UE Context release req/cmd/complete
- F1 Interface Management:
* F1 Setup request/response/failure
- F1 RRC Message Transfer:
* F1 Initial UL RRC Message Transfer
* F1 DL RRC Message Transfer
* F1 UL RRC Message Transfer
- F1 UE Context Management:
* F1 UE Context setup request/response
* F1 UE Context modification request/response
* F1 UE Context modification required
* F1 UE Context release req/cmd/complete
- F1 gNB CU configuration update
- F1 Reset (handled at DU only, full reset only)
- Interface with RRC
......
......@@ -159,6 +159,41 @@ cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr-uesoftmodem -r 32 --numerology 3 --band 257 -C 27533280000 --sa --uicc0.imsi 001010000000001 --ssb 72 --rfsim
```
### Connection to an NG-Core
A configuration file can be fed to the nrUE command line in order to connect to the local NGC.
The nrUE configuration file (e.g. [ue.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf)) is structured in a key-value format and contains the relevant UICC parameters that are necessary to authenticate the UE to the local 5GC. E.g.:
```shell
uicc0 = {
imsi = "001010000000001";
key = "fec86ba6eb707ed08905757b1bb44b8f";
opc = "C42449363BBAD02B66D16BC975D77CC1";
dnn = "oai";
nssai_sst = 1;
}
```
| **Parameter** | **Description** | **Default Value** |
|---------------|-----------------|-------------------|
| **IMSI** | Unique identifier for the UE within the mobile network. Used by the network to identify the UE during authentication. It ensures that the UE is correctly identified by the network. | 001010000000001 |
| **key** | Cryptographic key shared between the UE and the network, used for encryption during the authentication process. | `fec86ba6eb707ed08905757b1bb44b8f` |
| **OPC** | Operator key for the Milenage Authentication and Key Agreement algorithm used for encryption during the authentication process. | Ensures secure communication between the UE and the network by matching the encryption keys. | `C42449363BBAD02B66D16BC975D77CC1` |
| **DNN** | Specifies the name of the data network the UE wishes to connect to, similar to an APN in 4G networks. | `oai` |
| **NSSAI** | Allows the UE to select the appropriate network slice, which provides different QoS. | `1` |
The UE configuration must match the one of the network's AMF. The nrUE can connect by default to OAI CN5G with no need to provide the configuration file.
When running the `nr-uesoftmodem`, one can specify the nrUE configuration file using the `-O` option. E.g.:
```bash
sudo ./nr-uesoftmodem --rfsim --rfsimulator.serveraddr 127.0.0.1 --sa -r 106 --numerology 1 --band 78 -C 3619200000 -O ~/nrue.uicc.conf
```
The CL option `--uicc0.imsi` can override the IMSI value in the configuration file if necessary (e.g. when running multiple UEs): `--uicc0.imsi 001010000000001`.
More details available at [ci-scripts/yaml_files/5g_rfsimulator/README.md](../ci-scripts/yaml_files/5g_rfsimulator/README.md).
## 5.2 End-to-end connectivity test
- Ping test from the UE host to the CN5G
```bash
......
......@@ -106,7 +106,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
## Special-purpose libraries
- OAI has a scope based on Xforms, described in [this README](../openair1/PHY/TOOLS/readme.md)
- OAI has two scopes: one based on Xforms and one based on imgui, described in [this README](../openair1/PHY/TOOLS/readme.md)
- OAI comes with an integrated [telnet server](../common/utils/telnetsrv/DOC/telnethelp.md) to monitor and control
- OAI comes with an integrated [web server](../common/utils/websrv/DOC/websrv.md)
......
......@@ -102,47 +102,65 @@ Command line parameters for UE in `--sa` mode:
- `--band` : NR band number (default value 78)
- `--ssb` : SSB start subcarrier (default value 516)
**Optional parameters**:
- `-E`: use three-quarter sampling for split 8 sample rate. Required for
certain radios (e.g., 40MHz with B210). If used on the gNB, it is a good idea
to use for the UE as well (and vice versa).
- `--ue-scan-carrier` : scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`.
To simplify the configuration for the user testing OAI UE with OAI gNB, the latter prints the following LOG that guides the user to correctly set some of the UE command line parameters:
To simplify the configuration for the user testing OAI UE with OAI gNB, the latter prints the following LOG that guides the user to correctly set some of the UE command line parameters.
```
```shell
[PHY] Command line parameters for OAI UE: -C 3319680000 -r 106 --numerology 1 --ssb 516
```
You can run this, using USRPs, on two separate machines:
```
```shell
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --sa
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --sa
```
With the RFsimulator (on the same machine):
With the **RFsimulator** (on the same machine), just add the option `--rfsim` to both gNB and NR UE command lines.
```bash
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --rfsim --sa
```
UE capabilities can be passed according to the [UE Capabilities](#UE-Capabilities) section.
Additionally, at UE side `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml`
A detailed tutorial is provided at this page [NR_SA_Tutorial_OAI_nrUE.md](./NR_SA_Tutorial_OAI_nrUE.md).
## Some useful NR-UE parameters
## Optional NR-UE command line options
Some other useful paramters of the UE are
Here are some useful command line options for the NR UE:
- `--ue-fo-compensation`: enables the frequency offset compenstation at the UE. This is useful when running over the air and/or without an external clock/time source
- `--usrp-args`: this is the equivalend paramter of `sdr_addrs` field in the gNB config file and can be used to identify the USRP and set some basic paramters (like the clock source)
- `--clock-source`: sets the clock-source (internal or external).
- `--time-source`: sets the time-source (internal or external).
| Parameter | Description |
|--------------------------|---------------------------------------------------------------------------------------------------------------|
| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. |
| `--ue-fo-compensation` | Enables the frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
| `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). |
| `--clock-source` | Sets the clock source (internal or external). |
| `--time-source` | Sets the time source (internal or external). |
You can see all options by typing
```
You can view all available options by typing:
```shell
./nr-uesoftmodem --help
```
## Common gNB and NR UE command line options
### Three-quarter sampling
The command line option `-E` can be used to enable three-quarter sampling for split 8 sample rate. Required for certain radios (e.g., 40MHz with B210). If used on the gNB, it is a good idea to use for the UE as well (and vice versa).
### UE Capabilities
The `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g.`--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` for 1 layer or e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` for 2 layers.
This option is available for the following combinations of operation modes and gNB/nrUE softmodems:
| Mode | Executable | Description |
|------------|----------------|-----------------------------------------------------|
| SA | nr-uesoftmodem | Send UE capabilities from the UE to the gNB via RRC |
| phy-test | nr-softmodem | Mimic the reception of UE capabilities by the gNB |
| do-ra | nr-softmodem | Mimic the reception of UE capabilities by the gNB |
e.g.
```shell
sudo ./nr-uesoftmodem --sa -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml
```
## How to run a NTN configuration
......@@ -310,7 +328,7 @@ In summary:
* `scp usera@machineA:/the/path/where/you/launched/nr-softmodem/r*config.raw userb@machineB:/the/path/where/you/will/launch/nr-uesoftmodem/`
* Obviously this operation should be done before launching the `nr-uesoftmodem` executable.
In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` (1 layer) or `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` (2 layers).
In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB through the command line parameter `--uecap_file`. Refer to the [UE Capabilities](#UE-Capabilities) section for more details.
## noS1 setup with OAI UE
......@@ -346,7 +364,7 @@ The do-ra flag is used to ran the NR Random Access procedures in contention-free
In order to run the RA, the `--do-ra` flag is needed for both the gNB and the UE.
In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml`
In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB through the command line parameter `--uecap_file`. Refer to the [UE Capabilities](#UE-Capabilities) section for more details.
To run using the RFsimulator:
......
......@@ -25,7 +25,8 @@ ninja tests
```
Then, you can run `ctest` to run all tests:
```
```bash
$ ctest
Test project /home/richie/w/ctest/build
Start 1: nr_rlc_tests
......@@ -36,6 +37,8 @@ Test project /home/richie/w/ctest/build
Total Test time (real) = 0.06 sec
```
The user can see all available tests by typing `ctest -N` and then run a specific with `ctest -R <test_name>`, e.g. `ctest -R nr_rlc_tests`.
A couple of interesting variables are `--verbose`, `--output-on-failure`.
# How to add a new test
......@@ -59,7 +62,8 @@ process is
In the simplest case, in an existing `CMakeLists.txt`, you might add the
following:
```
```bash
if(ENABLE_TESTS)
add_executable(my_test mytest.c)
add_dependencies(tests my_test)
......
......@@ -35,6 +35,7 @@ ENV UHD_VERSION=4.4.0.0
RUN dnf install 'dnf-command(config-manager)' -y && \
dnf install epel-release -y && crb enable && \
dnf update -y && \
cat /etc/os-release && \
dnf install -y \
#gcc needed for build_oai
gcc gcc-c++ \
......@@ -42,9 +43,22 @@ RUN dnf install 'dnf-command(config-manager)' -y && \
file \
psmisc \
git \
meson \
wget \
xz \
pkg-config \
pcre2-devel \
m4 \
python3-devel \
numactl-libs \
numactl-devel \
gcc-toolset-12-gcc \
gcc-toolset-12-gcc-c++ \
# python3-pip and pyyaml are used for conf template generation
python3-pip && \
pip3 install --ignore-installed pyyaml
pip3 install --ignore-installed pyyaml && \
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
# Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini
# it will be copied into target containers, to print exit numbers and handle signals properly
......@@ -65,7 +79,8 @@ WORKDIR /oai-ran
COPY oaienv .
#run build_oai -I to get the builder image
RUN /bin/sh oaienv && \
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai -I --install-optional-packages -w USRP
scl enable gcc-toolset-12 "\
./build_oai -I --install-optional-packages -w USRP"
......@@ -66,6 +66,7 @@ RUN apt-get update && \
libssl-dev:arm64 \
libtool:arm64 \
zlib1g-dev:arm64 \
libyaml-cpp-dev:arm64 \
# cross build libs and compilers
libc6-dev-i386 \
gcc-11-aarch64-linux-gnu \
......
......@@ -35,4 +35,12 @@ COPY . .
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope" -w USRP -t Ethernet --noavx512 -c
CXXFLAGS="-Werror -fstack-protector-strong" CFLAGS="-Werror -fstack-protector-strong" ./build_oai -c --ninja \
--eNB --gNB --RU --UE --nrUE \
--build-lib "telnetsrv enbscope uescope nrscope" \
-w USRP -t Ethernet \
--noavx512 && \
echo "---- ldd on executables ----" && \
ldd ran_build/build/*softmodem* ran_build/build/nr-cuup ran_build/build/oairu && \
echo "---- ldd on shared libraries ----" && \
ldd ran_build/build/*.so
......@@ -41,6 +41,8 @@ RUN /bin/sh oaienv && \
ninja ldpc_generators generate_T > ../../log/host-tools.txt 2>&1 && \
echo "====== End of log for host-tools ======" && \
cd ../build-cross/ && \
# install missing libyaml-cpp-dev for arm64
apt install -y libyaml-cpp-dev:arm64 && \
cmake ../../.. -GNinja -DCMAKE_TOOLCHAIN_FILE=../../../cmake_targets/cross-arm.cmake -DNATIVE_DIR=../build && \
echo "====== Start of log for cross-build executables ======" && \
# making always passing so we can analyze the all.txt file
......
#/*
# * 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
# */
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface 7.2 Fronthaul
# Valid for Rocky 9
#
#---------------------------------------------------------------------
FROM ran-base:latest AS gnb-base
FROM ran-build-fhi72:latest AS gnb-build
#start from scratch for target executable
FROM docker.io/rockylinux:9 AS oai-gnb-fhi72
ENV TZ=Europe/Paris
RUN dnf update -y && \
dnf install -y \
procps-ng \
libXpm \
libX11 \
lksctp-tools \
xz \
numactl-libs \
numactl-devel \
pkg-config \
pciutils \
tzdata \
gdb \
python3 \
python3-pip \
net-tools \
iputils && \
pip3 install six && \
pip3 install requests && \
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
WORKDIR /opt/oai-gnb/bin
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/nr-softmodem ./
COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboran_fhlib_5g.so \
/oai-ran/cmake_targets/ran_build/build/liboai_transpro.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/usr/local/lib/
## Libxran library
COPY --from=gnb-build \
/opt/phy/fhi_lib/lib/build/libxran.so \
/opt/phy/fhi_lib/lib/build/
## Copy all DPDK libraries as liboran_fhlib_5g.so require most of them
COPY --from=gnb-build /usr/local/lib64/ /usr/local/lib64/
## Copy E2 SM models
COPY --from=gnb-build /usr/local/lib64/flexric /usr/local/lib64/flexric
# Copying file for configuration module
COPY --from=gnb-base \
/lib64/libconfig.so.11 \
/lib64/libforms.so.2 \
/lib64/libblas.so.3 \
/lib64/libcblas.so.3 \
/lib64/liblapack.so.3 \
/lib64/liblapacke.so.3 \
/lib64/libicudata.so.67 \
/lib64/libicui18n.so.67 \
/lib64/libicuuc.so.67 \
/lib64/
RUN ldconfig && \
echo "---- ldd on executable nr-softmodem ----" && \
ldd /opt/oai-gnb/bin/nr-softmodem && \
echo "---- ldd on shared libraries ----" && \
ldd /usr/local/lib/librfsimulator.so \
/usr/local/lib/liboran_fhlib_5g.so \
/usr/local/lib/liboai_transpro.so \
/usr/local/lib/libcoding.so \
/usr/local/lib/libparams_libconfig.so \
/usr/local/lib/libdfts.so \
/usr/local/lib/libldpc*.so \
/usr/local/lib/libtelnetsrv.so \
/usr/local/lib/libtelnetsrv_ci.so \
/opt/phy/fhi_lib/lib/build/libxran.so
WORKDIR /opt/oai-gnb
COPY --from=gnb-base /tini /tini
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"]
......@@ -34,6 +34,9 @@ FROM ran-build:latest AS nr-ue-build
FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-nr-ue
ENV TZ=Europe/Paris
# Install EPEL for RHEL9
RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
RUN dnf update -y && \
dnf install -y \
lksctp-tools \
......@@ -47,7 +50,8 @@ RUN dnf update -y && \
python3 \
python3-pip \
libXpm \
libX11 && \
libX11 \
yaml-cpp-devel && \
pip3 install six && \
pip3 install requests && \
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
......@@ -70,6 +74,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/usr/local/lib/
COPY --from=nr-ue-base \
......@@ -117,5 +122,5 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
WORKDIR /opt/oai-nr-ue
COPY --from=nr-ue-base /tini /tini
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/nr-ue.conf"]
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
......@@ -71,6 +71,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/usr/local/lib/
COPY --from=nr-ue-base \
......@@ -118,5 +119,5 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
WORKDIR /opt/oai-nr-ue
COPY --from=nr-ue-base /tini /tini
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/nr-ue.conf"]
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
......@@ -64,7 +64,8 @@ RUN apt-get update && \
iputils-ping \
iproute2 \
iperf3 \
iperf && \
iperf \
libyaml-cpp-dev && \
# if the --sanitize option was used to build, additional packages are required
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
#libasan5 \ # see below
......@@ -97,6 +98,7 @@ COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ciUE.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
......@@ -123,5 +125,5 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai
WORKDIR /opt/oai-nr-ue
COPY --from=nr-ue-base /tini /tini
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/nr-ue.conf"]
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
......@@ -9,8 +9,13 @@ echo "=================================="
echo "/proc/sys/kernel/core_pattern=$(cat /proc/sys/kernel/core_pattern)"
if [ ! -f $CONFIGFILE ]; then
echo "No configuration file found: please mount at $CONFIGFILE"
exit 255
echo "No configuration file $CONFIGFILE found: attempting to find YAML config"
YAML_CONFIGFILE=$PREFIX/etc/nr-ue.yaml
if [ ! -f $YAML_CONFIGFILE ]; then
echo "No configuration file $YAML_CONFIGFILE found. Please mount either at $CONFIGFILE or $YAML_CONFIGFILE"
exit 255
fi
CONFIGFILE=$YAML_CONFIGFILE
fi
echo "=================================="
......@@ -35,6 +40,9 @@ while [[ $# -gt 0 ]]; do
shift
done
new_args+=("-O")
new_args+=("$CONFIGFILE")
# enable printing of stack traces on assert
export OAI_GDBSTACKS=1
......
......@@ -734,14 +734,19 @@ int main( int argc, char **argv ) {
printf("ALL RUs ready - init gNBs\n");
for (int idx=0;idx<RC.nb_nr_L1_inst;idx++) RC.gNB[idx]->if_inst->sl_ahead = sl_ahead;
if(IS_SOFTMODEM_DOSCOPE) {
if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
load_softscope("nr",&p);
p.argc = &argc;
p.argv = argv;
p.gNB = RC.gNB[0];
p.ru = RC.ru[0];
if (IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr", &p);
}
if (IS_SOFTMODEM_IMSCOPE_ENABLED) {
load_softscope("im", &p);
}
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF && NFAPI_MODE != NFAPI_MODE_AERIAL) {
......
......@@ -521,8 +521,11 @@ int main(int argc, char **argv)
init_openair0();
lock_memory_to_ram();
if(IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr",PHY_vars_UE_g[0][0]);
if (IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr", PHY_vars_UE_g[0][0]);
}
if (IS_SOFTMODEM_IMSCOPE_ENABLED) {
load_softscope("im", PHY_vars_UE_g[0][0]);
}
for (int inst = 0; inst < NB_UE_INST; inst++) {
......
/*
* 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 SOFTMODEM_BITS_H
#define SOFTMODEM_BITS_H
// clang-format off
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
#define BIT_2 (1 << 2)
#define BIT_10 (1 << 10)
#define BIT_12 (1 << 12)
#define BIT_13 (1 << 13)
#define BIT_15 (1 << 15)
#define BIT_16 (1 << 16)
#define BIT_17 (1 << 17)
#define BIT_18 (1 << 18)
#define BIT_20 (1 << 20)
#define BIT_21 (1 << 21)
#define BIT_22 (1 << 22)
#define BIT_23 (1 << 23)
#define BIT_24 (1 << 24)
#define BIT_25 (1 << 25)
#define SOFTMODEM_NOS1_BIT BIT_0
#define SOFTMODEM_NOKRNMOD_BIT BIT_1
#define SOFTMODEM_NONBIOT_BIT BIT_2
#define SOFTMODEM_RFSIM_BIT BIT_10
#define SOFTMODEM_SIML1_BIT BIT_12
#define SOFTMODEM_DLSIM_BIT BIT_13
#define SOFTMODEM_DOSCOPE_BIT BIT_15
#define SOFTMODEM_RECPLAY_BIT BIT_16
#define SOFTMODEM_TELNETCLT_BIT BIT_17
#define SOFTMODEM_RECRECORD_BIT BIT_18
#define SOFTMODEM_ENB_BIT BIT_20
#define SOFTMODEM_GNB_BIT BIT_21
#define SOFTMODEM_4GUE_BIT BIT_22
#define SOFTMODEM_5GUE_BIT BIT_23
#define SOFTMODEM_NOSTATS_BIT BIT_24
#define SOFTMODEM_IMSCOPE_BIT BIT_25
// clang-format on
#endif // SOFTMODEM_BITS_H
......@@ -99,6 +99,7 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
uint32_t start_websrv = 0;
uint32_t noS1 = 0, nonbiot = 0;
uint32_t rfsim = 0, do_forms = 0;
uint32_t enable_imscope = 0;
int nfapi_index = 0;
char *logmem_filename = NULL;
check_execmask(execmask);
......@@ -158,6 +159,10 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT);
}
if (enable_imscope) {
set_softmodem_optmask(SOFTMODEM_IMSCOPE_BIT);
}
if (start_websrv) {
load_module_shlib("websrv", NULL, 0, NULL);
}
......
......@@ -32,6 +32,7 @@
#ifndef SOFTMODEM_COMMON_H
#define SOFTMODEM_COMMON_H
#include "openair1/PHY/defs_common.h"
#include "softmodem-bits.h"
#ifdef __cplusplus
extern "C"
{
......@@ -76,6 +77,7 @@ extern "C"
#define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n"
#define CONFIG_HLP_CHESTFREQ "Set channel estimation type in frequency domain. 0-Linear interpolation (default). 1-PRB based averaging of channel estimates in frequency. \n"
#define CONFIG_HLP_CHESTTIME "Set channel estimation type in time domain. 0-Symbols take estimates of the last preceding DMRS symbol (default). 1-Symbol based averaging of channel estimates in time. \n"
#define CONFIG_HLP_IMSCOPE "Enable phy scope based on imgui and implot"
#define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n"
//#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation"
......@@ -188,6 +190,7 @@ extern int usrp_tx_thread;
{"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \
{"imscope" , CONFIG_HLP_IMSCOPE, PARAMFLAG_BOOL, .uptr=&enable_imscope, .defintval=0, TYPE_UINT, 0}, \
}
// clang-format on
......@@ -235,6 +238,7 @@ extern int usrp_tx_thread;
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
// clang-format on
......@@ -274,21 +278,6 @@ extern int usrp_tx_thread;
/***************************************************************************************************************************************/
#define SOFTMODEM_NOS1_BIT (1<<0)
#define SOFTMODEM_NONBIOT_BIT (1<<2)
#define SOFTMODEM_RFSIM_BIT (1<<10)
#define SOFTMODEM_SIML1_BIT (1<<12)
#define SOFTMODEM_DLSIM_BIT (1<<13)
#define SOFTMODEM_DOSCOPE_BIT (1<<15)
#define SOFTMODEM_RECPLAY_BIT (1<<16)
#define SOFTMODEM_TELNETCLT_BIT (1<<17)
#define SOFTMODEM_RECRECORD_BIT (1<<18)
#define SOFTMODEM_ENB_BIT (1<<20)
#define SOFTMODEM_GNB_BIT (1<<21)
#define SOFTMODEM_4GUE_BIT (1<<22)
#define SOFTMODEM_5GUE_BIT (1<<23)
#define SOFTMODEM_NOSTATS_BIT (1<<24)
#define SOFTMODEM_FUNC_BITS (SOFTMODEM_ENB_BIT | SOFTMODEM_GNB_BIT | SOFTMODEM_5GUE_BIT | SOFTMODEM_4GUE_BIT)
#define MAPPING_SOFTMODEM_FUNCTIONS {{"enb",SOFTMODEM_ENB_BIT},{"gnb",SOFTMODEM_GNB_BIT},{"4Gue",SOFTMODEM_4GUE_BIT},{"5Gue",SOFTMODEM_5GUE_BIT}}
......@@ -307,6 +296,7 @@ extern int usrp_tx_thread;
#define IS_SOFTMODEM_4GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_4GUE_BIT)
#define IS_SOFTMODEM_5GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_5GUE_BIT)
#define IS_SOFTMODEM_NOSTATS_BIT ( get_softmodem_optmask() & SOFTMODEM_NOSTATS_BIT)
#define IS_SOFTMODEM_IMSCOPE_ENABLED ( get_softmodem_optmask() & SOFTMODEM_IMSCOPE_BIT)
typedef struct {
uint64_t optmask;
......
......@@ -199,7 +199,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
int n_buf = Prx*max_ul_mimo_layers;
int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB;
int nb_re_pusch2 = (nb_re_pusch + 15) & ~15;
int nb_re_pusch2 = ALIGN_UP_16(nb_re_pusch);
gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH));
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
......
......@@ -1263,7 +1263,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
int nb_layer = rel15_ul->nrOfLayers;
int nb_rx_ant = frame_parms->nb_antennas_rx;
int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
int buffer_length = (rel15_ul->rb_size * NR_NB_SC_PER_RB + 15) & ~15;
int buffer_length = ALIGN_UP_16(rel15_ul->rb_size * NR_NB_SC_PER_RB);
c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32)));
c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32)));
......@@ -1631,7 +1631,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
// extract the data in the OFDM frame, to the start of the array
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
nb_re_pusch = (nb_re_pusch + 15) & ~15;
nb_re_pusch = ALIGN_UP_16(nb_re_pusch);
int dmrs_symbol;
if (gNB->chest_time == 0)
dmrs_symbol = get_valid_dmrs_idx_for_channel_est(rel15_ul->ul_dmrs_symb_pos, meas_symbol);
......@@ -1699,8 +1699,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
start_meas(&gNB->rx_pusch_symbol_processing_stats);
int numSymbols = gNB->num_pusch_symbols_per_thread;
int total_res = 0;
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol += numSymbols) {
int total_res = 0;
for (int s = 0; s < numSymbols; s++) {
pusch_vars->ul_valid_re_per_slot[symbol+s] = get_nb_re_pusch(frame_parms,rel15_ul,symbol+s);
pusch_vars->llr_offset[symbol+s] = ((symbol+s) == rel15_ul->start_symbol_index) ?
......@@ -1744,5 +1744,26 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
}
stop_meas(&gNB->rx_pusch_symbol_processing_stats);
// Copy the data to the scope. This cannot be performed in one call to gNBscopeCopy because the data is not contiguous in the
// buffer due to reference symbol extraction and padding. The gNBscopeCopy call is broken up into steps: trylock, copy, unlock.
metadata mt = {.slot = slot, .frame = frame};
if (gNBTryLockScopeData(gNB, gNBPuschRxIq, sizeof(c16_t), 1, total_res, &mt)) {
int buffer_length = ALIGN_UP_16(rel15_ul->rb_size * NR_NB_SC_PER_RB);
size_t offset = 0;
for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);
symbol++) {
gNBscopeCopyUnsafe(gNB,
gNBPuschRxIq,
&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
sizeof(c16_t) * pusch_vars->ul_valid_re_per_slot[symbol],
offset,
symbol - rel15_ul->start_symbol_index);
offset += sizeof(c16_t) * pusch_vars->ul_valid_re_per_slot[symbol];
}
gNBunlockScopeData(gNB, gNBPuschRxIq)
}
uint32_t total_llrs = total_res * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers;
gNBscopeCopyWithMetadata(gNB, gNBPuschLlr, pusch_vars->llr, sizeof(c16_t), 1, total_llrs, 0, &mt);
return 0;
}
......@@ -1633,7 +1633,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
nr_slot_rx,
symbol,
frame_parms->ofdm_symbol_size,
(int16_t *)(rxdataF_comp[0][aarx] + symbol * nb_re_pdsch),
(int16_t *)(rxdataF_comp[0][aarx] + symbol * rx_size_symbol),
gold,
(int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
......@@ -1654,21 +1654,21 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
}
#ifdef DEBUG_DL_PTRS
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb), (*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb), 1, 1);
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1);
#endif
/*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/
for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) {
for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */
if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) {
if((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_DL_PTRS
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i);
#endif
rotate_cpx_vector((c16_t *)&rxdataF_comp[0][aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
rotate_cpx_vector((c16_t *)&rxdataF_comp[0][aarx][i * rx_size_symbol],
&phase_per_symbol[i],
(c16_t *)&rxdataF_comp[0][aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
(c16_t *)&rxdataF_comp[0][aarx][i * rx_size_symbol],
((*nb_rb) * NR_NB_SC_PER_RB),
15);
}// if not DMRS Symbol
......
......@@ -442,8 +442,9 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
// legacy code use int16, but it is complex16
if (ue) {
UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0);
UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0);
metadata meta = {.slot = proc->nr_slot_rx, .frame = proc->frame_rx};
UEscopeCopyWithMetadata(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0, &meta);
UEscopeCopyWithMetadata(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0, &meta);
}
#ifdef DEBUG_PBCH
for (int cnt = 0; cnt < 864 ; cnt++)
......
......@@ -52,116 +52,6 @@
*/
void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations);
/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream QPSK/QPSK reception.
@param stream0_in Input from channel compensated (MR combined) stream 0
@param stream1_in Input from channel compensated (MR combined) stream 1
@param stream0_out Output from LLR unit for stream0
@param rho01 Cross-correlation between channels (MR combined)
@param length in complex channel outputs*/
void nr_qpsk_qpsk(int16_t *stream0_in,
int16_t *stream1_in,
int16_t *stream0_out,
int16_t *rho01,
int32_t length);
/** \brief This function perform LLR computation for dual-stream (QPSK/QPSK) transmission.
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param rxdataF_comp_i Compensated channel output for interference
@param rho_i Correlation between channel of signal and inteference
@param dlsch_llr llr output
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag flag to indicate this is the first symbol of the dlsch
@param nb_rb number of RBs for this allocation
@param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
@param llr128p pointer to pointer to symbol in dlsch_llr*/
int32_t nr_dlsch_qpsk_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
int32_t **rxdataF_comp_i,
int32_t **rho_i,
int16_t *dlsch_llr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb,
uint16_t pbch_pss_sss_adj,
int16_t **llr128p);
/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
int32_t nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation and weighted for
mid-point in 16QAM constellation
@param len
@param symbol OFDM symbol index in sub-frame
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
/**
\brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@param frame_parms Frame descriptor structure
@param rxdataF_comp Compensated channel output
@param dlsch_llr llr output
@param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by first
mid-point of 64-QAM constellation
@param dl_ch_magb Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by second
mid-point of 64-QAM constellation
@param symbol OFDM symbol index in sub-frame
@param len
@param first_symbol_flag
@param nb_rb number of RBs for this allocation
*/
void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms,
int32_t *rxdataF_comp,
int16_t *dlsch_llr,
int32_t *dl_ch_mag,
int32_t *dl_ch_magb,
int32_t *dl_ch_magr,
uint8_t symbol,
uint32_t len,
uint8_t first_symbol_flag,
uint16_t nb_rb);
void nr_dlsch_deinterleaving(uint8_t symbol,
uint8_t start_symbol,
uint16_t L,
......
......@@ -63,3 +63,7 @@ endif()
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
if (ENABLE_IMSCOPE)
add_subdirectory(imscope)
endif()
CPMAddPackage("gh:ocornut/imgui#v1.90.9")
add_library(imgui
${imgui_SOURCE_DIR}/imgui_draw.cpp
${imgui_SOURCE_DIR}/imgui.cpp
${imgui_SOURCE_DIR}/imgui_widgets.cpp
${imgui_SOURCE_DIR}/imgui_tables.cpp
${imgui_SOURCE_DIR}/imgui_demo.cpp
)
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR})
add_library(imgui_opengl_renderer ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp)
target_include_directories(imgui_opengl_renderer PUBLIC ${imgui_SOURCE_DIR}/backends/)
target_link_libraries(imgui_opengl_renderer PUBLIC imgui)
add_library(imgui_glfw_backend ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp)
target_include_directories(imgui_glfw_backend PUBLIC ${imgui_SOURCE_DIR}/backends/)
target_link_libraries(imgui_glfw_backend PUBLIC imgui)
find_package(OpenGL REQUIRED)
find_package(glfw3 3.3 REQUIRED)
CPMAddPackage("gh:epezent/implot#v0.16")
add_library(implot
${implot_SOURCE_DIR}/implot.cpp
${implot_SOURCE_DIR}/implot_demo.cpp
${implot_SOURCE_DIR}/implot_items.cpp
)
target_link_libraries(implot PUBLIC imgui)
target_include_directories(implot PUBLIC ${implot_SOURCE_DIR})
add_library(imscope MODULE imscope.cpp ../phy_scope_interface.c)
target_link_libraries(imscope PUBLIC imgui_glfw_backend glfw imgui_opengl_renderer OpenGL::OpenGL implot UTIL)
set_target_properties(imscope PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
This diff is collapsed.
......@@ -58,8 +58,11 @@ int end_forms(void) {
return -1;
}
void copyData(void *scopeData, enum scopeDataType type, void *dataIn, int elementSz, int colSz, int lineSz, int offset)
void copyData(void *scopeData, enum scopeDataType type, void *dataIn, int elementSz, int colSz, int lineSz, int offset, metadata *meta)
{
if (type >= MAX_SCOPE_TYPES) {
return;
}
scopeData_t *tmp = (scopeData_t *)scopeData;
if (tmp) {
......
......@@ -70,7 +70,10 @@ enum scopeDataType {
psbchDlChEstimateTime,
psbchLlr,
psbchRxdataF_comp,
MAX_SCOPE_TYPES
MAX_SCOPE_TYPES,
gNBPuschRxIq = MAX_SCOPE_TYPES,
gNBPuschLlr,
EXTRA_SCOPE_TYPES
};
enum PlotTypeGnbIf {
......@@ -87,34 +90,89 @@ typedef struct {
int lineSz;
} scopeGraphData_t;
typedef struct {
int slot;
int frame;
} metadata;
typedef struct scopeData_s {
int *argc;
char **argv;
RU_t *ru;
PHY_VARS_gNB *gNB;
scopeGraphData_t *liveData[MAX_SCOPE_TYPES];
void (*copyData)(void *, enum scopeDataType, void *data, int elementSz, int colSz, int lineSz, int offset);
void (*copyData)(void *, enum scopeDataType, void *data, int elementSz, int colSz, int lineSz, int offset, metadata *meta);
pthread_mutex_t copyDataMutex;
scopeGraphData_t *copyDataBufs[MAX_SCOPE_TYPES][COPIES_MEM];
int copyDataBufsIdx[MAX_SCOPE_TYPES];
void (*scopeUpdater)(enum PlotTypeGnbIf plotType, int numElements);
bool (*tryLockScopeData)(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta);
void (*copyDataUnsafeWithOffset)(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index);
void (*unlockScopeData)(enum scopeDataType type);
} scopeData_t;
int load_softscope(char *exectype, void *initarg);
int end_forms(void) ;
int copyDataMutexInit(scopeData_t *);
void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int colSz, int lineSz, int offset);
void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int colSz, int lineSz, int offset, metadata *meta);
#define UEscopeCopyWithMetadata(ue, type, ...) \
if (ue->scopeData) { \
((scopeData_t *)ue->scopeData)->copyData((scopeData_t *)ue->scopeData, type, ##__VA_ARGS__); \
}
#define UEscopeCopy(ue, type, ...) \
if (ue->scopeData) \
((scopeData_t *)ue->scopeData)->copyData((scopeData_t *)ue->scopeData, type, ##__VA_ARGS__);
if (ue->scopeData) { \
metadata mt = {.slot = -1, .frame = -1}; \
((scopeData_t *)ue->scopeData)->copyData((scopeData_t *)ue->scopeData, type, ##__VA_ARGS__, &mt); \
}
#define gNBscopeCopyWithMetadata(gnb, type, ...) \
if (gnb->scopeData) { \
((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__); \
}
#define gNBscopeCopy(gnb, type, ...) \
if (gnb->scopeData) \
((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__);
if (gnb->scopeData) { \
metadata mt = {.slot = -1, .frame = -1}; \
((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__, &mt); \
}
#define GnbScopeUpdate(gnb, type, numElt) \
if (gnb->scopeData) \
((scopeData_t *)gnb->scopeData)->scopeUpdater(type, numElt);
#define gNBTryLockScopeData(gnb, type, ...) \
gnb->scopeData && ((scopeData_t *)gnb->scopeData)->tryLockScopeData \
&& ((scopeData_t *)gnb->scopeData)->tryLockScopeData(type, ##__VA_ARGS__)
#define gNBscopeCopyUnsafe(gnb, type, ...) \
scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \
if (scope_data && scope_data->copyDataUnsafeWithOffset) { \
scope_data->copyDataUnsafeWithOffset(type, ##__VA_ARGS__); \
}
#define gNBunlockScopeData(gnb, type) \
scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \
if (scope_data && scope_data->unlockScopeData) { \
scope_data->unlockScopeData(type); \
}
#define UEScopeHasTryLock(ue) \
(ue->scopeData && ((scopeData_t *)ue->scopeData)->tryLockScopeData)
#define UETryLockScopeData(ue, type, ...) \
ue->scopeData && ((scopeData_t *)ue->scopeData)->tryLockScopeData \
&& ((scopeData_t *)ue->scopeData)->tryLockScopeData(type, ##__VA_ARGS__)
#define UEscopeCopyUnsafe(ue, type, ...) \
scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \
if (scope_data && scope_data->copyDataUnsafeWithOffset) { \
scope_data->copyDataUnsafeWithOffset(type, ##__VA_ARGS__); \
}
#define UEunlockScopeData(ue, type) \
scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \
if (scope_data && scope_data->unlockScopeData) { \
scope_data->unlockScopeData(type); \
}
extended_kpi_ue* getKPIUE();
#endif
......@@ -31,3 +31,41 @@ or
```
phy_scope_gNB(0, phy_vars_gnb, phy_vars_ru, UE_id)
```
# ImScope
ImScope is a scope based on imgui & implot. This scope uses a different concurrency model than xforms scope, with thread
safety being priority. The goal is to never show incorrect data on the screen and be able to use the scope with real radios.
If correctness cannot be achieved e.g. due to performance issues when using thread safe implementation user should be warned
clearly on the screen.
![image](./imscope/imscope_screenshot.png)
## Prerequisites
ImScope uses imgui, implot, glfw3 and opengl. imgui and implot should be downloaded automatically when configuring the project
with `-DENABLE_IMSCOPE=ON`, using [CPM](https://github.com/cpm-cmake/CPM.cmake). CPM is used because imgui and implot do not have
an official binary release. glfw3 and opengl should be installed with your system, on ubuntu these are contained in packages
libglfw3-dev and libopengl-dev respectivly.
## Building
Add `-DENABLE_IMSCOPE=ON` to your `cmake` command. Build target `imscope`
## Running
Run with `--imscope` flag
## Usage notes
- It's experimental and might contain bugs
- It uses tree nodes to hide/show scopes (layout is subject to change). If a scope is not visible or is frozen it costs nearly
nothing in the PHY threads. If its unfrozen every time the data is displayed the PHY thread would have to perform the copy. By
default this can happen up to 24 times per second. User is informed on the estimated impact on PHY threads at the top of the
window. You can use FPS target to limit the impact on PHY threads and maintain scope functionality while minimizing the effect
on realtime operation.
## Reporting bugs and feature requests
Report bugs and feature requests on [gitlab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues). There is two demo windows
enabled in the scope that showcase imgui/implot, if you find something of interest it can be implemented in the scope.
add_library(nr_phy_common src/nr_phy_common.c)
target_link_libraries(nr_phy_common PRIVATE UTIL)
target_link_libraries(nr_phy_common PRIVATE UTIL PHY_COMMON)
target_include_directories(nr_phy_common PUBLIC inc/)
add_library(nr_ue_phy_meas src/nr_ue_phy_meas.c)
......
......@@ -24,6 +24,10 @@
#include "PHY/impl_defs_top.h"
#include "PHY/TOOLS/tools_defs.h"
void nr_qpsk_llr(int32_t *rxdataF_comp, int16_t *llr, uint32_t nb_re);
void nr_16qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag_in, int16_t *llr, uint32_t nb_re);
void nr_64qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int16_t *llr, uint32_t nb_re);
void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int32_t *ch_mag3, int16_t *llr, uint32_t nb_re);
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal);
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
......
......@@ -509,7 +509,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
int32_t ptrs_re_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_re_per_slot, 0, sizeof(ptrs_re_per_slot));
const uint32_t rx_size_symbol = dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB;
const uint32_t rx_size_symbol = (dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB + 15) & ~15;
__attribute__((aligned(32))) int32_t rxdataF_comp[dlsch[0].Nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT];
memset(rxdataF_comp, 0, sizeof(rxdataF_comp));
......
......@@ -278,8 +278,6 @@ typedef struct pdusession_s {
transport_layer_addr_t upf_addr;
/* Outgoing (UL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gtp_teid;
/* Stores the DRB ID of the DRBs used by this PDU Session */
uint8_t used_drbs[MAX_DRBS_PER_UE];
/* Incoming (DL) NG-U Tunnel Endpoint Identifier (S-GW/UPF) */
uint32_t gNB_teid_N3;
transport_layer_addr_t gNB_addr_N3;
......
This diff is collapsed.
......@@ -40,13 +40,13 @@ int f1ap_encode_pdu(F1AP_F1AP_PDU_t *pdu, uint8_t **buffer, uint32_t *length) {
LOG_E(F1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n");
}
char errbuf[128]; /* Buffer for error message */
char errbuf[4096]; /* Buffer for error message */
size_t errlen = sizeof(errbuf); /* Size of the buffer */
int ret = asn_check_constraints(&asn_DEF_F1AP_F1AP_PDU, pdu, errbuf, &errlen);
/* assert(errlen < sizeof(errbuf)); // Guaranteed: you may rely on that */
if(ret) {
fprintf(stderr, "Constraint validation failed: %s\n", errbuf);
xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, pdu);
LOG_E(F1AP, "Constraint validation failed: %s\n", errbuf);
}
encoded = aper_encode_to_new_buffer(&asn_DEF_F1AP_F1AP_PDU, 0, pdu, (void **)buffer);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment