Merge remote-tracking branch 'origin/oru-rebased' into integration_2026_w05 (!3848)
Initial implementation of O-RU for 7.2 emulator Added new executable nr-oru which acts as a 7.2 O-RU.
This commit is contained in:
@@ -1789,6 +1789,24 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIE
|
|||||||
target_link_libraries(lte-uesoftmodem PRIVATE
|
target_link_libraries(lte-uesoftmodem PRIVATE
|
||||||
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
|
asn1_lte_rrc asn1_s1ap asn1_m2ap asn1_m3ap asn1_x2ap)
|
||||||
|
|
||||||
|
# nr RRU
|
||||||
|
add_executable(nr-oru
|
||||||
|
${OPENAIR_DIR}/executables/nr-ru.c
|
||||||
|
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
|
||||||
|
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
|
||||||
|
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
|
||||||
|
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
|
||||||
|
${OPENAIR_DIR}/radio/COMMON/common_lib.c
|
||||||
|
${OPENAIR_DIR}/radio/COMMON/record_player.c
|
||||||
|
${OPENAIR_DIR}/executables/softmodem-common.c
|
||||||
|
${OPENAIR_DIR}/executables/main_nr_ru.c
|
||||||
|
)
|
||||||
|
target_link_libraries(nr-oru PRIVATE
|
||||||
|
UTIL SCHED_RU_LIB PHY_COMMON PHY_RU PHY_NR shlib_loader z dl)
|
||||||
|
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
|
||||||
|
barrier actor)
|
||||||
|
target_link_libraries(nr-oru PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_phy_common time_management)
|
||||||
|
|
||||||
# nr-softmodem
|
# nr-softmodem
|
||||||
###################################################
|
###################################################
|
||||||
|
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ class Containerize():
|
|||||||
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
|
||||||
imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
|
imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
|
||||||
imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
|
imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
|
||||||
|
imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
|
||||||
result = re.search('build_cross_arm64', self.imageKind)
|
result = re.search('build_cross_arm64', self.imageKind)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
self.dockerfileprefix = '.ubuntu.cross-arm64'
|
self.dockerfileprefix = '.ubuntu.cross-arm64'
|
||||||
@@ -412,7 +413,7 @@ class Containerize():
|
|||||||
# target images should use the proper ran-build image
|
# target images should use the proper ran-build image
|
||||||
if image != 'ran-build' and "-asan" in name:
|
if image != 'ran-build' and "-asan" in name:
|
||||||
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
||||||
elif "fhi72" in name:
|
elif "fhi72" in name or name == "oai-nr-oru":
|
||||||
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
||||||
elif image != 'ran-build':
|
elif image != 'ran-build':
|
||||||
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ Options:
|
|||||||
Makes the NR softmodem
|
Makes the NR softmodem
|
||||||
--RU
|
--RU
|
||||||
Makes the OAI RRU
|
Makes the OAI RRU
|
||||||
|
--nrRU
|
||||||
|
Makes the NR RRU
|
||||||
--UE
|
--UE
|
||||||
Makes the UE specific parts (usim, nvram) from the given configuration file
|
Makes the UE specific parts (usim, nvram) from the given configuration file
|
||||||
--nrUE
|
--nrUE
|
||||||
@@ -227,6 +229,11 @@ function main() {
|
|||||||
TARGET_LIST="$TARGET_LIST oairu"
|
TARGET_LIST="$TARGET_LIST oairu"
|
||||||
echo_info "Will compile RRU"
|
echo_info "Will compile RRU"
|
||||||
shift;;
|
shift;;
|
||||||
|
--nrRU)
|
||||||
|
NRRU=1
|
||||||
|
TARGET_LIST="$TARGET_LIST nr-oru"
|
||||||
|
echo_info "Will compile NR O-RU"
|
||||||
|
shift;;
|
||||||
--UE)
|
--UE)
|
||||||
UE=1
|
UE=1
|
||||||
TARGET_LIST="$TARGET_LIST lte-uesoftmodem conf2uedata usim nvram"
|
TARGET_LIST="$TARGET_LIST lte-uesoftmodem conf2uedata usim nvram"
|
||||||
@@ -452,7 +459,7 @@ function main() {
|
|||||||
if [[ $TARGET_LIST != "" ]] && [[ -f $OPENAIR_DIR/CMakeLists.txt ]]; then
|
if [[ $TARGET_LIST != "" ]] && [[ -f $OPENAIR_DIR/CMakeLists.txt ]]; then
|
||||||
# add some default libraries that should always be built
|
# add some default libraries that should always be built
|
||||||
# for eNB, gNB, UEs, simulators
|
# for eNB, gNB, UEs, simulators
|
||||||
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
|
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 || $NRRU == 1 ]]; then
|
||||||
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim rf_emulator"
|
TARGET_LIST="$TARGET_LIST params_libconfig coding rfsimulator dfts params_yaml vrtsim rf_emulator"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ RUN /bin/sh oaienv && \
|
|||||||
cd cmake_targets && \
|
cd cmake_targets && \
|
||||||
mkdir -p log && \
|
mkdir -p log && \
|
||||||
./build_oai \
|
./build_oai \
|
||||||
--ninja --gNB \
|
--ninja --gNB --nrRU \
|
||||||
--build-lib "telnetsrv enbscope uescope nrscope" \
|
--build-lib "telnetsrv enbscope uescope nrscope" \
|
||||||
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
|
-t oran_fhlib_5g --cmake-opt -Dxran_LOCATION=/opt/phy/fhi_lib/lib \
|
||||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#/*
|
||||||
|
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
# * contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# * this work for additional information regarding copyright ownership.
|
||||||
|
# * The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
# * except in compliance with the License.
|
||||||
|
# * You may obtain a copy of the License at
|
||||||
|
# *
|
||||||
|
# * http://www.openairinterface.org/?page_id=698
|
||||||
|
# *
|
||||||
|
# * Unless required by applicable law or agreed to in writing, software
|
||||||
|
# * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# * See the License for the specific language governing permissions and
|
||||||
|
# * limitations under the License.
|
||||||
|
# *-------------------------------------------------------------------------------
|
||||||
|
# * For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
# * contact@openairinterface.org
|
||||||
|
# */
|
||||||
|
|
||||||
|
FROM ran-base:latest AS ran-base
|
||||||
|
|
||||||
|
FROM ran-build-fhi72:latest AS ran-build
|
||||||
|
|
||||||
|
#start from scratch for target executable
|
||||||
|
FROM ubuntu:noble AS oai-nr-oru
|
||||||
|
ARG BUILD_OPTION
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Europe
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get upgrade --yes && \
|
||||||
|
apt-get install --yes \
|
||||||
|
software-properties-common \
|
||||||
|
procps \
|
||||||
|
pkg-config \
|
||||||
|
libsctp1 \
|
||||||
|
tzdata \
|
||||||
|
libblas3 \
|
||||||
|
libconfig9 \
|
||||||
|
openssl \
|
||||||
|
net-tools \
|
||||||
|
iperf \
|
||||||
|
iproute2 \
|
||||||
|
iputils-ping \
|
||||||
|
gdb \
|
||||||
|
pciutils \
|
||||||
|
libpcap-dev \
|
||||||
|
xz-utils \
|
||||||
|
libnuma-dev \
|
||||||
|
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 \
|
||||||
|
libasan8 \
|
||||||
|
libubsan1 \
|
||||||
|
liblapacke; fi' && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /opt/nr-oru/bin
|
||||||
|
COPY --from=ran-build \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/nr-oru ./
|
||||||
|
COPY ./docker/scripts/nr_oru_entrypoint.sh ./entrypoint.sh
|
||||||
|
|
||||||
|
COPY --from=ran-build \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/liboai_transpro.so \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
|
||||||
|
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||||
|
/usr/local/lib/
|
||||||
|
|
||||||
|
## Libxran library
|
||||||
|
COPY --from=ran-build \
|
||||||
|
/opt/phy/fhi_lib/lib/build/libxran.so \
|
||||||
|
/opt/phy/fhi_lib/lib/build/
|
||||||
|
|
||||||
|
## Copy all DPDK libraries as liboran_fhlib_5g.so require most of them
|
||||||
|
COPY --from=ran-build /usr/local/lib/x86_64-linux-gnu /usr/local/lib/x86_64-linux-gnu/
|
||||||
|
|
||||||
|
RUN ldconfig && \
|
||||||
|
echo "---- ldd on nr-oru ----" && \
|
||||||
|
ldd /opt/nr-oru/bin/nr-oru && \
|
||||||
|
echo "---- ldd on shared libraries ----" && \
|
||||||
|
ldd /usr/local/lib/liboai_transpro.so \
|
||||||
|
/usr/local/lib/libcoding.so \
|
||||||
|
/usr/local/lib/libparams_libconfig.so \
|
||||||
|
/usr/local/lib/libdfts.so \
|
||||||
|
/usr/local/lib/libldpc*.so \
|
||||||
|
/opt/phy/fhi_lib/lib/build/libxran.so
|
||||||
|
|
||||||
|
WORKDIR /opt/nr-oru
|
||||||
|
|
||||||
|
COPY --from=ran-base /usr/local/bin/yq /usr/local/bin/yq
|
||||||
|
COPY --from=ran-base /tini /tini
|
||||||
|
ENTRYPOINT ["/tini", "-v", "--", "/opt/nr-oru/bin/entrypoint.sh"]
|
||||||
|
CMD ["/opt/nr-oru/bin/nr-oru"]
|
||||||
Executable
+65
@@ -0,0 +1,65 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
PREFIX=/opt/nr-oru
|
||||||
|
CONFIGFILE=$PREFIX/etc/nr-oru.conf
|
||||||
|
|
||||||
|
echo "=================================="
|
||||||
|
echo "/proc/sys/kernel/core_pattern=$(cat /proc/sys/kernel/core_pattern)"
|
||||||
|
|
||||||
|
if [ ! -f $CONFIGFILE ]; then
|
||||||
|
echo "No configuration file $CONFIGFILE found: attempting to find YAML config"
|
||||||
|
YAML_CONFIGFILE=$PREFIX/etc/nr-oru.yaml
|
||||||
|
if [ ! -f $YAML_CONFIGFILE ]; then
|
||||||
|
echo "No configuration file $YAML_CONFIGFILE found. Please mount either at $CONFIGFILE or $YAML_CONFIGFILE"
|
||||||
|
exit 255
|
||||||
|
fi
|
||||||
|
CONFIGFILE=$YAML_CONFIGFILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=================================="
|
||||||
|
echo "== Configuration file:"
|
||||||
|
cat $CONFIGFILE
|
||||||
|
|
||||||
|
new_args=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
new_args+=("$1")
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
new_args+=("-O")
|
||||||
|
new_args+=("$CONFIGFILE")
|
||||||
|
|
||||||
|
# Load the USRP binaries
|
||||||
|
echo "=================================="
|
||||||
|
echo "== Load USRP binaries"
|
||||||
|
if [[ -v USE_B2XX ]]; then
|
||||||
|
$PREFIX/bin/uhd_images_downloader.py -t b2xx
|
||||||
|
elif [[ -v USE_X3XX ]]; then
|
||||||
|
$PREFIX/bin/uhd_images_downloader.py -t x3xx
|
||||||
|
elif [[ -v USE_N3XX ]]; then
|
||||||
|
$PREFIX/bin/uhd_images_downloader.py -t n3xx
|
||||||
|
fi
|
||||||
|
|
||||||
|
# enable printing of stack traces on assert
|
||||||
|
export OAI_GDBSTACKS=1
|
||||||
|
|
||||||
|
echo "=================================="
|
||||||
|
echo "== Starting O-RU "
|
||||||
|
if [[ -v USE_ADDITIONAL_OPTIONS ]]; then
|
||||||
|
echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}"
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
new_args+=("$1")
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
for word in ${USE_ADDITIONAL_OPTIONS}; do
|
||||||
|
new_args+=("$word")
|
||||||
|
done
|
||||||
|
echo "${new_args[@]}"
|
||||||
|
exec "${new_args[@]}"
|
||||||
|
else
|
||||||
|
echo "${new_args[@]}"
|
||||||
|
exec "${new_args[@]}"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sched.h>
|
||||||
|
#include "assertions.h"
|
||||||
|
#include "PHY/types.h"
|
||||||
|
#include "PHY/defs_RU.h"
|
||||||
|
#include "common/oai_version.h"
|
||||||
|
#include "common/config/config_userapi.h"
|
||||||
|
#include "common/utils/load_module_shlib.h"
|
||||||
|
#include "common/ran_context.h"
|
||||||
|
#include "radio/COMMON/common_lib.h"
|
||||||
|
#include "radio/ETHERNET/if_defs.h"
|
||||||
|
#include "PHY/phy_vars.h"
|
||||||
|
#include "PHY/phy_extern.h"
|
||||||
|
#include "PHY/TOOLS/phy_scope_interface.h"
|
||||||
|
#include "common/utils/LOG/log.h"
|
||||||
|
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||||
|
// #include "PHY/INIT/phy_init.h"
|
||||||
|
#include "openair2/ENB_APP/enb_paramdef.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "nfapi/oai_integration/vendor_ext.h"
|
||||||
|
#include <executables/softmodem-common.h>
|
||||||
|
#include <executables/thread-common.h>
|
||||||
|
|
||||||
|
pthread_cond_t sync_cond;
|
||||||
|
pthread_mutex_t sync_mutex;
|
||||||
|
int sync_var = -1; //!< protected by mutex \ref sync_mutex.
|
||||||
|
int config_sync_var = -1;
|
||||||
|
|
||||||
|
int oai_exit = 0;
|
||||||
|
int sf_ahead = 4;
|
||||||
|
int emulate_rf = 0;
|
||||||
|
|
||||||
|
RAN_CONTEXT_t RC;
|
||||||
|
|
||||||
|
extern void kill_NR_RU_proc(int inst);
|
||||||
|
extern void set_function_spec_param(RU_t *ru);
|
||||||
|
extern void start_NR_RU();
|
||||||
|
extern void init_NR_RU(configmodule_interface_t *cfg, char *);
|
||||||
|
|
||||||
|
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||||
|
|
||||||
|
void nfapi_setmode(nfapi_mode_t nfapi_mode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||||
|
{
|
||||||
|
if (s != NULL) {
|
||||||
|
printf("%s:%d %s() Exiting OAI softmodem: %s\n", file, line, function, s);
|
||||||
|
}
|
||||||
|
close_log_mem();
|
||||||
|
oai_exit = 1;
|
||||||
|
RU_t *ru = RC.ru[0];
|
||||||
|
|
||||||
|
if (ru->rfdevice.trx_end_func) {
|
||||||
|
ru->rfdevice.trx_end_func(&ru->rfdevice);
|
||||||
|
ru->rfdevice.trx_end_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ru->ifdevice.trx_end_func) {
|
||||||
|
ru->ifdevice.trx_end_func(&ru->ifdevice);
|
||||||
|
ru->ifdevice.trx_end_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(ru->ru_mutex);
|
||||||
|
pthread_cond_destroy(ru->ru_cond);
|
||||||
|
if (assert) {
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
sleep(1); // allow lte-softmodem threads to exit first
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_options(configmodule_interface_t *cfg)
|
||||||
|
{
|
||||||
|
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||||
|
get_common_options(cfg);
|
||||||
|
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||||
|
|
||||||
|
// NRCConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
nfapi_mode_t nfapi_getmode(void)
|
||||||
|
{
|
||||||
|
return (NFAPI_MODE_PNF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind)
|
||||||
|
{
|
||||||
|
AssertFatal(1 == 0, "This is bad ... please check why we get here\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait_eNBs(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void wait_gNBs(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timespec timespec_add(struct timespec, struct timespec)
|
||||||
|
{
|
||||||
|
struct timespec t = {0};
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
struct timespec timespec_sub(struct timespec, struct timespec)
|
||||||
|
{
|
||||||
|
struct timespec t = {0};
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
|
||||||
|
void perform_symbol_rotation(NR_DL_FRAME_PARMS *fp, double f0, c16_t *symbol_rotation)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
int beam_index_allocation(bool das,
|
||||||
|
int fapi_beam_index,
|
||||||
|
NR_gNB_COMMON *common_vars,
|
||||||
|
int slot,
|
||||||
|
int symbols_per_slot,
|
||||||
|
int bitmap_symbols)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void nr_fill_du(uint16_t N_ZC, const uint16_t *prach_root_sequence_map, uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
uint16_t nr_du[838];
|
||||||
|
|
||||||
|
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||||
|
|
||||||
|
configmodule_interface_t *uniqCfg = NULL;
|
||||||
|
THREAD_STRUCT thread_struct;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
memset(&RC, 0, sizeof(RC));
|
||||||
|
if ((uniqCfg = load_configmodule(argc, argv, 0)) == NULL) {
|
||||||
|
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
logInit();
|
||||||
|
LOG_W(PHY, "%s is experimental software and at this point is not an implementation of a 7.2 O-RAN RU\n", argv[0]);
|
||||||
|
printf("Reading in command-line options\n");
|
||||||
|
get_options(uniqCfg);
|
||||||
|
|
||||||
|
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
|
||||||
|
fprintf(stderr, "Getting configuration failed\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if T_TRACER
|
||||||
|
T_Config_Init();
|
||||||
|
#endif
|
||||||
|
printf("configuring for RRU\n");
|
||||||
|
// strdup to put the sring in the core file for post mortem identification
|
||||||
|
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
|
||||||
|
|
||||||
|
/* Read configuration */
|
||||||
|
|
||||||
|
printf("About to Init RU threads\n");
|
||||||
|
|
||||||
|
lock_memory_to_ram();
|
||||||
|
|
||||||
|
RC.nb_RU = 1;
|
||||||
|
RC.ru = malloc(sizeof(RC.ru));
|
||||||
|
|
||||||
|
init_NR_RU(config_get_if(), NULL);
|
||||||
|
|
||||||
|
RU_t *ru = RC.ru[0];
|
||||||
|
|
||||||
|
while (oai_exit == 0)
|
||||||
|
sleep(1);
|
||||||
|
// stop threads
|
||||||
|
|
||||||
|
kill_NR_RU_proc(0);
|
||||||
|
|
||||||
|
end_configmodule(uniqCfg);
|
||||||
|
|
||||||
|
if (ru->rfdevice.trx_end_func) {
|
||||||
|
ru->rfdevice.trx_end_func(&ru->rfdevice);
|
||||||
|
ru->rfdevice.trx_end_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ru->ifdevice.trx_end_func) {
|
||||||
|
ru->ifdevice.trx_end_func(&ru->ifdevice);
|
||||||
|
ru->ifdevice.trx_end_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
logClean();
|
||||||
|
printf("Bye.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+7
-2
@@ -1555,8 +1555,13 @@ void init_NR_RU(configmodule_interface_t *cfg, char *rf_config_file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PHY_VARS_gNB *gNB_RC = RC.gNB[0];
|
|
||||||
PHY_VARS_gNB *gNB0 = ru->gNB_list[0];
|
PHY_VARS_gNB *gNB_RC = NULL;
|
||||||
|
PHY_VARS_gNB *gNB0 = NULL;
|
||||||
|
if (RC.nb_nr_L1_inst > 0) {
|
||||||
|
gNB_RC = RC.gNB[0];
|
||||||
|
gNB0 = ru->gNB_list[0];
|
||||||
|
}
|
||||||
LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
|
LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
|
||||||
|
|
||||||
if (gNB0) {
|
if (gNB0) {
|
||||||
|
|||||||
@@ -33,20 +33,23 @@ void nr_phy_init_RU(RU_t *ru)
|
|||||||
|
|
||||||
LOG_D(PHY, "Initializing RU signal buffers (if_south %s) nb_tx %d, nb_rx %d\n", ru_if_types[ru->if_south], ru->nb_tx, ru->nb_rx);
|
LOG_D(PHY, "Initializing RU signal buffers (if_south %s) nb_tx %d, nb_rx %d\n", ru_if_types[ru->if_south], ru->nb_tx, ru->nb_rx);
|
||||||
|
|
||||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
ru->num_beams_period = 1;
|
||||||
ru->nb_log_antennas = 0;
|
if (ru->num_gNB > 0) {
|
||||||
for (int n = 0; n < ru->num_gNB; n++) {
|
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||||
if (cfg->carrier_config.num_tx_ant.value > ru->nb_log_antennas)
|
ru->nb_log_antennas = 0;
|
||||||
ru->nb_log_antennas = cfg->carrier_config.num_tx_ant.value;
|
for (int n = 0; n < ru->num_gNB; n++) {
|
||||||
|
if (cfg->carrier_config.num_tx_ant.value > ru->nb_log_antennas)
|
||||||
|
ru->nb_log_antennas = cfg->carrier_config.num_tx_ant.value;
|
||||||
|
}
|
||||||
|
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
||||||
|
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
||||||
}
|
}
|
||||||
|
else ru->nb_log_antennas = ru->nb_tx;
|
||||||
|
|
||||||
// copy configuration from gNB[0] in to RU, assume that all gNB instances sharing RU use the same configuration
|
// copy configuration from gNB[0] in to RU, assume that all gNB instances sharing RU use the same configuration
|
||||||
// (at least the parts that are needed by the RU, numerology and PRACH)
|
// (at least the parts that are needed by the RU, numerology and PRACH)
|
||||||
|
|
||||||
AssertFatal(ru->nb_log_antennas > 0 && ru->nb_log_antennas < 13, "ru->nb_log_antennas %d ! \n",ru->nb_log_antennas);
|
AssertFatal(ru->nb_log_antennas > 0 && ru->nb_log_antennas < 13, "ru->nb_log_antennas %d ! \n",ru->nb_log_antennas);
|
||||||
|
|
||||||
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
|
||||||
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
|
||||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||||
LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, ru->num_beams_period);
|
LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, ru->num_beams_period);
|
||||||
|
|||||||
+48
-17
@@ -184,7 +184,8 @@ void print_fh_init(const struct xran_fh_init *fh_init)
|
|||||||
fh_init->filePrefix,
|
fh_init->filePrefix,
|
||||||
fh_init->mtu,
|
fh_init->mtu,
|
||||||
fh_init->p_o_du_addr);
|
fh_init->p_o_du_addr);
|
||||||
print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr);
|
if (fh_init->p_o_ru_addr) print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr);
|
||||||
|
else if (fh_init->p_o_du_addr) print_ether_addr(" p_o_du_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_du_addr);
|
||||||
printf("\
|
printf("\
|
||||||
totalBfWeights %d\n",
|
totalBfWeights %d\n",
|
||||||
fh_init->totalBfWeights);
|
fh_init->totalBfWeights);
|
||||||
@@ -460,14 +461,14 @@ char bbdev_dev[32] = "";
|
|||||||
char bbdev_vfio_vf_token[64] = "";
|
char bbdev_vfio_vf_token[64] = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_rus)
|
static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump, const int num_rus, const int is_du)
|
||||||
{
|
{
|
||||||
DevAssert(fhip != NULL);
|
DevAssert(fhip != NULL);
|
||||||
int num_dev = gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->numelt;
|
int num_dev = gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->numelt;
|
||||||
AssertFatal(num_dev > 0, "need to provide DPDK devices for O-RAN 7.2 Fronthaul\n");
|
AssertFatal(num_dev > 0, "need to provide DPDK devices for O-RAN 7.2 Fronthaul\n");
|
||||||
AssertFatal(num_dev < 17, "too many DPDK devices for O-RAN 7.2 Fronthaul\n");
|
AssertFatal(num_dev < 17, "too many DPDK devices for O-RAN 7.2 Fronthaul\n");
|
||||||
|
|
||||||
io_cfg->id = 0; // 0 -> xran as O-DU; 1 -> xran as O-RU
|
io_cfg->id = 1 - is_du; // 0 -> xran as O-DU; 1 -> xran as O-RU
|
||||||
io_cfg->num_vfs = num_dev; // number of VFs for C-plane and U-plane (should be even); max = XRAN_VF_MAX
|
io_cfg->num_vfs = num_dev; // number of VFs for C-plane and U-plane (should be even); max = XRAN_VF_MAX
|
||||||
io_cfg->num_rxq = 1; // number of RX queues per VF
|
io_cfg->num_rxq = 1; // number of RX queues per VF
|
||||||
for (int i = 0; i < num_dev; ++i) {
|
for (int i = 0; i < num_dev; ++i) {
|
||||||
@@ -540,7 +541,7 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
|||||||
/* if RU does support, io_cfg->eowd_cmn[0] should only be filled as id = O_DU; io_cfg->eowd_cmn[1] only used if id = O_RU */
|
/* if RU does support, io_cfg->eowd_cmn[0] should only be filled as id = O_DU; io_cfg->eowd_cmn[1] only used if id = O_RU */
|
||||||
const uint16_t owdm_enable = *gpd(fhip, nump, ORAN_CONFIG_ECPRI_OWDM)->uptr;
|
const uint16_t owdm_enable = *gpd(fhip, nump, ORAN_CONFIG_ECPRI_OWDM)->uptr;
|
||||||
if (owdm_enable) {
|
if (owdm_enable) {
|
||||||
io_cfg->eowd_cmn[0].initiator_en = 1; // 1 -> initiator (always O-DU), 0 -> recipient (always O-RU)
|
io_cfg->eowd_cmn[0].initiator_en = is_du ? 1 : 0; // 1 -> initiator (always O-DU), 0 -> recipient (always O-RU)
|
||||||
io_cfg->eowd_cmn[0].numberOfSamples = 8; // total number of samples to be collected and averaged per port
|
io_cfg->eowd_cmn[0].numberOfSamples = 8; // total number of samples to be collected and averaged per port
|
||||||
io_cfg->eowd_cmn[0].filterType = 0; // 0 -> simple average based on number of measurements; not used in xran in both E and F releases
|
io_cfg->eowd_cmn[0].filterType = 0; // 0 -> simple average based on number of measurements; not used in xran in both E and F releases
|
||||||
io_cfg->eowd_cmn[0].responseTo = 10000000; // response timeout in [ns]
|
io_cfg->eowd_cmn[0].responseTo = 10000000; // response timeout in [ns]
|
||||||
@@ -678,6 +679,19 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
|||||||
const int nfh = sizeofArray(FHconfigs);
|
const int nfh = sizeofArray(FHconfigs);
|
||||||
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
|
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
|
||||||
|
|
||||||
|
int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs
|
||||||
|
int is_du = 0;
|
||||||
|
|
||||||
|
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
|
||||||
|
int num_du_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt;
|
||||||
|
if (num_ru_addr > 0 && num_du_addr == 0)
|
||||||
|
is_du = 1;
|
||||||
|
else if (num_du_addr > 0 && num_ru_addr == 0)
|
||||||
|
is_du = 0;
|
||||||
|
else
|
||||||
|
AssertFatal(false, "Illegal node configuration, num_du_addr %d, num_ru_addr %d\n", num_du_addr, num_ru_addr);
|
||||||
|
fh_init->xran_ports = is_du == 1 ? num_rus : num_du_addr;
|
||||||
|
|
||||||
#ifdef OAI_MPLANE
|
#ifdef OAI_MPLANE
|
||||||
ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api;
|
ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api;
|
||||||
int num_rus = ru_session_list->num_rus;
|
int num_rus = ru_session_list->num_rus;
|
||||||
@@ -704,9 +718,8 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs
|
|
||||||
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, is_du))
|
||||||
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
|
|
||||||
return false;
|
return false;
|
||||||
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
|
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
|
||||||
return false;
|
return false;
|
||||||
@@ -714,16 +727,35 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
|||||||
communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame);
|
communicated in a single xRAN network layer transaction. Supported 1500 bytes and 9600 bytes (Jumbo Frame);
|
||||||
xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */
|
xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */
|
||||||
fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr;
|
fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr;
|
||||||
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
|
|
||||||
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
|
fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
|
||||||
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
|
|
||||||
char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
|
char **ru_addrs,**du_addrs;
|
||||||
for (int i = 0; i < num_ru_addr; ++i) {
|
|
||||||
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
|
if (is_du > 0) {
|
||||||
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
|
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
|
||||||
printf("could not read ethernet address '%s' for RU!\n", ru_addrs[i]);
|
ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
|
||||||
return false;
|
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
|
||||||
|
for (int i = 0; i < num_ru_addr; ++i) {
|
||||||
|
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
|
||||||
|
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
|
||||||
|
printf("could not read ethernet address '%s' for RU!\n", ru_addrs[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
fh_init->p_o_du_addr = NULL;
|
||||||
|
} else {
|
||||||
|
fh_init->p_o_du_addr = calloc(num_du_addr, sizeof(struct rte_ether_addr));
|
||||||
|
du_addrs = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr;
|
||||||
|
AssertFatal(fh_init->p_o_du_addr != NULL, "out of memory\n");
|
||||||
|
for (int i = 0; i < num_du_addr; ++i) {
|
||||||
|
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_du_addr;
|
||||||
|
if (get_ether_addr(du_addrs[i], &ea[i]) == NULL) {
|
||||||
|
printf("could not read ethernet address '%s' for DU!\n", du_addrs[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fh_init->p_o_ru_addr = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -732,7 +764,6 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
|
|||||||
/* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes;
|
/* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes;
|
||||||
it is necessary */
|
it is necessary */
|
||||||
fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
|
fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr);
|
||||||
fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
|
|
||||||
fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec
|
fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec
|
||||||
|
|
||||||
#ifdef F_RELEASE
|
#ifdef F_RELEASE
|
||||||
|
|||||||
Reference in New Issue
Block a user