mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
24 Commits
23796f054f
...
k-teodora
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
307717ba78 | ||
|
|
88083df76b | ||
|
|
e7e4e0562f | ||
|
|
ea12a351de | ||
|
|
0924f1e9fb | ||
|
|
f97a8758a0 | ||
|
|
5ef21c6b82 | ||
|
|
45cd9fb04e | ||
|
|
e5f0f969e1 | ||
|
|
f2e13bc166 | ||
|
|
1839fe4628 | ||
|
|
ae12e04e80 | ||
|
|
4a48d7ca0a | ||
|
|
50c5e7ce0f | ||
|
|
b9e22d5fb2 | ||
|
|
e4c16fe050 | ||
|
|
8d34dafce5 | ||
|
|
ed39d42ada | ||
|
|
42325045ba | ||
|
|
9ad7032f3e | ||
|
|
2f8c5c0883 | ||
|
|
fa5da04daa | ||
|
|
c9ea8a7ad3 | ||
|
|
6f5fe48eff |
@@ -4,9 +4,9 @@
|
||||
# -------
|
||||
#
|
||||
# Finds the xran library. Note that the library number is as follows:
|
||||
# - oran_bronze_release_v1.1 -> 2.1.1 (B = second letter)
|
||||
# - oran_e_maintenance_release_v1.0 -> 5.1.0
|
||||
# the version is currently hardcoded to 5.1.0
|
||||
# - oran_e_maintenance_release_v1.5 -> 5.1.6
|
||||
# - oran_f_release_v1.3 -> 6.1.4
|
||||
# - oran_k_release_v1.1 -> 11.1.1
|
||||
#
|
||||
# Required options
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
@@ -88,6 +88,8 @@ if (xran_VERSION_STRING MATCHES "^oran_e_maintenance_release_v")
|
||||
string(REGEX REPLACE "oran_e_maintenance_release_v([0-9]+).([0-9]+)" "5.\\1.\\2" xran_VERSION ${xran_VERSION_STRING})
|
||||
elseif(xran_VERSION_STRING MATCHES "^oran_f_release_v")
|
||||
string(REGEX REPLACE "oran_f_release_v([0-9]+).([0-9]+)" "6.\\1.\\2" xran_VERSION ${xran_VERSION_STRING})
|
||||
elseif(xran_VERSION_STRING MATCHES "^oran_k_release_v")
|
||||
string(REGEX REPLACE "oran_k_release_v([0-9]+).([0-9]+)" "11.\\1.\\2" xran_VERSION ${xran_VERSION_STRING})
|
||||
elseif(xran_VERSION_STRING MATCHES "^oran_bronze_release_v")
|
||||
string(REGEX REPLACE "oran_bronze_release_v([0-9]+).([0-9]+)" "2.\\1.\\2" xran_VERSION ${xran_VERSION_STRING})
|
||||
else()
|
||||
|
||||
1228
cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch
Normal file
1228
cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -72,9 +72,9 @@ Tested libxran releases:
|
||||
| Vendor |
|
||||
|-----------------------------------------|
|
||||
| `oran_f_release_v1.0` |
|
||||
| `oran_k_release_v1.0` |
|
||||
|
||||
|
||||
**Note**: The libxran driver of OAI identifies the above F release version as "6.1.0" (F is the sixth letter, then 1.0).
|
||||
**Note**: The libxran driver of OAI identifies the above F release version as "6.1.0" (F is the sixth letter, then 1.0), and the above K release as "11.1.0".
|
||||
|
||||
### Configure your server
|
||||
|
||||
@@ -274,7 +274,7 @@ timedatectl set-ntp false
|
||||
|
||||
### DPDK (Data Plane Development Kit)
|
||||
|
||||
Download DPDK version 20.11.9.
|
||||
Download DPDK version 20.11.9 (F release) or 24.11.4 (K release).
|
||||
|
||||
```bash
|
||||
# on debian
|
||||
@@ -282,7 +282,8 @@ sudo apt install wget xz-utils libnuma-dev
|
||||
# on Fedora/RHEL
|
||||
sudo dnf install wget xz numactl-devel
|
||||
cd
|
||||
wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz
|
||||
wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz # F release
|
||||
wget http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz # K release
|
||||
```
|
||||
|
||||
#### DPDK Compilation and Installation
|
||||
@@ -293,7 +294,8 @@ wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz
|
||||
sudo apt install meson
|
||||
# on Fedora/RHEL
|
||||
sudo dnf install meson
|
||||
tar xvf dpdk-20.11.9.tar.xz && cd dpdk-stable-20.11.9
|
||||
tar xvf dpdk-20.11.9.tar.xz && cd dpdk-stable-20.11.9 # F release
|
||||
tar xvf dpdk-24.11.4.tar.xz && cd dpdk-stable-24.11.4 # K release
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
@@ -359,7 +361,8 @@ pkg-config --libs libdpdk --static
|
||||
Go back to the version folder you used to build and install
|
||||
|
||||
```
|
||||
cd ~/dpdk-stable-20.11.9
|
||||
cd ~/dpdk-stable-20.11.9 # F release
|
||||
cd ~/dpdk-stable-24.11.4 # K release
|
||||
sudo ninja deinstall -C build
|
||||
```
|
||||
|
||||
@@ -384,6 +387,14 @@ git checkout oran_f_release_v1.0
|
||||
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch
|
||||
```
|
||||
|
||||
#### K release
|
||||
```bash
|
||||
git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git ~/phy
|
||||
cd ~/phy
|
||||
git checkout oran_k_release_v1.0
|
||||
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch
|
||||
```
|
||||
|
||||
Compile the fronthaul interface library by calling `make` and the option
|
||||
`XRAN_LIB_SO=1` to have it build a shared object. Note that we provide two
|
||||
environment variables `RTE_SDK` for the path to the source tree of DPDK, and
|
||||
@@ -398,6 +409,7 @@ This feature is intended to enable experiments and future improvements on Arm sy
|
||||
cd ~/phy/fhi_lib/lib
|
||||
make clean
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # F release
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-24.11.4/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # K release
|
||||
...
|
||||
[AR] build/libxran.so
|
||||
./build/libxran.so
|
||||
@@ -487,19 +499,6 @@ cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
|
||||
ninja nr-softmodem oran_fhlib_5g params_libconfig
|
||||
```
|
||||
|
||||
Note that in tags 2025.w06 and prior, the FHI72 driver used polling to wait for
|
||||
the next slot. This is inefficient as it burns CPU time, and has been replaced
|
||||
with a more efficient mechanism. Nevertheless, if you experience problems that
|
||||
did not occur previously, it is possible to re-enable polling, either with
|
||||
`build_oai` like this
|
||||
|
||||
./build_oai --gNB --ninja -t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=$HOME/phy/fhi_lib/lib --cmake-opt -DOAI_FHI72_USE_POLLING=ON
|
||||
|
||||
or with `cmake` like so
|
||||
|
||||
cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib -DOAI_FHI72_USE_POLLING=ON
|
||||
ninja oran_fhlib_5g
|
||||
|
||||
## Configuration
|
||||
|
||||
RU and DU configurations have a circular dependency: you have to configure DU MAC address in the RU configuration and the RU MAC address, VLAN and Timing advance parameters in the DU configuration.
|
||||
|
||||
@@ -45,7 +45,9 @@ RUN rm -f /etc/rhsm-host && \
|
||||
gcc-toolset-13-gcc-c++ \
|
||||
# python3-pip and pyyaml are used for conf template generation
|
||||
python3-pip && \
|
||||
pip3 install --ignore-installed pyyaml && \
|
||||
pip3 install --ignore-installed \
|
||||
pyyaml \
|
||||
pyelftools && \
|
||||
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \
|
||||
echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ RUN apt-get update && \
|
||||
wget \
|
||||
xz-utils \
|
||||
pkg-config \
|
||||
libnuma-dev && \
|
||||
libnuma-dev \
|
||||
python3-pyelftools && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rm -Rf /oai-ran
|
||||
@@ -28,20 +29,20 @@ WORKDIR /oai-ran
|
||||
COPY . .
|
||||
|
||||
## Download and build DPDK
|
||||
RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
|
||||
tar -xvf dpdk-20.11.9.tar.xz && \
|
||||
cd dpdk-stable-20.11.9 && \
|
||||
meson setup -Dmachine=default build && \
|
||||
RUN wget --no-verbose http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz && \
|
||||
tar -xf dpdk-24.11.4.tar.xz && \
|
||||
cd dpdk-stable-24.11.4 && \
|
||||
meson build && \
|
||||
ninja -C build && \
|
||||
ninja install -C build
|
||||
|
||||
## Build Fronthaul library
|
||||
RUN git clone https://github.com/openairinterface/o-du-phy.git /opt/phy && \
|
||||
cd /opt/phy && \
|
||||
git checkout oran_f_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \
|
||||
git checkout oran_k_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch && \
|
||||
cd /opt/phy/fhi_lib/lib && \
|
||||
TARGET=armv8 WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
TARGET=armv8 WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-24.11.4/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
|
||||
## Build Arm RAN Acceleration Library
|
||||
RUN git clone https://git.gitlab.arm.com/networking/ral.git /opt/ral && \
|
||||
|
||||
@@ -15,9 +15,9 @@ WORKDIR /oai-ran
|
||||
COPY . .
|
||||
|
||||
## Download and build DPDK
|
||||
RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
|
||||
tar -xvf dpdk-20.11.9.tar.xz && \
|
||||
cd dpdk-stable-20.11.9 && \
|
||||
RUN wget --no-verbose http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz && \
|
||||
tar -xf dpdk-24.11.4.tar.xz && \
|
||||
cd dpdk-stable-24.11.4 && \
|
||||
meson build && \
|
||||
ninja -C build && \
|
||||
ninja install -C build
|
||||
@@ -25,10 +25,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
|
||||
## Build Fronthaul library
|
||||
RUN git clone https://github.com/openairinterface/o-du-phy.git /opt/phy && \
|
||||
cd /opt/phy && \
|
||||
git checkout oran_f_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \
|
||||
git checkout oran_k_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch && \
|
||||
cd /opt/phy/fhi_lib/lib && \
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-24.11.4/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
|
||||
FROM ran-base AS ran-build-fhi72
|
||||
ARG E2AP_VERSION=E2AP_V3
|
||||
|
||||
@@ -20,7 +20,8 @@ RUN apt-get update && \
|
||||
wget \
|
||||
xz-utils \
|
||||
pkg-config \
|
||||
libnuma-dev && \
|
||||
libnuma-dev \
|
||||
python3-pyelftools && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rm -Rf /oai-ran
|
||||
@@ -28,9 +29,9 @@ WORKDIR /oai-ran
|
||||
COPY . .
|
||||
|
||||
## Download and build DPDK
|
||||
RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
|
||||
tar -xvf dpdk-20.11.9.tar.xz && \
|
||||
cd dpdk-stable-20.11.9 && \
|
||||
RUN wget --no-verbose http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz && \
|
||||
tar -xf dpdk-24.11.4.tar.xz && \
|
||||
cd dpdk-stable-24.11.4 && \
|
||||
meson build && \
|
||||
ninja -C build && \
|
||||
ninja install -C build
|
||||
@@ -38,10 +39,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
|
||||
## Build Fronthaul library
|
||||
RUN git clone https://github.com/openairinterface/o-du-phy.git /opt/phy && \
|
||||
cd /opt/phy && \
|
||||
git checkout oran_f_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \
|
||||
git checkout oran_k_release_v1.0 &&\
|
||||
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/K/oaioran_K.patch && \
|
||||
cd /opt/phy/fhi_lib/lib && \
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-24.11.4/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
|
||||
|
||||
FROM ran-base AS ran-build-fhi72
|
||||
## Build and install OAI
|
||||
|
||||
@@ -41,6 +41,7 @@ RUN rm -f /etc/rhsm-host && \
|
||||
python3-pip \
|
||||
net-tools \
|
||||
iputils \
|
||||
libatomic \
|
||||
yaml-cpp-devel && \
|
||||
pip3 install six && \
|
||||
pip3 install requests && \
|
||||
|
||||
@@ -18,6 +18,7 @@ ENV TZ=Europe/Paris
|
||||
RUN dnf update -y && \
|
||||
dnf install -y \
|
||||
procps-ng \
|
||||
libatomic \
|
||||
libXpm \
|
||||
libX11 \
|
||||
lksctp-tools \
|
||||
|
||||
@@ -41,6 +41,7 @@ RUN apt-get update && \
|
||||
python3 \
|
||||
python3-six \
|
||||
python3-requests \
|
||||
libatomic1 \
|
||||
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 \
|
||||
|
||||
@@ -358,9 +358,6 @@ int stop_L1(module_id_t gnb_id)
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
stop_gNB(RC.nb_nr_L1_inst);
|
||||
|
||||
if (RC.nb_RU > 0)
|
||||
stop_RU(RC.nb_RU);
|
||||
|
||||
/* stop trx devices, multiple carrier currently not supported by RU */
|
||||
if (ru->rfdevice.trx_get_stats_func) {
|
||||
ru->rfdevice.trx_get_stats_func(&ru->rfdevice);
|
||||
@@ -378,6 +375,9 @@ int stop_L1(module_id_t gnb_id)
|
||||
LOG_I(GNB_APP, "turned off RU ifdevice\n");
|
||||
}
|
||||
|
||||
if (RC.nb_RU > 0)
|
||||
stop_RU(RC.nb_RU);
|
||||
|
||||
/* release memory used by the RU/gNB threads (incomplete), after all
|
||||
* threads have been stopped (they partially use the same memory) */
|
||||
for (int inst = 0; inst < RC.nb_RU; inst++) {
|
||||
|
||||
@@ -19,14 +19,17 @@ add_library(oran_fhlib_5g MODULE
|
||||
)
|
||||
|
||||
set(F_VERSION 6.1.9)
|
||||
set(K_VERSION 11.1.1)
|
||||
|
||||
find_package(xran REQUIRED)
|
||||
if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6)
|
||||
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION}")
|
||||
elseif(xran_VERSION VERSION_EQUAL F_VERSION)
|
||||
target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE)
|
||||
elseif(xran_VERSION VERSION_EQUAL K_VERSION)
|
||||
target_compile_definitions(oran_fhlib_5g PRIVATE K_RELEASE)
|
||||
else()
|
||||
message(FATAL_ERROR "Found xran version ${xran_VERSION} but needed ${F_VERSION} (F release)")
|
||||
message(FATAL_ERROR "Found xran version ${xran_VERSION} but needed ${F_VERSION} (F release) or ${K_VERSION} (K release)")
|
||||
endif()
|
||||
|
||||
# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress
|
||||
@@ -43,8 +46,6 @@ if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||
target_link_libraries(oran_fhlib_5g PRIVATE armral)
|
||||
endif()
|
||||
|
||||
add_boolean_option(OAI_FHI72_USE_POLLING OFF "Enable polling in FHI72 driver" ON)
|
||||
|
||||
message(STATUS "Building FHI72 CUS library")
|
||||
|
||||
set_target_properties(oran_fhlib_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
@@ -28,7 +28,8 @@ It calls various helper function in the same file to set up DPDK memory buffer
|
||||
- `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for
|
||||
PRACH data; not currently used and implemented in PUSCH data callback.
|
||||
- `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used
|
||||
to unblock timing in `oai_xran_fh_rx_callback()` upon first xran call.
|
||||
to unblock timing in `oai_xran_fh_rx_callback()` and `oai_xran_fh_rx_prach_callback()`
|
||||
upon first xran call.
|
||||
|
||||
More detailed information about the xran callbacks can be taken from the xran
|
||||
documentation.
|
||||
@@ -40,9 +41,10 @@ PDSCH.
|
||||
For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that
|
||||
optionally compresses IQ data, then writes it into IQ buffers of xran.
|
||||
|
||||
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()` that
|
||||
blocks and waits for the next slot. This is done through either a message
|
||||
queue, or through polling, which in both cases depends on xran calling the
|
||||
callback `oai_xran_fh_rx_callback()` as installed during xran initialization.
|
||||
Once unblocked, it reads first PRACH data, then PUSCH data, before returning to
|
||||
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()`/
|
||||
`xran_fh_rx_prach_read_slot()` that blocks and waits for the next slot.
|
||||
This is done through a message queue which depends on xran calling the callbacks
|
||||
`oai_xran_fh_rx_callback()`/`oai_xran_fh_rx_prach_callback()` as installed during
|
||||
xran initialization.
|
||||
Once unblocked, it reads first PUSCH data, then PRACH data, before returning to
|
||||
OAI.
|
||||
|
||||
@@ -12,6 +12,8 @@ if(xran_VERSION MATCHES "5.*")
|
||||
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION}")
|
||||
elseif(xran_VERSION VERSION_EQUAL F_VERSION)
|
||||
target_compile_definitions(oran_fhlib_5g_mplane PRIVATE F_RELEASE)
|
||||
elseif(xran_VERSION VERSION_EQUAL K_VERSION)
|
||||
target_compile_definitions(oran_fhlib_5g_mplane PRIVATE K_RELEASE)
|
||||
endif()
|
||||
|
||||
# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress
|
||||
|
||||
@@ -28,29 +28,87 @@
|
||||
|
||||
#define N_SC_PER_PRB 12
|
||||
|
||||
#if OAI_FHI72_USE_POLLING
|
||||
#define USE_POLLING
|
||||
#endif
|
||||
|
||||
// Declare variable useful for the send buffer function
|
||||
volatile bool first_call_set = false;
|
||||
|
||||
int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id);
|
||||
int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
);
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#ifndef USE_POLLING
|
||||
extern notifiedFIFO_t oran_sync_fifo;
|
||||
#define MAX_QUEUE_LENGTH_NO_JUMP 3
|
||||
atomic_int xran_queue_length = 0;
|
||||
#else
|
||||
volatile oran_sync_info_t oran_sync_info = {0};
|
||||
atomic_int xran_queue_prach_length = 0;
|
||||
#if defined K_RELEASE
|
||||
extern notifiedFIFO_t oran_sync_fifo_prach;
|
||||
#endif
|
||||
|
||||
/* Prints TX_TOTAL, RX_TOTAL, RX_ON_TIME, RX_ERR_DROP counters every 128 frames. */
|
||||
void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
|
||||
{
|
||||
static int64_t old_rx_counter[XRAN_PORTS_NUM] = {0};
|
||||
static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0};
|
||||
struct xran_common_counters x_counters[XRAN_PORTS_NUM];
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
|
||||
#if defined F_RELEASE
|
||||
if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) {
|
||||
#elif defined K_RELEASE
|
||||
if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle[o_xu_id], &x_counters[o_xu_id]) == XRAN_STATUS_SUCCESS) {
|
||||
#endif
|
||||
LOG_I(HW,
|
||||
"[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n",
|
||||
"o-du ",
|
||||
o_xu_id,
|
||||
x_counters[o_xu_id].rx_counter,
|
||||
x_counters[o_xu_id].rx_counter - old_rx_counter[o_xu_id],
|
||||
x_counters[o_xu_id].rx_bytes_per_sec * 8 / 1000L,
|
||||
x_counters[o_xu_id].tx_counter,
|
||||
x_counters[o_xu_id].tx_counter - old_tx_counter[o_xu_id],
|
||||
x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L,
|
||||
x_counters[o_xu_id].Total_msgs_rcvd);
|
||||
for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++)
|
||||
LOG_I(HW,
|
||||
"[%s%d][pusch%d %7ld prach%d %7ld]\n",
|
||||
"o_du",
|
||||
o_xu_id,
|
||||
rxant,
|
||||
x_counters[o_xu_id].rx_pusch_packets[rxant],
|
||||
rxant,
|
||||
x_counters[o_xu_id].rx_prach_packets[rxant]);
|
||||
#if defined K_RELEASE
|
||||
LOG_I(HW,
|
||||
"[%s%d][drop errors %7d ecpri errors %7d cp errors %7d up errors %7d pusch errors %7d prach errors %7d]\n",
|
||||
"o_du",
|
||||
o_xu_id,
|
||||
x_counters[o_xu_id].rx_err_drop,
|
||||
x_counters[o_xu_id].rx_err_ecpri,
|
||||
x_counters[o_xu_id].rx_err_cp,
|
||||
x_counters[o_xu_id].rx_err_up,
|
||||
x_counters[o_xu_id].rx_err_pusch,
|
||||
x_counters[o_xu_id].rx_err_prach);
|
||||
#endif
|
||||
if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id])
|
||||
old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter;
|
||||
if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id])
|
||||
old_tx_counter[o_xu_id] = x_counters[o_xu_id].tx_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @details xran-specific callback, called when all packets for given CC and
|
||||
* 1/4, 1/2, 3/4, all symbols of a slot arrived. Currently, only used to get
|
||||
* timing information and unblock another thread in xran_fh_rx_read_slot()
|
||||
* through either a message queue, or writing in global memory with polling, on
|
||||
* a full slot boundary. */
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
* through a message queue on a full slot boundary. */
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
|
||||
|
||||
@@ -60,9 +118,13 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
int num_ports = fh_init->xran_ports;
|
||||
|
||||
#if defined K_RELEASE
|
||||
const int slots_in_sf = 1 << mu;
|
||||
#elif defined F_RELEASE
|
||||
/* assuming all RUs have the same numerology */
|
||||
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
const int slots_in_sf = 1 << fh_cfg->frame_conf.nNumerology;
|
||||
#endif
|
||||
const int sf_in_frame = 10;
|
||||
|
||||
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
|
||||
@@ -115,21 +177,30 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
rx_RU[i][slot2] = 0;
|
||||
|
||||
if (last_slot == -1 || slot2 != last_slot) {
|
||||
#ifndef USE_POLLING
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, &oran_sync_fifo, NULL);
|
||||
oran_sync_info_t *info = NotifiedFifoData(req);
|
||||
info->tti = tti;
|
||||
info->sl = slot2;
|
||||
info->f = frame;
|
||||
#if defined K_RELEASE
|
||||
info->mu = mu;
|
||||
|
||||
oran_buf_list_t *bufs = get_xran_buffers(ru_id);
|
||||
struct xran_fh_config *fh_config = get_xran_fh_config(ru_id);
|
||||
for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet.
|
||||
for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) {
|
||||
struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->dstcp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id);
|
||||
for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
|
||||
info->nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
|
||||
pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LOG_D(HW, "Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
|
||||
atomic_fetch_add(&xran_queue_length, 1);
|
||||
pushNotifiedFIFO(&oran_sync_fifo, req);
|
||||
#else
|
||||
LOG_D(HW, "Writing %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
|
||||
oran_sync_info.tti = tti;
|
||||
oran_sync_info.sl = slot2;
|
||||
oran_sync_info.f = frame;
|
||||
#endif
|
||||
} else
|
||||
LOG_E(HW, "Cannot Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
|
||||
last_slot = slot2;
|
||||
@@ -137,9 +208,96 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
} // rx_sym == 7
|
||||
}
|
||||
|
||||
/** @details Only used to unblock timing in oai_xran_fh_rx_callback() on first
|
||||
* call. */
|
||||
int oai_physide_dl_tti_call_back(void *param)
|
||||
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined K_RELEASE
|
||||
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
|
||||
|
||||
static int32_t last_slot = -1;
|
||||
// static int32_t last_frame = -1;
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
int num_ports = fh_init->xran_ports;
|
||||
|
||||
const int slots_in_sf = 1 << mu;
|
||||
const int sf_in_frame = 10;
|
||||
|
||||
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
|
||||
uint32_t tti = callback_tag->slotiId;
|
||||
uint32_t frame = XranGetFrameNum(tti, 0, sf_in_frame, slots_in_sf);
|
||||
uint32_t subframe = XranGetSubFrameNum(tti, slots_in_sf, sf_in_frame);
|
||||
uint32_t slot = XranGetSlotNum(tti, slots_in_sf);
|
||||
|
||||
uint32_t rx_sym = callback_tag->symbol & 0xFF;
|
||||
uint32_t ru_id = callback_tag->oXuId;
|
||||
|
||||
LOG_D(HW, "prach_rx_callback at %4d.%3d (subframe %d), rx_sym %d ru_id %d\n", frame, slot, subframe, rx_sym, ru_id);
|
||||
|
||||
if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7))
|
||||
// if xran did not call xran_physide_dl_tti callback, it's not ready yet.
|
||||
// wait till first callback to advance counters, because otherwise users
|
||||
// would see periodic output with only "0" in stats counters
|
||||
if (!first_call_set)
|
||||
return;
|
||||
uint32_t slot2 = slot + (subframe * slots_in_sf);
|
||||
rx_RU[ru_id][slot2] = 1;
|
||||
// if (last_frame > 0 && frame > 0
|
||||
// && ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023))))
|
||||
// LOG_E(HW, "Jump in frame counter last_frame %d => %d, slot %d\n", last_frame, frame, slot2);
|
||||
for (int i = 0; i < num_ports; i++) {
|
||||
if (rx_RU[i][slot2] == 0)
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < num_ports; i++)
|
||||
rx_RU[i][slot2] = 0;
|
||||
|
||||
if (last_slot == -1 || slot2 != last_slot) {
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(oran_sync_info_t), 0, &oran_sync_fifo_prach, NULL);
|
||||
oran_sync_info_t *info = NotifiedFifoData(req);
|
||||
info->tti = tti;
|
||||
info->sl = slot2;
|
||||
info->f = frame;
|
||||
info->mu = mu;
|
||||
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
|
||||
uint32_t tti = callback_tag->slotiId;
|
||||
uint32_t ru_id = callback_tag->oXuId;
|
||||
oran_buf_list_t *bufs = get_xran_buffers(ru_id);
|
||||
struct xran_fh_config *fh_config = get_xran_fh_config(ru_id);
|
||||
for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet.
|
||||
for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) {
|
||||
struct xran_prb_map *pRbMap = (struct xran_prb_map *)bufs->prachdstdecomp[ant_id][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMapPrach == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id);
|
||||
for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
|
||||
AssertFatal(pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt <= 1, "PRACH segmentation is not supported\n");
|
||||
info->nRxPkt[cc_id][ant_id][sym_id] = pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt;
|
||||
pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_D(HW, "Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
|
||||
atomic_fetch_add(&xran_queue_prach_length, 1);
|
||||
pushNotifiedFIFO(&oran_sync_fifo_prach, req);
|
||||
} else
|
||||
LOG_E(HW, "Cannot Push PRACH slot %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot);
|
||||
last_slot = slot2;
|
||||
// last_frame = frame;
|
||||
} // rx_sym == 7
|
||||
#elif defined F_RELEASE
|
||||
rte_pause();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @details Only used to unblock timing in oai_xran_fh_rx_callback()/oai_xran_fh_rx_prach_callback()
|
||||
* on first call. */
|
||||
int oai_physide_dl_tti_call_back(void *param
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!first_call_set)
|
||||
LOG_I(HW, "first_call set from phy cb\n");
|
||||
@@ -147,13 +305,74 @@ int oai_physide_dl_tti_call_back(void *param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Reads PRACH data from xran buffers.
|
||||
/** @details Read PRACH data from xran buffers.
|
||||
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
|
||||
* before writing.
|
||||
*
|
||||
* @details Reads PRACH data from xran-specific buffers and, if I/Q compression
|
||||
* (bitwidth < 16 bits) is configured, uncompresses the data. Places PRACH data
|
||||
* in OAI buffer. */
|
||||
static int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
* Function is blocking and waits for next frame/slot combination. It is unblocked
|
||||
* by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters
|
||||
* frame/slot. If F_RELEASE, it takes the frame/slot. */
|
||||
int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot)
|
||||
{
|
||||
#if defined K_RELEASE
|
||||
// pull next even from oran_sync_fifo_prach if any
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo_prach);
|
||||
atomic_fetch_sub(&xran_queue_prach_length, 1);
|
||||
oran_sync_info_t *info = NotifiedFifoData(res);
|
||||
|
||||
if (xran_queue_prach_length > 0 && xran_queue_prach_length < MAX_QUEUE_LENGTH_NO_JUMP) {
|
||||
LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl);
|
||||
} else if (xran_queue_prach_length >= MAX_QUEUE_LENGTH_NO_JUMP) {
|
||||
uint32_t old_f = info->f;
|
||||
uint32_t old_sl = info->sl;
|
||||
// set the frame/slot info to what is in the last message
|
||||
notifiedFIFO_elt_t *f;
|
||||
while ((f = pollNotifiedFIFO(&oran_sync_fifo_prach)) != NULL) {
|
||||
atomic_fetch_sub(&xran_queue_prach_length, 1);
|
||||
delNotifiedFIFO_elt(res);
|
||||
res = f;
|
||||
}
|
||||
info = NotifiedFifoData(res);
|
||||
LOG_W(HW, "PRACH TTI processing delay detected, skipping %4d.%2d => %4d.%2d\n", old_f, old_sl, info->f, info->sl);
|
||||
DevAssert(xran_queue_prach_length == 0);
|
||||
}
|
||||
|
||||
*slot = info->sl;
|
||||
*frame = info->f;
|
||||
uint8_t mu = info->mu;
|
||||
delNotifiedFIFO_elt(res);
|
||||
#endif
|
||||
|
||||
prach_item_t *prach_id = find_nr_prach(prach_list, *frame, *slot, ru->nb_rx, NR_SEARCH_EXIST);
|
||||
if (prach_id) {
|
||||
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
#if defined F_RELEASE
|
||||
uint8_t mu = fh_cfg->frame_conf.nNumerology;
|
||||
#elif defined K_RELEASE
|
||||
uint8_t mu = fh_cfg->nNumerology[0];
|
||||
#endif
|
||||
int slots_per_subframe = 1 << mu;
|
||||
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
|
||||
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
|
||||
nr_prach_info_t prach_info = get_prach_info(0);
|
||||
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
|
||||
int32_t check_xran_prach_slot = xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)
|
||||
#if defined K_RELEASE
|
||||
|
||||
, mu
|
||||
#endif
|
||||
|
||||
); // `prach_id->slot` = slot in which PRACH is scheduled
|
||||
bool is_prach_slot = is_prach_frame && check_xran_prach_slot;
|
||||
if (is_prach_slot) {
|
||||
ru->prach_buf = prach_id->prach_buf;
|
||||
} else {
|
||||
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot);
|
||||
}
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* calculate tti and subframe_id from frame, slot num */
|
||||
int sym_idx = 0;
|
||||
|
||||
@@ -174,20 +393,49 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
int prach_start_sym = prach_info.start_symbol;
|
||||
int prach_end_sym = prach_info.N_dur + prach_start_sym;
|
||||
struct xran_ru_config *ru_conf = &fh_cfg->ru_conf;
|
||||
|
||||
#if defined K_RELEASE
|
||||
int slots_per_frame = 10 << mu;
|
||||
#elif defined F_RELEASE
|
||||
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
|
||||
int tti = slots_per_frame * (frame) + (slot);
|
||||
#endif
|
||||
|
||||
int tti = slots_per_frame * (*frame) + (*slot);
|
||||
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
/* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
|
||||
if (ru->prach_buf) {
|
||||
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
|
||||
for (int aa = 0; aa < ru->nb_rx; aa++) {
|
||||
|
||||
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
|
||||
for (int aa = 0; aa < ru->nb_rx; aa++) {
|
||||
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
|
||||
int16_t *dst, *src;
|
||||
int idx = 0;
|
||||
oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru);
|
||||
// hardcoded to use only first prach occasion
|
||||
dst = (int16_t *)ru->prach_buf[aa][0];
|
||||
#if defined K_RELEASE
|
||||
struct xran_prb_map * pPrbMap = (struct xran_prb_map *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pPrbMap->sFrontHaulRxPacketCtrl[sym_idx];
|
||||
int32_t nRxPkt = info->nRxPkt[cc_id][aa][sym_idx];
|
||||
if (nRxPkt == 0) {
|
||||
LOG_D(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = 0!\n", *frame, *slot, sym_idx, aa);
|
||||
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
|
||||
continue;
|
||||
} else if (nRxPkt > 1) { // protection
|
||||
LOG_E(HW, "read_prach %d.%d.%d saa = %d: nRxPkt = %d!\n", *frame, *slot, sym_idx, aa, nRxPkt);
|
||||
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
|
||||
continue;
|
||||
} else {
|
||||
src = (int16_t *)p_rx_packet_ctl->pData[0];
|
||||
if (src == NULL) { // protection
|
||||
LOG_E(HW, "read_prach %d.%d.%d saa = %d: src = NULL!!\n", *frame, *slot, sym_idx, aa);
|
||||
memset(&dst[sym_idx], 0, N_ZC * 2 * sizeof(*dst));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
num_prbu = p_rx_packet_ctl->nRBSize[0];
|
||||
#elif defined F_RELEASE
|
||||
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
|
||||
#endif
|
||||
/* convert Network order to host order */
|
||||
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
|
||||
if (sym_idx == prach_start_sym) {
|
||||
@@ -229,9 +477,10 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
for (idx = 0; idx < (N_ZC * 2); idx++)
|
||||
dst[idx] += (local_dst[idx + g_kbar]);
|
||||
} // COMPMETHOD_BLKFLOAT
|
||||
} // aa
|
||||
} // symb_indx
|
||||
} // ru->prach_buf
|
||||
} // sym_idx
|
||||
} // aa
|
||||
} // cc_id
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -287,9 +536,9 @@ static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int
|
||||
return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
|
||||
}
|
||||
|
||||
/** @details Read PRACH and PUSCH data from xran buffers. If
|
||||
* I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data
|
||||
* before writing. Prints ON TIME counters every 128 frames.
|
||||
/** @details Read PUSCH data from xran buffers.
|
||||
* If I/Q compression (bitwidth < 16 bits) is configured, decompresses the data
|
||||
* before writing.
|
||||
*
|
||||
* Function is blocking and waits for next frame/slot combination. It is unblocked
|
||||
* by oai_xran_fh_rx_callback(). It writes the current slot into parameters
|
||||
@@ -300,17 +549,12 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
int32_t *pos = NULL;
|
||||
int idx = 0;
|
||||
|
||||
static int64_t old_rx_counter[XRAN_PORTS_NUM] = {0};
|
||||
static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0};
|
||||
struct xran_common_counters x_counters[XRAN_PORTS_NUM];
|
||||
static int outcnt = 0;
|
||||
#ifndef USE_POLLING
|
||||
// pull next event from oran_sync_fifo
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo);
|
||||
atomic_fetch_sub(&xran_queue_length, 1);
|
||||
oran_sync_info_t *info = NotifiedFifoData(res);
|
||||
|
||||
#define MAX_QUEUE_LENGTH_NO_JUMP 3
|
||||
if (xran_queue_length > 0 && xran_queue_length < MAX_QUEUE_LENGTH_NO_JUMP) {
|
||||
LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl);
|
||||
} else if (xran_queue_length >= MAX_QUEUE_LENGTH_NO_JUMP) {
|
||||
@@ -330,34 +574,27 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
|
||||
*slot = info->sl;
|
||||
*frame = info->f;
|
||||
delNotifiedFIFO_elt(res);
|
||||
#else
|
||||
*slot = oran_sync_info.sl;
|
||||
*frame = oran_sync_info.f;
|
||||
uint32_t tti_in = oran_sync_info.tti;
|
||||
|
||||
static int last_slot = -1;
|
||||
LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot);
|
||||
int cnt = 0;
|
||||
// while (*slot == last_slot) {
|
||||
while (tti_in == oran_sync_info.tti) {
|
||||
//*slot = oran_sync_info.sl;
|
||||
cnt++;
|
||||
}
|
||||
LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot);
|
||||
last_slot = *slot;
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu = info->mu;
|
||||
#endif
|
||||
delNotifiedFIFO_elt(res);
|
||||
// return(0);
|
||||
|
||||
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
#if defined K_RELEASE
|
||||
int slots_per_frame = 10 << mu;
|
||||
#elif defined F_RELEASE
|
||||
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
|
||||
#endif
|
||||
|
||||
int tti = slots_per_frame * (*frame) + (*slot);
|
||||
|
||||
read_prach_data(ru, *frame, *slot);
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
#if defined K_RELEASE
|
||||
int fftsize = 1 << fh_cfg->perMu[mu].nULFftSize;
|
||||
#elif defined F_RELEASE
|
||||
int fftsize = 1 << fh_cfg->nULFftSize;
|
||||
#endif
|
||||
|
||||
int slot_offset_rxdata = 3 & (*slot);
|
||||
uint32_t slot_size = 4 * 14 * fftsize;
|
||||
@@ -391,13 +628,34 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
int start_totalRB = pRbMap->prbMap[0].nRBStart;
|
||||
int32_t local_dst[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
|
||||
#if defined K_RELEASE
|
||||
struct xran_prb_elm *pRbElm = &pRbMap->prbMap[0];
|
||||
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pRbMap->sFrontHaulRxPacketCtrl[sym_idx];
|
||||
uint32_t one_rb_size =
|
||||
(((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1));
|
||||
int32_t nRxPkt = info->nRxPkt[cc_id][ant_id][sym_idx];
|
||||
LOG_D(HW, "nRxPkt %d\n", nRxPkt);
|
||||
for (int pkt_idx = 0; pkt_idx < nRxPkt; pkt_idx++) {
|
||||
uint8_t *pData;
|
||||
if (fh_init->mtu < p_rx_packet_ctl->nRBSize[pkt_idx] * one_rb_size)
|
||||
pData = bufs->dst[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN]
|
||||
.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT]
|
||||
.pData;
|
||||
else
|
||||
pData = p_rx_packet_ctl->pData[pkt_idx];
|
||||
int numRB = p_rx_packet_ctl->nRBSize[pkt_idx];
|
||||
int startRB = p_rx_packet_ctl->nRBStart[pkt_idx];
|
||||
// num_prbu & start_prbu are for UL U-plane only
|
||||
LOG_D(HW, "p_rx_packet_ctl[%d] startRB[%d]:numRB[%d]\n", pkt_idx, startRB, numRB);
|
||||
{
|
||||
{
|
||||
#elif defined F_RELEASE
|
||||
LOG_D(HW, "[%d.%d] pRbMap->nPrbElm %d\n", *frame, *slot, pRbMap->nPrbElm);
|
||||
for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
int numRB, startRB;
|
||||
uint8_t *pData;
|
||||
struct xran_section_desc *p_sec_desc = NULL;
|
||||
struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm];
|
||||
#if defined F_RELEASE
|
||||
// UP_nRBSize & UP_nRBStart are for DL U-plane only
|
||||
LOG_D(HW, "[%d.%d] idxElm[%d] startSym[%d]:numSym[%d] UP_startRB[%d]:UP_numRB[%d] sym_idx[%d] ant_id[%d] pRbElm->nRBStart[%d]:pRbElm->nRBSize[%d]\n", *frame, *slot, idxElm, pRbElm->nStartSymb, pRbElm->numSymb, pRbElm->UP_nRBStart, pRbElm->UP_nRBSize, sym_idx, ant_id, pRbElm->nRBStart, pRbElm->nRBSize);
|
||||
for (int idxDesc = 0; idxDesc < XRAN_MAX_FRAGMENT; idxDesc++) {
|
||||
@@ -471,34 +729,6 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
} // sym_ind
|
||||
} // ant_ind
|
||||
} // vv_inf
|
||||
if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) {
|
||||
for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
|
||||
LOG_I(HW,
|
||||
"[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n",
|
||||
"o-du ",
|
||||
o_xu_id,
|
||||
x_counters[o_xu_id].rx_counter,
|
||||
x_counters[o_xu_id].rx_counter - old_rx_counter[o_xu_id],
|
||||
x_counters[o_xu_id].rx_bytes_per_sec * 8 / 1000L,
|
||||
x_counters[o_xu_id].tx_counter,
|
||||
x_counters[o_xu_id].tx_counter - old_tx_counter[o_xu_id],
|
||||
x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L,
|
||||
x_counters[o_xu_id].Total_msgs_rcvd);
|
||||
for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++)
|
||||
LOG_I(HW,
|
||||
"[%s%d][pusch%d %7ld prach%d %7ld]\n",
|
||||
"o_du",
|
||||
o_xu_id,
|
||||
rxant,
|
||||
x_counters[o_xu_id].rx_pusch_packets[rxant],
|
||||
rxant,
|
||||
x_counters[o_xu_id].rx_prach_packets[rxant]);
|
||||
if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id])
|
||||
old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter;
|
||||
if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id])
|
||||
old_tx_counter[o_xu_id] = x_counters[o_xu_id].tx_counter;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -516,7 +746,12 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
|
||||
const struct xran_fh_init *fh_init = get_xran_fh_init();
|
||||
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number = fh_cfg->mu_number[0];
|
||||
int fftsize = 1 << fh_cfg->perMu[mu_number].nDLFftSize;
|
||||
#elif defined F_RELEASE
|
||||
int fftsize = 1 << fh_cfg->nDLFftSize;
|
||||
#endif
|
||||
int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports;
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
|
||||
@@ -542,12 +777,15 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
|
||||
LOG_D(HW, "pPrbMap->nPrbElm %d\n", pPrbMap->nPrbElm);
|
||||
for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) {
|
||||
struct xran_section_desc *p_sec_desc = NULL;
|
||||
struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[idxElm];
|
||||
int numRB, startRB;
|
||||
#if defined F_RELEASE
|
||||
numRB = pRbElm->UP_nRBSize;
|
||||
startRB = pRbElm->UP_nRBStart;
|
||||
struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0];
|
||||
#if defined F_RELEASE
|
||||
p_sec_desc = &pRbElm->sec_desc[sym_idx][0];
|
||||
#elif defined K_RELEASE
|
||||
p_sec_desc = &pRbElm->sec_desc[sym_idx];
|
||||
#endif
|
||||
LOG_D(HW, "pPrbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, startRB, numRB);
|
||||
// For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx.
|
||||
@@ -644,9 +882,11 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
// => seems that the RUs don't check for E-bit
|
||||
#if defined F_RELEASE
|
||||
p_sec_desc = &p_prbMapElm->sec_desc[sym_idx][0];
|
||||
#elif defined K_RELEASE
|
||||
p_sec_desc = &p_prbMapElm->sec_desc[sym_idx];
|
||||
#endif
|
||||
int16_t startRB = p_prbMapElm->UP_nRBStart;
|
||||
int16_t numRB = p_prbMapElm->UP_nRBSize;
|
||||
#endif
|
||||
|
||||
if (p_sec_desc == NULL) {
|
||||
printf("p_sec_desc == NULL\n");
|
||||
|
||||
@@ -12,11 +12,29 @@ typedef struct {
|
||||
uint32_t tti;
|
||||
uint32_t sl;
|
||||
uint32_t f;
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu;
|
||||
int32_t nRxPkt[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
#endif
|
||||
} oran_sync_info_t;
|
||||
|
||||
/** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status);
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
);
|
||||
/** @brief xran callback for fronthaul PRACH RX, see xran_5g_prach_req(). */
|
||||
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
);
|
||||
/** @brief xran callback for time alignment, see xran_reg_physide_cb(). */
|
||||
int oai_physide_dl_tti_call_back(void *param);
|
||||
int oai_physide_dl_tti_call_back(void *param
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif /* OAIORAN_H */
|
||||
|
||||
@@ -108,11 +108,9 @@ static void print_fh_init_io_cfg(const struct xran_io_cfg *io_cfg)
|
||||
io_cfg->one_vf_cu_plane);
|
||||
print_fh_eowd_cmn(io_cfg->id, &io_cfg->eowd_cmn[io_cfg->id]);
|
||||
printf("eowd_port (filled within xran library)\n");
|
||||
#if defined F_RELEASE
|
||||
printf("\
|
||||
bbu_offload %d\n",
|
||||
io_cfg->bbu_offload);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_fh_init_eaxcid_conf(const struct xran_eaxcid_config *eaxcid_conf)
|
||||
@@ -154,7 +152,13 @@ void print_fh_init(const struct xran_fh_init *fh_init)
|
||||
{
|
||||
printf("xran_fh_init:\n");
|
||||
print_fh_init_io_cfg(&fh_init->io_cfg);
|
||||
#if defined K_RELEASE
|
||||
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
|
||||
print_fh_init_eaxcid_conf(&fh_init->eAxCId_conf[o_xu_id]);
|
||||
}
|
||||
#elif defined F_RELEASE
|
||||
print_fh_init_eaxcid_conf(&fh_init->eAxCId_conf);
|
||||
#endif
|
||||
printf("\
|
||||
xran_ports %d\n\
|
||||
dpdkBasebandFecMode %d\n\
|
||||
@@ -173,34 +177,58 @@ void print_fh_init(const struct xran_fh_init *fh_init)
|
||||
printf("\
|
||||
totalBfWeights %d\n",
|
||||
fh_init->totalBfWeights);
|
||||
#if defined F_RELEASE
|
||||
printf("\
|
||||
mlogxranenable %d\n\
|
||||
dlCpProcBurst %d\n",
|
||||
fh_init->mlogxranenable,
|
||||
fh_init->dlCpProcBurst);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_prach_config(const struct xran_prach_config *prach_conf)
|
||||
{
|
||||
printf("\
|
||||
prach_config:\n\
|
||||
nPrachConfIdx %d\n\
|
||||
nPrachSubcSpacing %d\n\
|
||||
nPrachZeroCorrConf %d\n\
|
||||
nPrachRestrictSet %d\n\
|
||||
nPrachRootSeqIdx %d\n\
|
||||
nPrachFreqStart %d\n\
|
||||
nPrachFreqOffset %d\n\
|
||||
nPrachFilterIdx %d\n\
|
||||
startSymId %d\n\
|
||||
lastSymId %d\n\
|
||||
startPrbc %d\n\
|
||||
numPrbc %d\n\
|
||||
timeOffset %d\n\
|
||||
freqOffset %d\n\
|
||||
eAxC_offset %d\n",
|
||||
"
|
||||
#if defined K_RELEASE
|
||||
" prach_config:\n\
|
||||
nPrachConfIdx %d\n\
|
||||
nPrachSubcSpacing %d\n\
|
||||
nPrachZeroCorrConf %d\n\
|
||||
nPrachRestrictSet %d\n\
|
||||
nPrachRootSeqIdx %d\n\
|
||||
nPrachFreqStart %d\n\
|
||||
nPrachFreqOffset %d\n\
|
||||
nPrachFilterIdx %d\n\
|
||||
startSymId %d\n\
|
||||
lastSymId %d\n\
|
||||
startPrbc %d\n\
|
||||
numPrbc %d\n\
|
||||
timeOffset %d\n\
|
||||
freqOffset %d\n\
|
||||
prachEaxcOffset %d\n\
|
||||
nprachformat %d\n\
|
||||
periodicity %d\n\
|
||||
startTime %d\n\
|
||||
suboffset %d\n\
|
||||
numSubCarriers %d\n\
|
||||
nRep %d\n",
|
||||
#elif defined F_RELEASE
|
||||
" prach_config:\n\
|
||||
nPrachConfIdx %d\n\
|
||||
nPrachSubcSpacing %d\n\
|
||||
nPrachZeroCorrConf %d\n\
|
||||
nPrachRestrictSet %d\n\
|
||||
nPrachRootSeqIdx %d\n\
|
||||
nPrachFreqStart %d\n\
|
||||
nPrachFreqOffset %d\n\
|
||||
nPrachFilterIdx %d\n\
|
||||
startSymId %d\n\
|
||||
lastSymId %d\n\
|
||||
startPrbc %d\n\
|
||||
numPrbc %d\n\
|
||||
timeOffset %d\n\
|
||||
freqOffset %d\n\
|
||||
eAxC_offset %d\n",
|
||||
#endif
|
||||
prach_conf->nPrachConfIdx,
|
||||
prach_conf->nPrachSubcSpacing,
|
||||
prach_conf->nPrachZeroCorrConf,
|
||||
@@ -215,33 +243,55 @@ static void print_prach_config(const struct xran_prach_config *prach_conf)
|
||||
prach_conf->numPrbc,
|
||||
prach_conf->timeOffset,
|
||||
prach_conf->freqOffset,
|
||||
prach_conf->eAxC_offset);
|
||||
#if defined F_RELEASE
|
||||
#if defined K_RELEASE
|
||||
prach_conf->prachEaxcOffset,
|
||||
prach_conf->nprachformat,
|
||||
prach_conf->periodicity,
|
||||
prach_conf->startTime,
|
||||
prach_conf->suboffset,
|
||||
prach_conf->numSubCarriers,
|
||||
prach_conf->nRep
|
||||
#elif defined F_RELEASE
|
||||
prach_conf->eAxC_offset
|
||||
#endif
|
||||
);
|
||||
printf("\
|
||||
nPrachConfIdxLTE %d\n",
|
||||
prach_conf->nPrachConfIdxLTE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_srs_config(const struct xran_srs_config *srs_conf)
|
||||
{
|
||||
printf("\
|
||||
srs_config:\n\
|
||||
symbMask %04x\n\
|
||||
eAxC_offset %d\n",
|
||||
symbMask %04x\n"
|
||||
#if defined K_RELEASE
|
||||
" srsEaxcOffset %d\n",
|
||||
#elif defined F_RELEASE
|
||||
" eAxC_offset %d\n",
|
||||
#endif
|
||||
srs_conf->symbMask,
|
||||
srs_conf->eAxC_offset);
|
||||
#if defined K_RELEASE
|
||||
srs_conf->srsEaxcOffset
|
||||
#elif defined F_RELEASE
|
||||
srs_conf->eAxC_offset
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
static void print_frame_config(const struct xran_frame_config *frame_conf)
|
||||
{
|
||||
printf("\
|
||||
frame_conf:\n\
|
||||
nFrameDuplexType %s\n\
|
||||
nNumerology %d\n\
|
||||
nTddPeriod %d\n",
|
||||
nFrameDuplexType %s\n"
|
||||
#if defined F_RELEASE
|
||||
" nNumerology %d\n"
|
||||
#endif
|
||||
" nTddPeriod %d\n",
|
||||
frame_conf->nFrameDuplexType == XRAN_TDD ? "TDD" : "FDD",
|
||||
#if defined F_RELEASE
|
||||
frame_conf->nNumerology,
|
||||
#endif
|
||||
frame_conf->nTddPeriod);
|
||||
for (int i = 0; i < frame_conf->nTddPeriod; ++i) {
|
||||
printf(" sSlotConfig[%d]: ", i);
|
||||
@@ -253,7 +303,11 @@ static void print_frame_config(const struct xran_frame_config *frame_conf)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_ru_config(const struct xran_ru_config *ru_conf)
|
||||
static void print_ru_config(
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number,
|
||||
#endif
|
||||
const struct xran_ru_config *ru_conf)
|
||||
{
|
||||
printf("\
|
||||
ru_config:\n\
|
||||
@@ -263,9 +317,13 @@ static void print_ru_config(const struct xran_ru_config *ru_conf)
|
||||
iqWidth %d\n\
|
||||
compMeth %d\n\
|
||||
iqWidth_PRACH %d\n\
|
||||
compMeth_PRACH %d\n\
|
||||
fftSize %d\n\
|
||||
byteOrder %s\n\
|
||||
compMeth_PRACH %d\n"
|
||||
#if defined K_RELEASE
|
||||
" fftSize[mu_number] %d\n"
|
||||
#elif defined F_RELEASE
|
||||
" fftSize %d\n"
|
||||
#endif
|
||||
" byteOrder %s\n\
|
||||
iqOrder %s\n\
|
||||
xran_max_frame %d\n",
|
||||
ru_conf->xranTech == XRAN_RAN_5GNR ? "NR" : "LTE",
|
||||
@@ -275,27 +333,106 @@ static void print_ru_config(const struct xran_ru_config *ru_conf)
|
||||
ru_conf->compMeth,
|
||||
ru_conf->iqWidth_PRACH,
|
||||
ru_conf->compMeth_PRACH,
|
||||
#if defined K_RELEASE
|
||||
ru_conf->fftSize[mu_number],
|
||||
#elif defined F_RELEASE
|
||||
ru_conf->fftSize,
|
||||
#endif
|
||||
ru_conf->byteOrder == XRAN_NE_BE_BYTE_ORDER ? "network/BE" : "CPU/LE",
|
||||
ru_conf->iqOrder == XRAN_I_Q_ORDER ? "I_Q" : "Q_I",
|
||||
ru_conf->xran_max_frame);
|
||||
}
|
||||
|
||||
#if defined K_RELEASE
|
||||
void print_fh_per_mu_cfg(const struct xran_fh_per_mu_cfg *perMu)
|
||||
{
|
||||
printf("\
|
||||
perMu:\n\
|
||||
nDLBandwidth %d\n\
|
||||
nULBandwidth %d\n",
|
||||
perMu->nDLBandwidth,
|
||||
perMu->nULBandwidth);
|
||||
|
||||
print_prach_config(&perMu->prach_conf);
|
||||
|
||||
printf("\
|
||||
freqOffset %d\n\
|
||||
nDLFftSize %d\n\
|
||||
nULFftSize %d\n\
|
||||
eaxcOffset %d\n\
|
||||
nDLRBs %d\n\
|
||||
nULRBs %d\n\
|
||||
Tadv_cp_dl %d\n\
|
||||
T2a_min_cp_dl %d\n\
|
||||
T2a_max_cp_dl %d\n\
|
||||
T2a_min_cp_ul %d\n\
|
||||
T2a_max_cp_ul %d\n\
|
||||
T2a_min_up %d\n\
|
||||
T2a_max_up %d\n\
|
||||
Ta3_min %d\n\
|
||||
Ta3_max %d\n\
|
||||
T1a_min_cp_dl %d\n\
|
||||
T1a_max_cp_dl %d\n\
|
||||
T1a_min_cp_ul %d\n\
|
||||
T1a_max_cp_ul %d\n\
|
||||
T1a_min_up %d\n\
|
||||
T1a_max_up %d\n\
|
||||
Ta4_min %d\n\
|
||||
Ta4_max %d\n\
|
||||
prachEnable %d\n\
|
||||
prachConfigIndex %d\n\
|
||||
prachConfigIndexLTE %d\n\
|
||||
nbIotUlScs %d\n\
|
||||
adv_tx_time %d\n",
|
||||
perMu->freqOffset,
|
||||
perMu->nDLFftSize,
|
||||
perMu->nULFftSize,
|
||||
perMu->eaxcOffset,
|
||||
perMu->nDLRBs,
|
||||
perMu->nULRBs,
|
||||
perMu->Tadv_cp_dl,
|
||||
perMu->T2a_min_cp_dl,
|
||||
perMu->T2a_max_cp_dl,
|
||||
perMu->T2a_min_cp_ul,
|
||||
perMu->T2a_max_cp_ul,
|
||||
perMu->T2a_min_up,
|
||||
perMu->T2a_max_up,
|
||||
perMu->Ta3_min,
|
||||
perMu->Ta3_max,
|
||||
perMu->T1a_min_cp_dl,
|
||||
perMu->T1a_max_cp_dl,
|
||||
perMu->T1a_min_cp_ul,
|
||||
perMu->T1a_max_cp_ul,
|
||||
perMu->T1a_min_up,
|
||||
perMu->T1a_max_up,
|
||||
perMu->Ta4_min,
|
||||
perMu->Ta4_max,
|
||||
perMu->prachEnable,
|
||||
perMu->prachConfigIndex,
|
||||
perMu->prachConfigIndexLTE,
|
||||
perMu->nbIotUlScs,
|
||||
perMu->adv_tx_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
void print_fh_config(const struct xran_fh_config *fh_config)
|
||||
{
|
||||
printf("xran_fh_config:\n");
|
||||
|
||||
printf("\
|
||||
dpdk_port %d\n\
|
||||
sector_id %d\n\
|
||||
nCC %d\n\
|
||||
neAxc %d\n\
|
||||
neAxcUl %d\n\
|
||||
nAntElmTRx %d\n\
|
||||
nDLFftSize %d\n\
|
||||
nAntElmTRx %d\n"
|
||||
#if defined F_RELEASE
|
||||
" nDLFftSize %d\n\
|
||||
nULFftSize %d\n\
|
||||
nDLRBs %d\n\
|
||||
nULRBs %d\n\
|
||||
nDLAbsFrePointA %d\n\
|
||||
nULRBs %d\n"
|
||||
#endif
|
||||
" nDLAbsFrePointA %d\n\
|
||||
nULAbsFrePointA %d\n\
|
||||
nDLCenterFreqARFCN %d\n\
|
||||
nULCenterFreqARFCN %d\n\
|
||||
@@ -307,17 +444,23 @@ void print_fh_config(const struct xran_fh_config *fh_config)
|
||||
fh_config->neAxc,
|
||||
fh_config->neAxcUl,
|
||||
fh_config->nAntElmTRx,
|
||||
#if defined F_RELEASE
|
||||
fh_config->nDLFftSize,
|
||||
fh_config->nULFftSize,
|
||||
fh_config->nDLRBs,
|
||||
fh_config->nULRBs,
|
||||
#endif
|
||||
fh_config->nDLAbsFrePointA,
|
||||
fh_config->nULAbsFrePointA,
|
||||
fh_config->nDLCenterFreqARFCN,
|
||||
fh_config->nULCenterFreqARFCN,
|
||||
fh_config->ttiCb,
|
||||
fh_config->ttiCbParam);
|
||||
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number = fh_config->mu_number[0];
|
||||
print_fh_per_mu_cfg(&fh_config->perMu[mu_number]);
|
||||
#endif
|
||||
#if defined F_RELEASE
|
||||
printf("\
|
||||
Tadv_cp_dl %d\n\
|
||||
T2a_min_cp_dl %d\n\
|
||||
@@ -353,45 +496,49 @@ void print_fh_config(const struct xran_fh_config *fh_config)
|
||||
fh_config->T1a_max_up,
|
||||
fh_config->Ta4_min,
|
||||
fh_config->Ta4_max);
|
||||
|
||||
#endif
|
||||
printf("\
|
||||
enableCP %d\n\
|
||||
prachEnable %d\n\
|
||||
srsEnable %d\n\
|
||||
enableCP %d\n"
|
||||
#if defined F_RELEASE
|
||||
" prachEnable %d\n"
|
||||
#endif
|
||||
" srsEnable %d\n\
|
||||
puschMaskEnable %d\n\
|
||||
puschMaskSlot %d\n\
|
||||
cp_vlan_tag %d\n\
|
||||
up_vlan_tag %d\n\
|
||||
debugStop %d\n\
|
||||
debugStopCount %d\n\
|
||||
DynamicSectionEna %d\n\
|
||||
GPS_Alpha %d\n\
|
||||
GPS_Beta %d\n",
|
||||
fh_config->enableCP,
|
||||
#if defined F_RELEASE
|
||||
fh_config->prachEnable,
|
||||
#endif
|
||||
fh_config->srsEnable,
|
||||
fh_config->puschMaskEnable,
|
||||
fh_config->puschMaskSlot,
|
||||
fh_config->cp_vlan_tag,
|
||||
fh_config->up_vlan_tag,
|
||||
fh_config->debugStop,
|
||||
fh_config->debugStopCount,
|
||||
fh_config->DynamicSectionEna,
|
||||
fh_config->GPS_Alpha,
|
||||
fh_config->GPS_Beta);
|
||||
|
||||
#if defined F_RELEASE
|
||||
printf("\
|
||||
srsEnableCp %d\n\
|
||||
SrsDelaySym %d\n",
|
||||
fh_config->srsEnableCp,
|
||||
fh_config->SrsDelaySym);
|
||||
#endif
|
||||
|
||||
#if defined F_RELEASE
|
||||
print_prach_config(&fh_config->prach_conf);
|
||||
#endif
|
||||
print_srs_config(&fh_config->srs_conf);
|
||||
print_frame_config(&fh_config->frame_conf);
|
||||
print_ru_config(&fh_config->ru_conf);
|
||||
print_ru_config(
|
||||
#if defined K_RELEASE
|
||||
mu_number,
|
||||
#endif
|
||||
&fh_config->ru_conf);
|
||||
|
||||
printf("\
|
||||
bbdev_enc %p\n\
|
||||
@@ -413,7 +560,6 @@ void print_fh_config(const struct xran_fh_config *fh_config)
|
||||
fh_config->max_sections_per_slot,
|
||||
fh_config->max_sections_per_symbol);
|
||||
|
||||
#if defined F_RELEASE
|
||||
printf("\
|
||||
RunSlotPrbMapBySymbolEnable %d\n\
|
||||
dssEnable %d\n\
|
||||
@@ -422,6 +568,15 @@ void print_fh_config(const struct xran_fh_config *fh_config)
|
||||
fh_config->RunSlotPrbMapBySymbolEnable,
|
||||
fh_config->dssEnable,
|
||||
fh_config->dssPeriod);
|
||||
|
||||
#if defined K_RELEASE
|
||||
printf("\
|
||||
numMUs %d\n\
|
||||
mu_number[0] %d\n\
|
||||
nNumerology[0] %d\n",
|
||||
fh_config->numMUs,
|
||||
fh_config->mu_number[0],
|
||||
fh_config->nNumerology[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -511,6 +666,10 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
||||
io_cfg->io_sleep = 0; // enable sleep on PMD cores; 0 -> no sleep
|
||||
io_cfg->nEthLinePerPort = *gpd(fhip, nump, ORAN_CONFIG_NETHPERPORT)->uptr; // 1, 2, 3 total number of links per O-RU (Fronthaul Ethernet link)
|
||||
io_cfg->nEthLineSpeed = *gpd(fhip, nump, ORAN_CONFIG_NETHSPEED)->uptr; // 10G,25G,40G,100G speed of Physical connection on O-RU
|
||||
#if defined K_RELEASE
|
||||
io_cfg->num_mbuf_alloc = NUM_MBUFS; // number of mbuf allocated by DPDK (optimal is n = (2^q - 1))
|
||||
io_cfg->num_mbuf_vf_alloc = NUM_MBUFS_VF; // number of mbuf allocated by DPDK (optimal is n = (2^q - 1))
|
||||
#endif
|
||||
io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_rus); // C-plane and U-plane use one VF
|
||||
|
||||
/* eCPRI One-Way Delay Measurements common settings for O-DU and O-RU;
|
||||
@@ -536,9 +695,7 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
||||
/* eCPRI OWDM per port variables for O-DU; this parameter is filled within xran library */
|
||||
// eowd_port[0][XRAN_VF_MAX]
|
||||
|
||||
#if defined F_RELEASE
|
||||
io_cfg->bbu_offload = 0; // enable packet handling on BBU cores
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -575,7 +732,7 @@ static bool set_fh_eaxcid_conf_mplane(struct xran_eaxcid_config *eaxcid_conf, en
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat)
|
||||
static bool __attribute__((unused)) set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat)
|
||||
{
|
||||
/* CUS specification, section 3.1.3.1.6
|
||||
DU_port_ID - used to differentiate processing units at O-DU (e.g., different baseband cards).
|
||||
@@ -666,8 +823,16 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
|
||||
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
|
||||
return false;
|
||||
#if defined K_RELEASE
|
||||
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
|
||||
if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf[o_xu_id], xran_cat, ru_session_list))
|
||||
return false;
|
||||
}
|
||||
#elif defined F_RELEASE
|
||||
if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf, xran_cat, ru_session_list))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
|
||||
communicated in a single xRAN network layer transaction. Based on the MTU size, xran calculates the number
|
||||
of DL fragments (nPrbElm) needed for transmission of one symbol. */
|
||||
@@ -691,8 +856,16 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
|
||||
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
|
||||
return false;
|
||||
#if defined K_RELEASE
|
||||
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
|
||||
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf[o_xu_id], xran_cat))
|
||||
return false;
|
||||
}
|
||||
#elif defined F_RELEASE
|
||||
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
|
||||
communicated in a single xRAN network layer transaction. Based on the MTU size, xran calculates the number
|
||||
of DL fragments (nPrbElm) needed for transmission of one symbol. */
|
||||
@@ -736,11 +909,9 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
||||
fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
|
||||
fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec
|
||||
|
||||
#if defined F_RELEASE
|
||||
fh_init->mlogxranenable = 0; // enable mlog; 0 -> disabled
|
||||
fh_init->dlCpProcBurst = 0; /* 1 -> DL CP processing will be done on single symbol,
|
||||
0 -> DL CP processing will be spread across all allowed symbols and multiple cores to reduce burstiness */
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -780,9 +951,7 @@ static bool set_fh_prach_config(void *mplane_api,
|
||||
prach_config->numPrbc = 0;
|
||||
prach_config->timeOffset = 0;
|
||||
prach_config->freqOffset = 0;
|
||||
#if defined F_RELEASE
|
||||
prach_config->nPrachConfIdxLTE = 0; // used only if DSS enabled and technology is XRAN_RAN_LTE
|
||||
#endif
|
||||
|
||||
/* xran defines PDSCH eAxC IDs as [0...Ntx-1];
|
||||
xran defines PUSCH eAxC IDs as [0...Nrx-1];
|
||||
@@ -791,10 +960,18 @@ static bool set_fh_prach_config(void *mplane_api,
|
||||
Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU. */
|
||||
#ifdef OAI_MPLANE
|
||||
xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
|
||||
#if defined F_RELEASE
|
||||
prach_config->eAxC_offset = xran_mplane->prach_offset;
|
||||
#elif defined K_RELEASE
|
||||
prach_config->prachEaxcOffset = xran_mplane->prach_offset;
|
||||
#endif
|
||||
#else
|
||||
const paramdef_t *pd = gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET);
|
||||
#if defined F_RELEASE
|
||||
prach_config->eAxC_offset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
|
||||
#elif defined K_RELEASE
|
||||
prach_config->prachEaxcOffset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr;
|
||||
@@ -806,8 +983,10 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame
|
||||
{
|
||||
const split7_config_t *s7cfg = &oai0->split7;
|
||||
frame_config->nFrameDuplexType = oai0->duplex_mode == duplex_mode_TDD ? XRAN_TDD : XRAN_FDD; // Frame Duplex type: 0 -> FDD, 1 -> TDD
|
||||
#if defined F_RELEASE
|
||||
frame_config->nNumerology = oai0->nr_scs_for_raster; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz
|
||||
3 -> 120kHz, 4 -> 240kHz */
|
||||
#endif
|
||||
|
||||
if (frame_config->nFrameDuplexType == XRAN_FDD)
|
||||
return true;
|
||||
@@ -824,7 +1003,11 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat, struct xran_ru_config *ru_config)
|
||||
static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat
|
||||
#if defined K_RELEASE
|
||||
, uint8_t mu_number
|
||||
#endif
|
||||
, struct xran_ru_config *ru_config)
|
||||
{
|
||||
ru_config->xranTech = XRAN_RAN_5GNR; // 5GNR or LTE
|
||||
ru_config->xranCat = xran_cat; // mode: Catergory A or Category B
|
||||
@@ -843,7 +1026,11 @@ static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t f
|
||||
ru_config->compMeth_PRACH = ru_config->iqWidth_PRACH < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method for PRACH
|
||||
|
||||
AssertFatal(fftSize > 0, "FFT size cannot be 0\n");
|
||||
#if defined K_RELEASE
|
||||
ru_config->fftSize[mu_number] = fftSize; // FFT Size
|
||||
#elif defined F_RELEASE
|
||||
ru_config->fftSize = fftSize; // FFT Size
|
||||
#endif
|
||||
ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER; // order of bytes in int16_t in buffer; big or little endian
|
||||
ru_config->iqOrder = XRAN_I_Q_ORDER; // order of IQs in the buffer
|
||||
ru_config->xran_max_frame = 0; // max frame number supported; if not specified, default of 1023 is used
|
||||
@@ -866,6 +1053,82 @@ static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint1
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined K_RELEASE
|
||||
static bool set_fh_per_mu_cfg(void *mplane_api, int ru_idx, int num_rus, const openair0_config_t *oai0, struct xran_fh_per_mu_cfg *perMu)
|
||||
{
|
||||
char aprefix[MAX_OPTNAME_SIZE] = {0};
|
||||
|
||||
paramdef_t FHconfigs[] = ORAN_FH_DESC;
|
||||
paramlist_def_t FH_ConfigList = {CONFIG_STRING_ORAN_FH};
|
||||
sprintf(aprefix, "%s", CONFIG_STRING_ORAN);
|
||||
const int nfh = sizeofArray(FHconfigs);
|
||||
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
|
||||
if (FH_ConfigList.numelt == 0) {
|
||||
printf("No configuration section \"%s\" found inside \"%s\": cannot initialize fhi_lib!\n", CONFIG_STRING_ORAN_FH, aprefix);
|
||||
return false;
|
||||
}
|
||||
paramdef_t *fhp = FH_ConfigList.paramarray[ru_idx];
|
||||
|
||||
paramdef_t prachp[] = ORAN_PRACH_DESC;
|
||||
int nprach = sizeofArray(prachp);
|
||||
sprintf(aprefix, "%s.%s.[%d].%s", CONFIG_STRING_ORAN, CONFIG_STRING_ORAN_FH, ru_idx, CONFIG_STRING_ORAN_PRACH);
|
||||
int ret = config_get(config_get_if(), prachp, nprach, aprefix);
|
||||
if (ret < 0) {
|
||||
printf("No configuration section \"%s\": cannot initialize fhi_lib!\n", aprefix);
|
||||
return false;
|
||||
}
|
||||
|
||||
perMu->nDLBandwidth = 0; // Carrier bandwidth for in MHz. Value: 5->400. Not used in K release
|
||||
perMu->nULBandwidth = 0; // Carrier bandwidth for in MHz. Value: 5->400. Not used in K release
|
||||
if (!set_fh_prach_config(mplane_api, oai0, RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus), prachp, nprach, &perMu->prach_conf))
|
||||
return false;
|
||||
perMu->freqOffset = 0;
|
||||
|
||||
perMu->nDLFftSize = oai0->split7.fftSize; // DL FFT size
|
||||
perMu->nULFftSize = oai0->split7.fftSize; // UL FFT size
|
||||
|
||||
perMu->eaxcOffset = 0; // Starting value of Eaxc for PDSCH, PUSCH packets (Absolute value) of this numerology. Should be unique across all numerologies for the RU
|
||||
|
||||
perMu->nDLRBs = oai0->num_rb_dl; // DL PRB
|
||||
perMu->nULRBs = oai0->num_rb_dl; // UL PRB
|
||||
|
||||
/* DU delay profile */
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &perMu->T1a_min_cp_dl, &perMu->T1a_max_cp_dl)) // E - min not used in xran, max yes; F - both min and max are used in xran
|
||||
return false;
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_UL, &perMu->T1a_min_cp_ul, &perMu->T1a_max_cp_ul)) // both E and F - min not used in xran, max yes
|
||||
return false;
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_UP, &perMu->T1a_min_up, &perMu->T1a_max_up)) // both E and F - min not used in xran, max yes
|
||||
return false;
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &perMu->Ta4_min, &perMu->Ta4_max)) // both E and F - min not used in xran, max yes
|
||||
return false;
|
||||
|
||||
perMu->prachEnable = 1; // enable PRACH
|
||||
const split7_config_t *s7cfg = &oai0->split7;
|
||||
perMu->prachConfigIndex = s7cfg->prach_index; // TS36.211 - Table 5.7.1-2 : PRACH Configuration Index
|
||||
perMu->prachConfigIndexLTE = 0; // PRACH Configuration Index for LTE in dss case
|
||||
|
||||
perMu->nbIotUlScs = XRAN_NBIOT_UL_SCS_15; /* Applicable only for NB-IOT (mu=4). NBIOT supports asymmetric SCS usage in
|
||||
downlink and uplink directions. xran library will use this parameter to derive
|
||||
slot-duration for UL NB-IOT:
|
||||
XRAN_NBIOT_UL_SCS_15: slot-duration=1ms
|
||||
XRAN_NBIOT_UL_SCS_3_75: slot-duration=2ms */
|
||||
perMu->adv_tx_time = 0; // Time by which the packet should be transmitted in advance (microseconds)
|
||||
return true;
|
||||
}
|
||||
|
||||
xran_active_numerologies_per_tti activeMUs;
|
||||
|
||||
static bool set_activeMUs(xran_active_numerologies_per_tti *p_activeMUs, uint8_t mu)
|
||||
{
|
||||
for (int i = 0; i < XRAN_N_FE_BUF_LEN; i++) {
|
||||
for (int j = 0; j < XRAN_MAX_NUM_MU; j++) {
|
||||
p_activeMUs->numerology[i][j] = j == mu;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_category xran_cat, const openair0_config_t *oai0, struct xran_fh_config *fh_config)
|
||||
{
|
||||
AssertFatal(num_rus == 1 || num_rus == 2, "only support 1 or 2 RUs as of now\n");
|
||||
@@ -913,12 +1176,18 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
fh_config->sector_id = 0; // Band sector ID for FH; not used in xran
|
||||
fh_config->nCC = 1; // number of Component carriers supported on FH; M-plane info
|
||||
fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
|
||||
#if defined K_RELEASE
|
||||
fh_config->neAxcUl = oai0->rx_num_channels / num_rus; // number of eAxc supported on one CC for UL direction = PUSCH
|
||||
#elif defined F_RELEASE
|
||||
fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B
|
||||
#endif
|
||||
fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B
|
||||
#if defined F_RELEASE
|
||||
fh_config->nDLFftSize = oai0->split7.fftSize; // DL FFT size; not used in xran
|
||||
fh_config->nULFftSize = oai0->split7.fftSize; // UL FFT size; not used in xran
|
||||
fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB; used in oaioran.c/oran-init.c; not used in xran, neither in E nor in F release
|
||||
fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; used in oaioran.c/oran-init.c; in xran E release not used so the patch fixes it, but in xran F release this value is properly used
|
||||
#endif
|
||||
fh_config->nDLAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
|
||||
fh_config->nULAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
|
||||
fh_config->nDLCenterFreqARFCN = 0; // center frequency for DL in NR-ARFCN; not used in xran
|
||||
@@ -926,6 +1195,13 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
fh_config->ttiCb = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call
|
||||
fh_config->ttiCbParam = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call
|
||||
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number = oai0->nr_scs_for_raster;
|
||||
if(!set_fh_per_mu_cfg(mplane_api, ru_idx, num_rus, oai0, &fh_config->perMu[mu_number]))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if defined F_RELEASE
|
||||
/* DU delay profile */
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &fh_config->T1a_min_cp_dl, &fh_config->T1a_max_cp_dl)) // E - min not used in xran, max yes; F - both min and max are used in xran
|
||||
return false;
|
||||
@@ -935,9 +1211,12 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
return false;
|
||||
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &fh_config->Ta4_min, &fh_config->Ta4_max)) // both E and F - min not used in xran, max yes
|
||||
return false;
|
||||
#endif
|
||||
|
||||
fh_config->enableCP = 1; // enable C-plane
|
||||
#if defined F_RELEASE
|
||||
fh_config->prachEnable = 1; // enable PRACH
|
||||
#endif
|
||||
fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B
|
||||
// For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it.
|
||||
#if defined F_RELEASE
|
||||
@@ -946,22 +1225,36 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
#endif
|
||||
fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU
|
||||
fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU
|
||||
#if defined K_RELEASE
|
||||
fh_config->csirsEnable = 0; // enable CSI-RS (Cat B specific)
|
||||
#elif defined F_RELEASE
|
||||
fh_config->cp_vlan_tag = 0; // C-plane VLAN tag; not used in xran; needed for M-plane
|
||||
fh_config->up_vlan_tag = 0; // U-plane VLAN tag; not used in xran; needed for M-plane
|
||||
#endif
|
||||
fh_config->debugStop = 0; // enable auto stop; only used if id = O_RU
|
||||
fh_config->debugStopCount = 0; // enable auto stop after number of Tx packets; not used in xran
|
||||
fh_config->DynamicSectionEna = 0; // enable dynamic C-Plane section allocation
|
||||
fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha
|
||||
fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100
|
||||
|
||||
#if defined K_RELEASE
|
||||
fh_config->numMUs = 1;
|
||||
fh_config->mu_number[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
|
||||
fh_config->nNumerology[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
|
||||
#elif defined F_RELEASE
|
||||
if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* SRS only used if XRAN_CATEGORY_B
|
||||
Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */
|
||||
// fh_config->srs_conf = {0};
|
||||
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
|
||||
return false;
|
||||
if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat, &fh_config->ru_conf))
|
||||
if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat
|
||||
#if defined K_RELEASE
|
||||
, mu_number
|
||||
#endif
|
||||
, &fh_config->ru_conf))
|
||||
return false;
|
||||
|
||||
fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder
|
||||
@@ -985,12 +1278,15 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
fh_config->max_sections_per_slot = 0; // not used in xran
|
||||
fh_config->max_sections_per_symbol = 0; // not used in xran
|
||||
|
||||
#if defined F_RELEASE
|
||||
fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_CP_MULTISECTION)->uptr; // enable PRB mapping by symbol with multisection
|
||||
|
||||
fh_config->dssEnable = 0; // enable DSS (extension-9)
|
||||
fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR
|
||||
// fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled
|
||||
#if defined K_RELEASE
|
||||
if (!set_activeMUs(&activeMUs, oai0->nr_scs_for_raster))
|
||||
return false;
|
||||
fh_config->activeMUs = &activeMUs;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
// structure holding allocated memory for ports (multiple DUs) and sectors
|
||||
// (multiple CCs)
|
||||
static oran_port_instance_t gPortInst[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR];
|
||||
#if defined F_RELEASE
|
||||
void *gxran_handle;
|
||||
#elif defined K_RELEASE
|
||||
void *gxran_handle[XRAN_PORTS_NUM];
|
||||
#endif
|
||||
|
||||
static struct xran_fh_init g_fh_init = {0};
|
||||
static struct xran_fh_config g_fh_config[XRAN_PORTS_NUM] = {0};
|
||||
@@ -81,13 +85,46 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
|
||||
e->nStartSymb = start_sym;
|
||||
e->numSymb = num_sym;
|
||||
e->nRBStart = 0;
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number = f->mu_number[0];
|
||||
e->nRBSize = (dir == XRAN_DIR_DL) ? f->perMu[mu_number].nDLRBs : f->perMu[mu_number].nULRBs;
|
||||
#elif defined F_RELEASE
|
||||
e->nRBSize = (dir == XRAN_DIR_DL) ? f->nDLRBs : f->nULRBs;
|
||||
#endif
|
||||
e->nBeamIndex = 0;
|
||||
e->compMethod = f->ru_conf.compMeth;
|
||||
e->iqWidth = f->ru_conf.iqWidth;
|
||||
#if defined K_RELEASE
|
||||
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
|
||||
#endif
|
||||
return prbmap;
|
||||
}
|
||||
|
||||
#if defined K_RELEASE
|
||||
static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f)
|
||||
{
|
||||
struct xran_prb_map prbmap = {
|
||||
.dir = XRAN_DIR_UL,
|
||||
.xran_port = 0,
|
||||
.band_id = 0,
|
||||
.cc_id = 0,
|
||||
.ru_port_id = 0,
|
||||
.tti_id = 0,
|
||||
.nPrbElm = 1,
|
||||
};
|
||||
struct xran_prb_elm *e = &prbmap.prbMap[0];
|
||||
e->nStartSymb = 0;
|
||||
e->numSymb = 14;
|
||||
e->nRBStart = 0;
|
||||
e->nRBSize = 12;
|
||||
e->nBeamIndex = 0;
|
||||
e->compMethod = f->ru_conf.compMeth;
|
||||
e->iqWidth = f->ru_conf.iqWidth;
|
||||
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
|
||||
return prbmap;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t next_power_2(uint32_t num)
|
||||
{
|
||||
uint32_t power = 2;
|
||||
@@ -182,10 +219,8 @@ static void oran_allocate_cplane_buffers(void *instHandle,
|
||||
struct xran_flat_buffer buf[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],
|
||||
uint32_t ant,
|
||||
uint32_t sect,
|
||||
#if defined F_RELEASE
|
||||
uint32_t mtu,
|
||||
const struct xran_fh_config *fh_config,
|
||||
#endif
|
||||
uint32_t size_of_prb_map,
|
||||
oran_cplane_prb_config *prb_conf)
|
||||
{
|
||||
@@ -219,31 +254,26 @@ static void oran_allocate_cplane_buffers(void *instHandle,
|
||||
// get mixed slot map if in TDD and in mixed slot
|
||||
if (prb_conf->nTddPeriod != 0 && (j % prb_conf->nTddPeriod) == prb_conf->mixed_slot_index)
|
||||
src = &prb_conf->mixedSlotMap;
|
||||
#if defined F_RELEASE
|
||||
if (fh_config->RunSlotPrbMapBySymbolEnable) {
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu_number = fh_config->mu_number[0];
|
||||
xran_init_PrbMap_by_symbol_from_cfg(src, ptr, mtu, fh_config->perMu[mu_number].nDLRBs);
|
||||
#elif defined F_RELEASE
|
||||
xran_init_PrbMap_by_symbol_from_cfg(src, ptr, mtu, fh_config->nDLRBs);
|
||||
#endif
|
||||
} else {
|
||||
xran_init_PrbMap_from_cfg(src, ptr, mtu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
printf("xran_bm_allocate_buffer() hInstance %p poolIdx %u count %u\n", instHandle, poolPrb, count1);
|
||||
}
|
||||
|
||||
/* callback not actively used */
|
||||
static void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status)
|
||||
{
|
||||
rte_pause();
|
||||
}
|
||||
|
||||
static void oran_allocate_buffers(void *handle,
|
||||
int xran_inst,
|
||||
int num_sectors,
|
||||
oran_port_instance_t *portInstances,
|
||||
#if defined F_RELEASE
|
||||
uint32_t mtu,
|
||||
#endif
|
||||
const struct xran_fh_config *fh_config)
|
||||
{
|
||||
AssertFatal(num_sectors == 1, "only support one sector at the moment\n");
|
||||
@@ -272,6 +302,9 @@ static void oran_allocate_buffers(void *handle,
|
||||
// DL/UL PRB mapping depending on the duplex mode
|
||||
struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14);
|
||||
struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14);
|
||||
#if defined K_RELEASE
|
||||
struct xran_prb_map prachPm = get_xran_prb_map_prach(fh_config);
|
||||
#endif
|
||||
struct xran_prb_map dlPmMixed = {0};
|
||||
struct xran_prb_map ulPmMixed = {0};
|
||||
uint32_t idx = 0;
|
||||
@@ -297,92 +330,145 @@ static void oran_allocate_buffers(void *handle,
|
||||
.mixedSlotMap = ulPmMixed,
|
||||
};
|
||||
|
||||
#if defined F_RELEASE
|
||||
uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu);
|
||||
uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
|
||||
#if defined K_RELEASE
|
||||
oran_cplane_prb_config prachConf = {
|
||||
.nTddPeriod = fh_config->frame_conf.nTddPeriod,
|
||||
.mixed_slot_index = idx,
|
||||
.slotMap = prachPm,
|
||||
.mixedSlotMap = prachPm,
|
||||
};
|
||||
|
||||
uint32_t numPrbElmPrach = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&prachPm, mtu);
|
||||
uint32_t size_of_prb_map_prach = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElmPrach);
|
||||
#endif
|
||||
|
||||
// PDSCH
|
||||
#if defined K_RELEASE
|
||||
const uint32_t txBufSize = get_nSW_ToFpga_FTH_TxBufferLen(fh_config->nNumerology[0], fh_config->max_sections_per_slot);
|
||||
#elif defined F_RELEASE
|
||||
const uint32_t txBufSize = get_nSW_ToFpga_FTH_TxBufferLen(fh_config->frame_conf.nNumerology, fh_config->max_sections_per_slot);
|
||||
#endif
|
||||
oran_allocate_uplane_buffers(pi->instanceHandle, bl->src, bl->bufs.tx, xran_max_antenna_nr, txBufSize);
|
||||
oran_allocate_cplane_buffers(pi->instanceHandle,
|
||||
bl->srccp,
|
||||
bl->bufs.tx_prbmap,
|
||||
xran_max_antenna_nr,
|
||||
xran_max_sections_per_slot,
|
||||
#if defined F_RELEASE
|
||||
mtu,
|
||||
fh_config,
|
||||
#endif
|
||||
size_of_prb_map,
|
||||
&dlConf);
|
||||
|
||||
// PUSCH
|
||||
#if defined K_RELEASE
|
||||
const uint32_t rxBufSize = get_nFpgaToSW_FTH_RxBufferLen(fh_config->nNumerology[0]);
|
||||
#elif defined F_RELEASE
|
||||
const uint32_t rxBufSize = get_nFpgaToSW_FTH_RxBufferLen(fh_config->frame_conf.nNumerology);
|
||||
#endif
|
||||
oran_allocate_uplane_buffers(pi->instanceHandle, bl->dst, bl->bufs.rx, xran_max_antenna_nr, rxBufSize);
|
||||
oran_allocate_cplane_buffers(pi->instanceHandle,
|
||||
bl->dstcp,
|
||||
bl->bufs.rx_prbmap,
|
||||
xran_max_antenna_nr,
|
||||
xran_max_sections_per_slot,
|
||||
#if defined F_RELEASE
|
||||
mtu,
|
||||
fh_config,
|
||||
#endif
|
||||
size_of_prb_map,
|
||||
&ulConf);
|
||||
|
||||
// PRACH
|
||||
const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES;
|
||||
oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize);
|
||||
#if defined K_RELEASE
|
||||
oran_allocate_cplane_buffers(pi->instanceHandle,
|
||||
bl->prachdstdecomp,
|
||||
bl->bufs.prachdecomp,
|
||||
xran_max_antenna_nr,
|
||||
xran_max_sections_per_slot,
|
||||
mtu,
|
||||
fh_config,
|
||||
size_of_prb_map_prach,
|
||||
&prachConf);
|
||||
#elif defined F_RELEASE
|
||||
// PRACH decomp buffer does not have separate DPDK-allocated memory pool
|
||||
// bufs, it points to the same pool as the prach buffer. Unclear to me why
|
||||
for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) {
|
||||
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
|
||||
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j][0];
|
||||
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j];
|
||||
for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) {
|
||||
struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k];
|
||||
fb->pData = bl->prachdst[a][j].pBuffers[k].pData;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *dst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *dstcp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *prachdst[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
struct xran_buffer_list *prachdstdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
for (uint32_t a = 0; a < XRAN_MAX_ANTENNA_NR; ++a) {
|
||||
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
|
||||
src[a][j] = &bl->src[a][j];
|
||||
srccp[a][j] = &bl->srccp[a][j];
|
||||
dst[a][j] = &bl->dst[a][j];
|
||||
dstcp[a][j] = &bl->dstcp[a][j];
|
||||
prach[a][j] = &bl->prachdst[a][j];
|
||||
prachdecomp[a][j] = &bl->prachdstdecomp[a][j];
|
||||
prachdst[a][j] = &bl->prachdst[a][j];
|
||||
prachdstdecomp[a][j] = &bl->prachdstdecomp[a][j];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined K_RELEASE
|
||||
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]);
|
||||
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
|
||||
#elif defined F_RELEASE
|
||||
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
|
||||
xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
|
||||
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
|
||||
#endif
|
||||
}
|
||||
|
||||
int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_config *xran_fh_config)
|
||||
void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_config *xran_fh_config)
|
||||
{
|
||||
int32_t xret = 0;
|
||||
|
||||
#if defined K_RELEASE
|
||||
xran_mem_mgr_leak_detector_init();
|
||||
#endif
|
||||
|
||||
print_fh_init(xran_fh_init);
|
||||
#if defined F_RELEASE
|
||||
xret = xran_init(0, NULL, xran_fh_init, NULL, &gxran_handle);
|
||||
#elif defined K_RELEASE
|
||||
xret = xran_init(0, NULL, xran_fh_init, NULL, gxran_handle);
|
||||
#endif
|
||||
if (xret != XRAN_STATUS_SUCCESS) {
|
||||
printf("xran_init failed %d\n", xret);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#if defined K_RELEASE
|
||||
for (int32_t o_xu_id = 0; o_xu_id < xran_fh_init->xran_ports; o_xu_id++) {
|
||||
if (gxran_handle[o_xu_id] == NULL) {
|
||||
printf("xran_init for RU%d failed\n", o_xu_id);
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("RU%d handle = %p\n", o_xu_id, gxran_handle[o_xu_id]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** process all the O-RU|O-DU for use case */
|
||||
for (int32_t o_xu_id = 0; o_xu_id < xran_fh_init->xran_ports; o_xu_id++) {
|
||||
print_fh_config(&xran_fh_config[o_xu_id]);
|
||||
#if defined F_RELEASE
|
||||
xret = xran_open(gxran_handle, &xran_fh_config[o_xu_id]);
|
||||
#elif defined K_RELEASE
|
||||
xret = xran_open(gxran_handle[o_xu_id], &xran_fh_config[o_xu_id]);
|
||||
#endif
|
||||
if (xret != XRAN_STATUS_SUCCESS) {
|
||||
printf("xran_open failed %d\n", xret);
|
||||
exit(-1);
|
||||
@@ -394,20 +480,35 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
|
||||
struct xran_cb_tag tag = {.cellId = sector, .oXuId = o_xu_id};
|
||||
pi->prach_tag = tag;
|
||||
pi->pusch_tag = tag;
|
||||
#if defined F_RELEASE
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
#endif
|
||||
|
||||
#if defined K_RELEASE
|
||||
oran_allocate_buffers(gxran_handle[0], o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
if ((xret = xran_timingsource_reg_tticb(NULL, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
|
||||
printf("xran_timingsource_reg_tticb failed %d\n", xret);
|
||||
exit(-1);
|
||||
}
|
||||
#elif defined F_RELEASE
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
|
||||
printf("xran_reg_physide_cb failed %d\n", xret);
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// retrieve and store prach duration
|
||||
#if defined K_RELEASE
|
||||
uint8_t mu = xran_fh_config[o_xu_id].nNumerology[0];
|
||||
uint8_t idx = xran_fh_config[o_xu_id].perMu[mu].prach_conf.nPrachConfIdx;
|
||||
#elif defined F_RELEASE
|
||||
uint8_t idx = xran_fh_config[o_xu_id].prach_conf.nPrachConfIdx;
|
||||
#endif
|
||||
const struct xran_frame_config *fc = &xran_fh_config[o_xu_id].frame_conf;
|
||||
g_prach_info[o_xu_id] = get_nr_prach_occasion_info_from_index(idx,
|
||||
#if defined K_RELEASE
|
||||
mu > 2 ? FR2 : FR1,
|
||||
#elif defined F_RELEASE
|
||||
fc->nNumerology > 2 ? FR2 : FR1,
|
||||
#endif
|
||||
fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD);
|
||||
}
|
||||
|
||||
@@ -416,7 +517,7 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
|
||||
memcpy(&g_fh_init, xran_fh_init, sizeof(*xran_fh_init));
|
||||
memcpy(&g_fh_config, xran_fh_config, sizeof(*xran_fh_config) * xran_fh_init->xran_ports);
|
||||
|
||||
return (void *)gxran_handle;
|
||||
return gxran_handle;
|
||||
}
|
||||
|
||||
oran_buf_list_t *get_xran_buffers(uint32_t port_id)
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef struct oran_bufs {
|
||||
struct xran_flat_buffer rx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
|
||||
struct xran_flat_buffer prach[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
struct xran_flat_buffer prachdecomp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
|
||||
} oran_bufs_t;
|
||||
|
||||
typedef struct oran_buf_list {
|
||||
@@ -41,9 +41,13 @@ typedef struct oran_port_instance_t {
|
||||
} oran_port_instance_t;
|
||||
|
||||
extern struct xran_fh_config gxran_fh_config[XRAN_PORTS_NUM];
|
||||
#if defined F_RELEASE
|
||||
extern void *gxran_handle;
|
||||
#elif defined K_RELEASE
|
||||
extern void *gxran_handle[XRAN_PORTS_NUM];
|
||||
#endif
|
||||
|
||||
int *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh_config);
|
||||
void *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh_config);
|
||||
|
||||
oran_buf_list_t *get_xran_buffers(uint32_t port_id);
|
||||
struct xran_fh_init *get_xran_fh_init(void);
|
||||
|
||||
@@ -13,11 +13,4 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot);
|
||||
|
||||
int transport_init(openair0_device_t *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
|
||||
|
||||
typedef struct {
|
||||
eth_state_t e;
|
||||
shared_buffers buffers;
|
||||
rru_config_msg_type_t last_msg;
|
||||
int capabilities_sent;
|
||||
void *oran_priv;
|
||||
} oran_eth_state_t;
|
||||
#endif /* _ORAN_H_ */
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "oaioran.h"
|
||||
#include "oran-config.h"
|
||||
|
||||
@@ -33,9 +32,14 @@ typedef struct {
|
||||
int capabilities_sent;
|
||||
void *oran_priv;
|
||||
void *mplane_priv;
|
||||
uint32_t nCC;
|
||||
uint32_t num_ports;
|
||||
} oran_eth_state_t;
|
||||
|
||||
notifiedFIFO_t oran_sync_fifo;
|
||||
#if defined K_RELEASE
|
||||
notifiedFIFO_t oran_sync_fifo_prach;
|
||||
#endif
|
||||
|
||||
int trx_oran_start(openair0_device_t *device)
|
||||
{
|
||||
@@ -44,12 +48,53 @@ int trx_oran_start(openair0_device_t *device)
|
||||
oran_eth_state_t *s = device->priv;
|
||||
|
||||
// Start ORAN
|
||||
#if defined K_RELEASE
|
||||
if (xran_timingsource_start() != 0) {
|
||||
printf("%s:%d:%s: Start timing source failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Start timing source. Done\n");
|
||||
}
|
||||
|
||||
if (xran_start_worker_threads() != 0) {
|
||||
printf("%s:%d:%s: Start worker thread failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Start worker thread. Done\n");
|
||||
}
|
||||
|
||||
xran_mem_mgr_leak_detector_display(0);
|
||||
#endif
|
||||
|
||||
#if defined F_RELEASE
|
||||
if (xran_start(s->oran_priv) != 0) {
|
||||
printf("%s:%d:%s: Start ORAN failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Start ORAN. Done\n");
|
||||
}
|
||||
#elif defined K_RELEASE
|
||||
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
|
||||
if (xran_start(((void **)s->oran_priv)[port_id]) != 0) {
|
||||
printf("%s:%d:%s: Start ORAN port ID %d failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__, port_id);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("Start ORAN. Done\n");
|
||||
|
||||
#if defined K_RELEASE
|
||||
for (int32_t cc_id = 0; cc_id < s->nCC; cc_id++) {
|
||||
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
|
||||
if (xran_activate_cc(port_id, cc_id) != 0) {
|
||||
printf("%s:%d:%s: Activate CC failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Activate CC. Done\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,14 +102,39 @@ void trx_oran_end(openair0_device_t *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
oran_eth_state_t *s = device->priv;
|
||||
#if defined K_RELEASE
|
||||
xran_shutdown(s->oran_priv);
|
||||
#endif
|
||||
xran_close(s->oran_priv);
|
||||
#if defined K_RELEASE
|
||||
xran_cleanup();
|
||||
xran_mem_mgr_leak_detector_destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
int trx_oran_stop(openair0_device_t *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
oran_eth_state_t *s = device->priv;
|
||||
|
||||
#if defined K_RELEASE
|
||||
for (int32_t cc_id = 0; cc_id < s->nCC; cc_id++) {
|
||||
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
|
||||
xran_deactivate_cc(port_id, cc_id);
|
||||
}
|
||||
}
|
||||
|
||||
xran_timingsource_stop();
|
||||
#endif
|
||||
|
||||
#if defined F_RELEASE
|
||||
xran_stop(s->oran_priv);
|
||||
#elif defined K_RELEASE
|
||||
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
|
||||
xran_stop(((void **)s->oran_priv)[port_id]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OAI_MPLANE
|
||||
printf("[MPLANE] Stopping M-plane.\n");
|
||||
disconnect_mplane(s->mplane_priv);
|
||||
@@ -196,6 +266,8 @@ int trx_oran_ctlrecv(openair0_device_t *device, void *msg, ssize_t msg_len)
|
||||
|
||||
void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
int ret = 0; // return code for PUSCH/PRACH processing
|
||||
|
||||
ru_info_t ru_info = {
|
||||
.nb_rx = ru->nb_rx * ru->num_beams_period,
|
||||
.nb_tx = ru->nb_tx * ru->num_beams_period,
|
||||
@@ -205,33 +277,30 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
.prach_buf = NULL,
|
||||
};
|
||||
|
||||
prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, SEARCH_EXIST);
|
||||
if (prach_id) {
|
||||
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
|
||||
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
|
||||
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
|
||||
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
|
||||
nr_prach_info_t prach_info = get_prach_info(0);
|
||||
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
|
||||
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled
|
||||
if (is_prach_slot) {
|
||||
ru_info.prach_buf = prach_id->prach_buf;
|
||||
} else {
|
||||
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot);
|
||||
}
|
||||
}
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
/* Firstly, process PUSCH packets */
|
||||
RU_proc_t *proc = &ru->proc; // to check if (frame,slot) combination corresponds to the expected PUSCH one
|
||||
int f, sl;
|
||||
LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
|
||||
ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
|
||||
stop_meas(&ru->rx_fhaul);
|
||||
LOG_D(HW, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]);
|
||||
if (ret != 0) {
|
||||
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
|
||||
}
|
||||
|
||||
/* Secondly, process PRACH packets */
|
||||
int f_prach, sl_prach;
|
||||
#if defined F_RELEASE
|
||||
// no PRACH callback (no queue) in F release so use the expected combination
|
||||
f_prach = *frame;
|
||||
sl_prach = *slot;
|
||||
#endif
|
||||
ret = xran_fh_rx_prach_read_slot(&ru->gNB_list[0]->prach_list, &ru_info, &f_prach, &sl_prach);
|
||||
if (ret != 0) {
|
||||
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX PRACH function \n", f_prach, sl_prach);
|
||||
}
|
||||
|
||||
int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster);
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
@@ -239,6 +308,7 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
proc->frame_tx = (sl > (slots_per_frame - 1 - ru->sl_ahead)) ? (f + 1) & 1023 : f;
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
print_fhi_counters(&ru_info, proc->frame_rx, proc->tti_rx);
|
||||
if (proc->tti_rx != *slot) {
|
||||
LOG_E(HW,
|
||||
"Received Time doesn't correspond to the time we think it is (slot mismatch, received %d.%d, expected %d.%d)\n",
|
||||
@@ -378,11 +448,16 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t
|
||||
// create message queues for ORAN sync
|
||||
|
||||
initNotifiedFIFO(&oran_sync_fifo);
|
||||
#if defined K_RELEASE
|
||||
initNotifiedFIFO(&oran_sync_fifo_prach);
|
||||
#endif
|
||||
|
||||
eth->e.flags = ETH_RAW_IF4p5_MODE;
|
||||
eth->e.compression = NO_COMPRESS;
|
||||
eth->e.if_name = eth_params->local_if_name;
|
||||
eth->last_msg = (rru_config_msg_type_t)-1;
|
||||
eth->nCC = fh_config->nCC;
|
||||
eth->num_ports = fh_init.xran_ports;
|
||||
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_oran_start;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "openair1/PHY/impl_defs_nr.h"
|
||||
#include "openair1/PHY/TOOLS/tools_defs.h"
|
||||
#include "openair1/PHY/defs_nr_common.h"
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
|
||||
/*
|
||||
* Structure added to bear the information needed from OAI RU
|
||||
*/
|
||||
@@ -38,12 +40,20 @@ typedef struct ru_info_s {
|
||||
c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
|
||||
} ru_info_t;
|
||||
|
||||
/** @brief Reads RX data (PRACH/PUSCH) of next slot.
|
||||
void print_fhi_counters(ru_info_t *ru, const int frame, const int slot);
|
||||
|
||||
/** @brief Reads RX data PUSCH of next slot.
|
||||
*
|
||||
* @param ru pointer to structure keeping pointers to OAI data.
|
||||
* @param frame output of the frame which has been read.
|
||||
* @param slot output of the slot which has been read. */
|
||||
int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot);
|
||||
/** @brief Reads RX data PRACH of next slot.
|
||||
*
|
||||
* @param ru pointer to structure keeping pointers to OAI data.
|
||||
* @param frame input for F_RELEASE, output for K_RELEASE.
|
||||
* @param slot input for F_RELEASE, output for K_RELEASE. */
|
||||
int xran_fh_rx_prach_read_slot(prach_list_t *prach_list, ru_info_t *ru, int *frame, int *slot);
|
||||
/** @brief Writes TX data (PDSCH) of given slot. */
|
||||
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user