diff --git a/cmake_targets/tools/MODULES/Findxran.cmake b/cmake_targets/tools/MODULES/Findxran.cmake index efb6db13ea..56035c1426 100644 --- a/cmake_targets/tools/MODULES/Findxran.cmake +++ b/cmake_targets/tools/MODULES/Findxran.cmake @@ -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 # ^^^^^^^^^^^^^^^^ @@ -46,13 +46,7 @@ # ``xran_LIBRARY`` # The path to the xran library. -option(xran_LOCATION "directory of XRAN library" "") -if (NOT xran_LOCATION) - message(FATAL_ERROR "xran_LOCATION required") -endif() -if (NOT EXISTS ${xran_LOCATION}) - message(FATAL_ERROR "no such directory: ${xran_LOCATION}") -endif() +set(CACHE{xran_LOCATION} TYPE PATH HELP "directory of XRAN library" VALUE "") find_path(xran_INCLUDE_DIR NAMES @@ -73,27 +67,26 @@ find_library(xran_LIBRARY PATH_SUFFIXES build api NO_DEFAULT_PATH ) -if (NOT xran_LIBRARY) - message(FATAL_ERROR "could not detect xran build artifacts at ${xran_LOCATION}/build") -endif() set(xran_VERSION_FILE "${xran_LOCATION}/../app/src/common.h") -if(NOT EXISTS ${xran_VERSION_FILE}) - message(FATAL_ERROR "could not find xran version file at ${xran_VERSION_FILE}") +if(EXISTS ${xran_VERSION_FILE}) + file(STRINGS ${xran_VERSION_FILE} xran_VERSION_LINE REGEX "^#define[ \t]+VERSIONX[ \t]+\"[a-z_.0-9]+\"$") +else() + set(xran_VERSION_LINE "UNKNOWN") endif() -file(STRINGS ${xran_VERSION_FILE} xran_VERSION_LINE REGEX "^#define[ \t]+VERSIONX[ \t]+\"[a-z_.0-9]+\"$") string(REGEX REPLACE "^#define[ \t]+VERSIONX[ \t]+\"([a-z_.0-9]+)\"$" "\\1" xran_VERSION_STRING "${xran_VERSION_LINE}") 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() - message(FATAL_ERROR "unrecognized xran version string: ${xran_VERSION_STRING}") + set(xran_VERSION "UNKNOWN") endif() -message(STATUS "Found xran release ${xran_VERSION_STRING} (v${xran_VERSION})") unset(xran_VERSION_LINE) unset(xran_VERSION_STRING) unset(xran_VERSION_FILE) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 051962fdb2..2633396e0b 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -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 @@ -290,10 +291,11 @@ wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz ```bash # Installing meson : it should pull ninja-build and compiler packages # on debian -sudo apt install meson +sudo apt install python3-pyelftools meson # on Fedora/RHEL -sudo dnf install meson -tar xvf dpdk-20.11.9.tar.xz && cd dpdk-stable-20.11.9 +sudo dnf install python3-pyelftools meson +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,13 @@ 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://github.com/openairinterface/o-du-phy.git ~/phy +cd ~/phy +git checkout # shall match a variable `K_VERSION` +``` + 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 +408,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 @@ -483,23 +494,13 @@ Note that you might also call cmake directly instead of using `build_oai`: ``` cd ~/openairinterface5g mkdir build && cd build +# build RAN after manually building xran F or K release cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib +# build RAN and xran K release automatically +cmake .. -GNinja -DOAI_FHI72=ON -Dxran_DOWNLOAD=ON 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. @@ -1636,6 +1637,8 @@ PKG_CONFIG_PATH=/opt/mplane-v2/lib/pkgconfig cmake .. -GNinja -DOAI_FHI72=ON -DO ninja nr-softmodem oran_fhlib_5g_mplane params_libconfig ``` +Note: instead of setting `xran_LOCATION`, feel free to use `xran_DOWNLOAD` option for automatic xran K release build. + ### Start the gNB Run the `nr-softmodem` from the build directory: ```bash diff --git a/docker/Dockerfile.base.rhel9 b/docker/Dockerfile.base.rhel9 index 7ed085faf5..d838b038f9 100644 --- a/docker/Dockerfile.base.rhel9 +++ b/docker/Dockerfile.base.rhel9 @@ -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 diff --git a/docker/Dockerfile.build.fhi72.native_arm.ubuntu b/docker/Dockerfile.build.fhi72.native_arm.ubuntu index 8aa77c3b33..eb3dd4b7c7 100644 --- a/docker/Dockerfile.build.fhi72.native_arm.ubuntu +++ b/docker/Dockerfile.build.fhi72.native_arm.ubuntu @@ -9,6 +9,7 @@ FROM ran-base:latest AS ran-base +ARG xran_VERSION=11.1.1 ARG E2AP_VERSION=E2AP_V3 ARG KPM_VERSION=KPM_V3_00 ENV DEBIAN_FRONTEND=noninteractive @@ -20,7 +21,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 +30,19 @@ 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 $xran_VERSION &&\ 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 && \ diff --git a/docker/Dockerfile.build.fhi72.rhel9 b/docker/Dockerfile.build.fhi72.rhel9 index 315d1367bb..ec26015da2 100644 --- a/docker/Dockerfile.build.fhi72.rhel9 +++ b/docker/Dockerfile.build.fhi72.rhel9 @@ -14,10 +14,12 @@ RUN rm -Rf /oai-ran WORKDIR /oai-ran COPY . . +ARG xran_VERSION=11.1.1 + ## 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 +27,9 @@ 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 $xran_VERSION &&\ 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 diff --git a/docker/Dockerfile.build.fhi72.ubuntu b/docker/Dockerfile.build.fhi72.ubuntu index 3375be7ff7..d9149171fb 100644 --- a/docker/Dockerfile.build.fhi72.ubuntu +++ b/docker/Dockerfile.build.fhi72.ubuntu @@ -9,6 +9,7 @@ FROM ran-base:latest AS ran-base +ARG xran_VERSION=11.1.1 ARG E2AP_VERSION=E2AP_V3 ARG KPM_VERSION=KPM_V3_00 ENV DEBIAN_FRONTEND=noninteractive @@ -20,7 +21,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 +30,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 +40,9 @@ 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 $xran_VERSION &&\ 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 diff --git a/docker/Dockerfile.gNB.fhi72.rhel9 b/docker/Dockerfile.gNB.fhi72.rhel9 index 1fc3d18d37..d1afe4ffd4 100644 --- a/docker/Dockerfile.gNB.fhi72.rhel9 +++ b/docker/Dockerfile.gNB.fhi72.rhel9 @@ -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 && \ diff --git a/docker/Dockerfile.gNB.fhi72.rocky b/docker/Dockerfile.gNB.fhi72.rocky index 09ead432e8..3a25062fea 100644 --- a/docker/Dockerfile.gNB.fhi72.rocky +++ b/docker/Dockerfile.gNB.fhi72.rocky @@ -18,6 +18,7 @@ ENV TZ=Europe/Paris RUN dnf update -y && \ dnf install -y \ procps-ng \ + libatomic \ libXpm \ libX11 \ lksctp-tools \ diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu b/docker/Dockerfile.gNB.fhi72.ubuntu index 132f22c9a6..84758df455 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu +++ b/docker/Dockerfile.gNB.fhi72.ubuntu @@ -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 \ diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 1198e5bd02..59f8b96194 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -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++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index dc3cb1950d..efcc3dae1b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -34,7 +34,8 @@ static bool drop_old_prach(const void *data, void *user) { const prach_item_t *p = data; const fsn_t *now = user; - const fsn_t t = {p->frame, p->slot, now->mu}; + // account for long PRACH over more than 1 slot + const fsn_t t = {p->frame, p->slot + p->num_slots - 1, now->mu}; bool drop = fsn_in_the_past(t, *now); if (drop) LOG_E(NR_PHY, "%4d.%2d PRACH job is in the past (%4d.%2d)\n", now->f, now->s, t.f, t.s); @@ -45,7 +46,8 @@ static bool get_current_prach(const void *data, void *user) { const prach_item_t *p = data; const fsn_t *now = user; - const fsn_t t = {p->frame, p->slot, now->mu}; + // account for long PRACH over more than 1 slot + const fsn_t t = {p->frame, p->slot + p->num_slots - 1, now->mu}; return fsn_equal(t, *now); } diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index c9c51f7d80..549fe0b2ed 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -19,14 +19,56 @@ 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) +add_boolean_option(xran_DOWNLOAD OFF "Download and build xran library" OFF) + +find_package(xran) +if(xran_FOUND) + 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} or K version ${K_VERSION}") + elseif(xran_VERSION VERSION_EQUAL F_VERSION) + target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE) + elseif(xran_VERSION VERSION_EQUAL K_VERSION) + if(dpdk_VERSION VERSION_LESS 22) + message(FATAL_ERROR "DPDK version miniminum 22 required for K release, but found ${dpdk_VERSION}") + endif() + target_compile_definitions(oran_fhlib_5g PRIVATE K_RELEASE) + else() + message(FATAL_ERROR "Found xran version ${xran_VERSION} but needed ${F_VERSION} (F release) or ${K_VERSION} (K release)") + endif() +elseif(NOT xran_FOUND AND xran_DOWNLOAD) + if(dpdk_VERSION VERSION_LESS 22) + message(FATAL_ERROR "DPDK version miniminum 22 required for K release, but found ${dpdk_VERSION}") + endif() + include(ExternalProject) + set(xran_DIR "${CMAKE_BINARY_DIR}/.deps/src/extern_xran/fhi_lib/lib") + ExternalProject_Add(extern_xran + PREFIX ${CMAKE_BINARY_DIR}/.deps + GIT_REPOSITORY https://github.com/openairinterface/o-du-phy.git + GIT_TAG ${K_VERSION} + CONFIGURE_COMMAND "" # nothing to configure + BUILD_COMMAND cd fhi_lib/lib && WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=${dpdk_PREFIX} XRAN_DIR=.. make XRAN_LIB_SO=1 + BUILD_IN_SOURCE ON + INSTALL_COMMAND "" + BUILD_BYPRODUCTS ${xran_DIR}/build/libxran.so + ) + add_library(xran::xran UNKNOWN IMPORTED) + add_dependencies(xran::xran extern_xran) + # This is a workaround for the fact that included directories of an imported + # target should exist in the filesystem already at the configuration time. + # ref: https://gitlab.kitware.com/cmake/cmake/-/issues/15052 + file(MAKE_DIRECTORY "${xran_DIR}/api/") + file(MAKE_DIRECTORY "${xran_DIR}/build/") + set_target_properties(xran::xran PROPERTIES + IMPORTED_LOCATION "${xran_DIR}/build/libxran.so" + INTERFACE_INCLUDE_DIRECTORIES "${xran_DIR}/api/" + ) + message(STATUS "xran not found. Will clone and build automatically K release ${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 "could not find xran, and auto-download disabled. Update + xran_LOCATION, or set -Dxran_DOWNLOAD=ON") endif() # Ignore xran-specific warning: we don't care/can't change the following warning, so suppress @@ -43,8 +85,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}) diff --git a/radio/fhi_72/README.md b/radio/fhi_72/README.md index e0585d22dc..a631e72641 100644 --- a/radio/fhi_72/README.md +++ b/radio/fhi_72/README.md @@ -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. diff --git a/radio/fhi_72/mplane/CMakeLists.txt b/radio/fhi_72/mplane/CMakeLists.txt index b25402cfce..4ed91cfb7a 100644 --- a/radio/fhi_72/mplane/CMakeLists.txt +++ b/radio/fhi_72/mplane/CMakeLists.txt @@ -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 diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index cca7d6190b..6aaaa0d8fb 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -25,32 +25,91 @@ #include "oran-config.h" // for g_kbar #include "common/utils/threadPool/notified_fifo.h" +#include "common/utils/fsn.h" #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 +119,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 +178,32 @@ 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; + + for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { + oran_buf_list_t *bufs = get_xran_buffers(ru_idx); + struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx); + 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 +211,98 @@ 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; + for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { + oran_buf_list_t *bufs = get_xran_buffers(ru_idx); + struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx); + 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 +310,72 @@ 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(PHY_VARS_gNB *gNB, 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 p; + fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index}; + if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { + 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); + bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe) +#if defined K_RELEASE + , mu +#endif + ); // `p.slot` = slot in which PRACH is scheduled + if (is_prach_slot) { + ru->prach_buf = p.prach_buf; + } else { + LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot); + } + } else { + return (0); + } + /* calculate tti and subframe_id from frame, slot num */ int sym_idx = 0; @@ -174,20 +396,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 +480,17 @@ 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 + + // after reading PRACH, write back to queue + bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p)); + // assume prach_l1rx_queue never full: prach_ru_queue filled at + // constant pace, but prach_l1rx_queue emptied as fast as possible, + // see rx_func() + DevAssert(success); + return (0); } @@ -287,9 +546,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 +559,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 +584,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 +638,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 +739,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 +756,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 +787,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 +892,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"); diff --git a/radio/fhi_72/oaioran.h b/radio/fhi_72/oaioran.h index 3bb3a21970..324fd55283 100644 --- a/radio/fhi_72/oaioran.h +++ b/radio/fhi_72/oaioran.h @@ -12,11 +12,30 @@ typedef struct { uint32_t tti; uint32_t sl; uint32_t f; +#if defined K_RELEASE + uint8_t mu; + // the first column can expand to XRAN_MAX_SECTOR_NR for the support of multiple CCs + int32_t nRxPkt[1][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 */ diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 8da11c64ed..ca7c1527dd 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -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 } @@ -437,10 +592,8 @@ static void get_u128_mask(const paramdef_t *pd, uint64_t *u0t63, uint64_t *u64t1 } } -#if defined F_RELEASE char bbdev_dev[32] = ""; char bbdev_vfio_vf_token[64] = ""; -#endif static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_rus) { @@ -511,6 +664,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,13 +693,53 @@ 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; } +#if defined K_RELEASE +static bool set_fh_bbdev_params(struct xran_fh_init *fh_init) +{ + struct xran_io_cfg *io_cfg = &fh_init->io_cfg; + io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 + fh_init->dpdkVfioVfToken = NULL; // BBDev dev token; max devices = 1 + char *shlibversion = NULL; // version of the LDPC coding library + paramdef_t LoaderParams_shlibversion[] = {{"shlibversion", NULL, 0, .strptr = &shlibversion, .defstrval = NULL, TYPE_STRING, 0, NULL}}; + config_get(config_get_if(), LoaderParams_shlibversion, sizeofArray(LoaderParams_shlibversion), "loader.ldpc"); + if (shlibversion != NULL && strncmp(shlibversion, "_aal", 4) == 0) { + uint32_t is_t2 = 0; // If not 0 then include the BBDEV device in the EAL init for FHI + char *dpdk_dev = NULL; // PCI address of the card + char *vfio_vf_token = NULL; // vfio token for the bbdev card + paramdef_t LoaderParams[] = { + {"is_t2", NULL, 0, .uptr = &is_t2, .defuintval = 0, TYPE_UINT, 0, NULL}, + {"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL}, + {"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL} + }; + config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal"); + + if (!is_t2) { + AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_aal.dpdk_dev was not provided"); + snprintf(&bbdev_dev[0], sizeof(bbdev_dev), "%s", dpdk_dev); + io_cfg->bbdev_dev[0] = &bbdev_dev[0]; // BBDev dev name; max devices = 1 + if(vfio_vf_token != NULL) { + snprintf(&bbdev_vfio_vf_token[0], sizeof(bbdev_vfio_vf_token), "%s", vfio_vf_token); + fh_init->dpdkVfioVfToken = &bbdev_vfio_vf_token[0]; // BBDev dev token; max devices = 1 + } else { + fh_init->dpdkVfioVfToken = NULL; // BBDev dev token; max devices = 1 + } + io_cfg->bbdev_mode = XRAN_BBDEV_MODE_HW_ON; // DPDK for BBDev + } else { + io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev + } + } else { + io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev + } + + return true; +} +#endif + #ifdef OAI_MPLANE static bool set_fh_eaxcid_conf_mplane(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat, const ru_session_list_t *ru_session_list) { @@ -575,7 +772,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 +863,18 @@ 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 + if (!set_fh_bbdev_params(fh_init)) + return false; + 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 +898,18 @@ 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 + if (!set_fh_bbdev_params(fh_init)) + return false; + 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 +953,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 +995,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 +1004,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 +1027,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 +1047,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 +1070,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 +1097,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 +1220,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 +1239,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 +1255,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 +1269,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 +1322,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; diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index ec5f6d0f8c..8d1e01023a 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -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,36 @@ 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 + LOG_W(HW, "Please be aware that F release support will be removed in the future. Consider switching to K release.\n"); + 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 +518,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) diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index ed1076d483..d1d4d43ee9 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -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); diff --git a/radio/fhi_72/oran.h b/radio/fhi_72/oran.h index 08d7574f49..d322f35f1e 100644 --- a/radio/fhi_72/oran.h +++ b/radio/fhi_72/oran.h @@ -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_ */ diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 3a670f5f7f..5d3a624555 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -12,9 +12,7 @@ #include "xran_sync_api.h" #include "common/utils/LOG/log.h" -#include "common/utils/fsn.h" #include "openair1/PHY/defs_gNB.h" -#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h" #include "oaioran.h" #include "oran-config.h" @@ -34,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) { @@ -45,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; } @@ -58,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); @@ -197,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, @@ -206,42 +277,28 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) .prach_buf = NULL, }; - prach_item_t p; - PHY_VARS_gNB *gNB = ru->gNB_list[0]; - fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index}; - if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) { - 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, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled - if (is_prach_slot) { - ru_info.prach_buf = p.prach_buf; - } else { - LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.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); } - if (ru_info.prach_buf) { - // xran_fh_rx_read_slot() should have read PRACH, write back to queue - bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p)); - // assume prach_l1rx_queue never full: prach_ru_queue filled at - // constant pace, but prach_l1rx_queue emptied as fast as possible, - // see rx_func() - DevAssert(success); + /* 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], &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); @@ -251,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", @@ -390,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; diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index afdf443596..24ee524656 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -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(PHY_VARS_gNB *gNB, 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);