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:
Jaroslava Fiedlerova
2026-01-27 20:30:12 +01:00
10 changed files with 478 additions and 30 deletions

View File

@@ -1789,6 +1789,24 @@ target_link_libraries(lte-uesoftmodem PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIE
target_link_libraries(lte-uesoftmodem PRIVATE
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
###################################################

View File

@@ -324,6 +324,7 @@ class Containerize():
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(('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)
if result is not None:
self.dockerfileprefix = '.ubuntu.cross-arm64'
@@ -412,7 +413,7 @@ class Containerize():
# target images should use the proper ran-build image
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}')
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}')
elif image != 'ran-build':
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')

View File

@@ -82,6 +82,8 @@ Options:
Makes the NR softmodem
--RU
Makes the OAI RRU
--nrRU
Makes the NR RRU
--UE
Makes the UE specific parts (usim, nvram) from the given configuration file
--nrUE
@@ -227,6 +229,11 @@ function main() {
TARGET_LIST="$TARGET_LIST oairu"
echo_info "Will compile RRU"
shift;;
--nrRU)
NRRU=1
TARGET_LIST="$TARGET_LIST nr-oru"
echo_info "Will compile NR O-RU"
shift;;
--UE)
UE=1
TARGET_LIST="$TARGET_LIST lte-uesoftmodem conf2uedata usim nvram"
@@ -452,7 +459,7 @@ function main() {
if [[ $TARGET_LIST != "" ]] && [[ -f $OPENAIR_DIR/CMakeLists.txt ]]; then
# add some default libraries that should always be built
# for eNB, gNB, UEs, simulators
if [[ $gNB == 1 || $eNB == 1 || $UE == 1 || $nrUE == 1 || $SIMUS_PHY == 1 || $RU == 1 ]]; then
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"
fi

View File

@@ -68,7 +68,7 @@ RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai \
--ninja --gNB \
--ninja --gNB --nrRU \
--build-lib "telnetsrv enbscope uescope nrscope" \
-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 \

View File

@@ -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"]

View File

@@ -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

220
executables/main_nr_ru.c Normal file
View File

@@ -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;
}

View File

@@ -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);
if (gNB0) {

View File

@@ -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);
nfapi_nr_config_request_scf_t *cfg = &ru->config;
ru->nb_log_antennas = 0;
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;
ru->num_beams_period = 1;
if (ru->num_gNB > 0) {
nfapi_nr_config_request_scf_t *cfg = &ru->config;
ru->nb_log_antennas = 0;
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
// (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);
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_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);

View File

@@ -184,7 +184,8 @@ void print_fh_init(const struct xran_fh_init *fh_init)
fh_init->filePrefix,
fh_init->mtu,
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("\
totalBfWeights %d\n",
fh_init->totalBfWeights);
@@ -460,14 +461,14 @@ 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)
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);
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 < 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_rxq = 1; // number of RX queues per VF
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 */
const uint16_t owdm_enable = *gpd(fhip, nump, ORAN_CONFIG_ECPRI_OWDM)->uptr;
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].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]
@@ -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);
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
ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api;
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
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))
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus, is_du))
return false;
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
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);
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;
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));
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
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; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function
char **ru_addrs,**du_addrs;
if (is_du > 0) {
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
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
@@ -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;
it is necessary */
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
#ifdef F_RELEASE