From 3e3d87226802db439e3114b1849b2b03c97f55aa Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 May 2025 17:53:51 +0200 Subject: [PATCH 1/9] Avoid use of xran_get_slot_idx_from_tti() and use public API xran_get_slot_idx_from_tti() has been introduced to access data information from xran. However, it makes no sense, as the used macros to calculate frame, slot, subframe, are already in the public API. Hence, use these macros directly. It would be possible to remove xran_get_slot_idx_from_tti(), but doing so we would need to update the patch ID, causing trouble to users. --- radio/fhi_72/oaioran.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 7ac4998e40..755a07dee1 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -67,12 +67,6 @@ volatile oran_sync_info_t oran_sync_info = {0}; void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) { struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag; - uint64_t second; - uint32_t tti; - uint32_t frame; - uint32_t subframe; - uint32_t slot, slot2; - uint32_t rx_sym; static int32_t last_slot = -1; static int32_t last_frame = -1; @@ -87,21 +81,17 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) const int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; static int rx_RU[XRAN_PORTS_NUM][160] = {0}; - uint32_t rx_tti = callback_tag->slotiId; + uint32_t tti = callback_tag->slotiId; + uint32_t slotnum = SLOTNUM_PER_SUBFRAME(xran_ctx->interval_us_local); + uint32_t frame = XranGetFrameNum(tti, 0, SUBFRAMES_PER_SYSTEMFRAME, slotnum); + uint32_t subframe = XranGetSubFrameNum(tti, slotnum, SUBFRAMES_PER_SYSTEMFRAME); + uint32_t slot = XranGetSlotNum(tti, slotnum); - tti = xran_get_slot_idx_from_tti(rx_tti, &frame, &subframe, &slot, &second); - - rx_sym = callback_tag->symbol & 0xFF; + uint32_t rx_sym = callback_tag->symbol & 0xFF; uint32_t ru_id = callback_tag->oXuId; - LOG_D(HW, - "rx_callback frame %d, subframe %d, slot %d, second %lld, rx_sym %d ru_id %d\n", - frame, - subframe, - slot, - (unsigned long long)second, - rx_sym, - ru_id); + LOG_D(HW, "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)) #ifdef F_RELEASE for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { @@ -127,7 +117,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) // would see periodic output with only "0" in stats counters if (!first_call_set) return; - slot2 = slot + (subframe * slots_per_subframe); + uint32_t slot2 = slot + (subframe * slots_per_subframe); 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)))) From 8dcdee85f70f06349944def311cd6f2a2346c2d6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:21:17 +0200 Subject: [PATCH 2/9] Use buffers as set up by driver The buffers are set up by the OAI xran driver, so instead of peaking into xran internal data, access the buffers through the driver directly. The buffers get set up through the following xran calls In xran_5g_fronthault_config(): - src => sFrontHaulTxBbuIoBufCtrl - srccp => sFrontHaulTxPrbMapBbuIoBufCtrl - dst => sFrontHaulRxBbuIoBufCtrl - dstcp => sFrontHaulRxPrbMapBbuIoBufCtrl In xran_5g_prach_req() - prach(dst) => sFHPrachRxBbuIoBufCtrl - prach(dst)decomp => sFHPrachRxBbuIoBufCtrlDecomp Note that in all cases: - the xran buffer array is [XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR] (of [internal] type BbuIoBufCtrlStruct, but we give an sBufferList) - the driver buffer array is [XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN] Hence, we switch the order of indexing, leave out the sector, and omit the sBufferList member. --- radio/fhi_72/oaioran.c | 28 ++++++++++++---------------- radio/fhi_72/oran-init.c | 5 +++++ radio/fhi_72/oran-init.h | 2 ++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 755a07dee1..8be878f8ca 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -97,9 +97,10 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { struct xran_device_ctx *xran_ctx_per_ru = xran_dev_get_ctx_by_id(ru_idx); struct xran_fh_config *fh_config = &xran_ctx_per_ru->fh_cfg; + oran_buf_list_t *bufs = get_xran_buffers(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 *)xran_ctx_per_ru->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers->pData; + 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++) { @@ -188,12 +189,9 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; - xran_ctx = xran_dev_get_ctx_by_id(aa / nb_rx_per_ru); + oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); dst = ru->prach_buf[aa]; // + (sym_idx*576)); - src = (int16_t *)((uint8_t *)xran_ctx->sFHPrachRxBbuIoBufCtrlDecomp[tti % XRAN_N_FE_BUF_LEN][0][aa % nb_rx_per_ru] - .sBufferList.pBuffers[sym_idx] - .pData); - + src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (sym_idx == 0) { @@ -351,8 +349,8 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) continue; uint8_t *pData; - uint8_t *pPrbMapData = xran_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_rx_per_ru] - .sBufferList.pBuffers->pData; + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); + uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; @@ -364,8 +362,8 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) uint32_t one_rb_size = (((pRbElm->iqWidth == 0) || (pRbElm->iqWidth == 16)) ? (N_SC_PER_PRB * 2 * 2) : (3 * pRbElm->iqWidth + 1)); if (fh_init->mtu < pRbElm->nRBSize * one_rb_size) - pData = xran_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_rx_per_ru] - .sBufferList.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] + 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_sec_desc->pData; @@ -491,14 +489,12 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) { - xran_ctx = xran_dev_get_ctx_by_id(ant_id / nb_tx_per_ru); + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - uint8_t *pData = xran_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_tx_per_ru] - .sBufferList.pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT] - .pData; - uint8_t *pPrbMapData = xran_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id % nb_tx_per_ru] - .sBufferList.pBuffers->pData; + uint8_t *pData = + bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; ptr = pData; pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize]; diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 38e766805a..410df0166a 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -464,3 +464,8 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi return (void *)gxran_handle; } + +oran_buf_list_t *get_xran_buffers(uint32_t port_id) +{ + return gPortInst[port_id][0].buf_list; +} diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index b9f31d9889..e12fa90858 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -59,4 +59,6 @@ extern void *gxran_handle; int *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); + #endif /* ORAN_INIT_H */ From 42b5df351d0fefbb591bd421cd52398c6c5bb693 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 9 Jul 2025 14:49:03 +0200 Subject: [PATCH 3/9] Split out PRACH-specific functions into separate header Split out type and function definitions for a cleaner separation for some consumers of these functions. Concretely, nr_mac_common.h includes various ASN.1 NR RRC headers, but not all consumers of these APIs might need these headers. For instance, the next commit will use these functions in the driver for 7.2 (it needs to compute PRACH length), but the driver itself does not depend on nor does it need the ASN.1 NR RRC headers. Defining a new header avoids the problem. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 21 +----- .../LAYER2/NR_MAC_COMMON/nr_prach_config.h | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 84284f0c48..3770d2c6ec 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -35,6 +35,7 @@ #include "NR_CellGroupConfig.h" #include "NR_UE-NR-Capability.h" #include "nr_mac.h" +#include "nr_prach_config.h" #include "common/utils/nr/nr_common.h" #define NB_SRS_PERIOD (18) @@ -52,20 +53,6 @@ typedef enum { pusch_len2 = 2 } pusch_maxLength_t; -typedef struct { - uint32_t format; - uint32_t start_symbol; - uint32_t N_t_slot; - uint32_t N_dur; - uint32_t N_RA_slot; - uint32_t N_RA_sfn; - uint32_t max_association_period; - int x; - int y; - int y2; - uint64_t s_map; -} nr_prach_info_t; - typedef struct { uint16_t bwpStart; uint16_t bwpSize; @@ -161,8 +148,6 @@ void find_aggregation_candidates(uint8_t *aggregation_level, const NR_SearchSpace_t *ss, int maxL); -uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired); - bool get_nr_prach_sched_from_info(nr_prach_info_t info, int config_index, int frame, @@ -172,8 +157,6 @@ bool get_nr_prach_sched_from_info(nr_prach_info_t info, uint16_t *RA_sfn_index, uint8_t unpaired); -nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired); - uint8_t get_pusch_mcs_table(long *mcs_Table, int is_tp, int dci_format, @@ -190,8 +173,6 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type); -int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range); - uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); int compute_pucch_crc_size(int O_uci); uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h b/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h new file mode 100644 index 0000000000..1b6aa0bfb7 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h @@ -0,0 +1,75 @@ +/* + * 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 + */ + +/*! \file openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h +* \brief Tools to query the PRACH configuration tables +* \author Romain beurdouche +* \date Jul. 2025 +* \version 0.1 +* \company Eurecom +* \email romain.beurdouche@eurecom.fr +* \note The PRACH configuration tables are used in the MAC layer for scheduling and beyond. +* For example the PRACH duration is requested in the O-RAN 7.2 FrontHaul Interface +*/ + +/** + * @brief Fetch PRACH format (format only) from PRACH configuration tables + * + * @param index PRACH configuration index + * @param unpaired Duplex mode TDD or FDD + * @param freq_range Frequency range FR1 or FR2 + * @return PRACH format (format only) + */ +int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range); + +typedef struct { + uint32_t format; + uint32_t start_symbol; + uint32_t N_t_slot; + uint32_t N_dur; + uint32_t N_RA_slot; + uint32_t N_RA_sfn; + uint32_t max_association_period; + int x; + int y; + int y2; + uint64_t s_map; +} nr_prach_info_t; + +/** + * @brief Fetch PRACH occasion info from PRACH configuration tables + * + * @param index PRACH configuration index + * @param freq_range Frequency range FR1 or FR2 + * @param unpaired Duplex mode TDD or FDD + * @return PRACH occasion information + */ +nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired); + +/** + * @brief Fetch PRACH format (format concatenated with format2) from PRACH configuration tables + * + * @param index PRACH configuration index + * @param pointa Point A ARFCN to determine the Frequency range FR1 or FR2 + * @param unpaired Duplex mode TDD or FDD + * @return PRACH format (format concatenated with format2) + */ +uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired); From cc076eb54704968bd20859a8627ea195ef09b378 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Jul 2025 14:54:52 +0200 Subject: [PATCH 4/9] Use locally available data instead of peaking into xran internals Look up xran_fh_init/xran_fh_config through driver instead of peaking into xran internals. Note that xran writes values back into these structs during initialization, and hence it is important to store them _after initialization_. Some remarks regarding less obvious changes: - slotnum is replaced by slots_in_sf: SLOTNUM_PER_SUBFRAME uses the time duration of a slot (=interval_us_local) to calculate the numbers of slots in a subframe, which can be done with a simple shift instead - The prach duration should be queried from the PRACH configuration table. The function to query the occasion info is part of the MAC layer code while this information can be used outside of this layer. Use header `nr_prach_config.h` to not duplicate functionality. Co-authored-by: Romain Beurdouche --- radio/fhi_72/oaioran.c | 59 ++++++++++++++++++++-------------------- radio/fhi_72/oran-init.c | 41 ++++++++++++++++++++++++++++ radio/fhi_72/oran-init.h | 3 ++ 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 8be878f8ca..ee213f4301 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -43,6 +43,8 @@ #include "common/utils/threadPool/notified_fifo.h" +#define N_SC_PER_PRB 12 + #if OAI_FHI72_USE_POLLING #define USE_POLLING #endif @@ -71,21 +73,19 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) static int32_t last_slot = -1; static int32_t last_frame = -1; - /* xran context contains the same xran_fh_init struct info, - but xran_fh_config struct info is RU specific only */ - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; + const struct xran_fh_init *fh_init = get_xran_fh_init(); int num_ports = fh_init->xran_ports; /* assuming all RUs have the same numerology */ - const int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; + const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + const int slots_in_sf = 1 << fh_cfg->frame_conf.nNumerology; + const int sf_in_frame = 10; static int rx_RU[XRAN_PORTS_NUM][160] = {0}; uint32_t tti = callback_tag->slotiId; - uint32_t slotnum = SLOTNUM_PER_SUBFRAME(xran_ctx->interval_us_local); - uint32_t frame = XranGetFrameNum(tti, 0, SUBFRAMES_PER_SYSTEMFRAME, slotnum); - uint32_t subframe = XranGetSubFrameNum(tti, slotnum, SUBFRAMES_PER_SYSTEMFRAME); - uint32_t slot = XranGetSlotNum(tti, slotnum); + 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; @@ -95,8 +95,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) #ifdef F_RELEASE for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { - struct xran_device_ctx *xran_ctx_per_ru = xran_dev_get_ctx_by_id(ru_idx); - struct xran_fh_config *fh_config = &xran_ctx_per_ru->fh_cfg; + struct xran_fh_config *fh_config = get_xran_fh_config(ru_idx); oran_buf_list_t *bufs = get_xran_buffers(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++) { @@ -118,7 +117,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) // would see periodic output with only "0" in stats counters if (!first_call_set) return; - uint32_t slot2 = slot + (subframe * slots_per_subframe); + 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)))) @@ -172,20 +171,21 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) /* calculate tti and subframe_id from frame, slot num */ int sym_idx = 0; - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - struct xran_prach_cp_config *pPrachCPConfig = &(xran_ctx->PrachCPConfig); - struct xran_ru_config *ru_conf = &(xran_ctx->fh_cfg.ru_conf); - int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology; - int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; + struct xran_fh_init *fh_init = get_xran_fh_init(); + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int prach_sym = get_prach_conf_duration(0); + struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; + int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; + int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; int tti = slots_per_frame * (frame) + (slot); uint32_t subframe = slot / slots_per_subframe; uint32_t is_prach_slot = xran_is_prach_slot(0, subframe, (slot % slots_per_subframe)); - int nb_rx_per_ru = ru->nb_rx / xran_ctx->fh_init.xran_ports; + 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 (is_prach_slot) { - for (sym_idx = 0; sym_idx < pPrachCPConfig->numSymbol; sym_idx++) { + for (sym_idx = 0; sym_idx < prach_sym; sym_idx++) { for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; @@ -316,16 +316,16 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) #endif // return(0); - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology; + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; int tti = slots_per_frame * (*frame) + (*slot); read_prach_data(ru, *frame, *slot); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; - int nPRBs = xran_ctx->fh_cfg.nULRBs; - int fftsize = 1 << xran_ctx->fh_cfg.ru_conf.fftSize; + const struct xran_fh_init *fh_init = get_xran_fh_init(); + int nPRBs = fh_cfg->nULRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; int slot_offset_rxdata = 3 & (*slot); uint32_t slot_size = 4 * 14 * fftsize; @@ -336,8 +336,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { rx_data = (uint8_t *)ru->rxdataF[ant_id]; start_ptr = rx_data + (slot_size * slot_offset_rxdata); - xran_ctx = xran_dev_get_ctx_by_id(ant_id / nb_rx_per_ru); - const struct xran_frame_config *frame_conf = &xran_ctx->fh_cfg.frame_conf; + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; // skip processing this slot is TX (no RX in this slot) if (is_tdd_dl_guard_slot(frame_conf, *slot)) continue; @@ -481,10 +480,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int32_t *pos = NULL; int idx = 0; - struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); - const struct xran_fh_init *fh_init = &xran_ctx->fh_init; - int nPRBs = xran_ctx->fh_cfg.nDLRBs; - int fftsize = 1 << xran_ctx->fh_cfg.ru_conf.fftSize; + const struct xran_fh_init *fh_init = get_xran_fh_init(); + const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int nPRBs = fh_cfg->nDLRBs; + int fftsize = 1 << fh_cfg->ru_conf.fftSize; int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 410df0166a..07517dcf18 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -30,7 +30,9 @@ #include "common/utils/assertions.h" #include "common/utils/LOG/log.h" +#include "common/utils/nr/nr_common.h" #include "common_lib.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h" /* PRACH data samples are 32 bits wide (16bits for I/Q). Each packet contains * 840 samples for long sequence or 144 for short sequence. The payload length @@ -46,6 +48,10 @@ static oran_port_instance_t gPortInst[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; void *gxran_handle; +static struct xran_fh_init g_fh_init = {0}; +static struct xran_fh_config g_fh_config[XRAN_PORTS_NUM] = {0}; +static uint32_t g_prach_conf_duration[XRAN_PORTS_NUM] = {0}; + static uint32_t get_nSW_ToFpga_FTH_TxBufferLen(int mu, int sections) { uint32_t xran_max_sections_per_slot = RTE_MAX(sections, XRAN_MIN_SECTIONS_PER_SLOT); @@ -460,12 +466,47 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi printf("xran_reg_physide_cb failed %d\n", xret); exit(-1); } + + // retrieve and store prach duration + uint8_t idx = xran_fh_config[o_xu_id].prach_conf.nPrachConfIdx; + const struct xran_frame_config *fc = &xran_fh_config[o_xu_id].frame_conf; + g_prach_conf_duration[o_xu_id] = + get_nr_prach_occasion_info_from_index(idx, + fc->nNumerology > 2 ? FR2 : FR1, + fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD) + .N_dur; } + // store config after xran initialization -- xran makes modifications to + // these structs during initialization + 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; } oran_buf_list_t *get_xran_buffers(uint32_t port_id) { + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); return gPortInst[port_id][0].buf_list; } + +struct xran_fh_init *get_xran_fh_init(void) +{ + return &g_fh_init; +} + +struct xran_fh_config *get_xran_fh_config(uint32_t port_id) +{ + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); + return &g_fh_config[port_id]; +} + +uint32_t get_prach_conf_duration(uint32_t port_id) +{ + struct xran_fh_init *fh_init = get_xran_fh_init(); + DevAssert(port_id < fh_init->xran_ports); + return g_prach_conf_duration[port_id]; +} diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index e12fa90858..e56b683a9f 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -60,5 +60,8 @@ extern void *gxran_handle; int *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); +struct xran_fh_config *get_xran_fh_config(uint32_t port_id); +uint32_t get_prach_conf_duration(uint32_t port_id); #endif /* ORAN_INIT_H */ From b7a6b1b7d68c0be6067ebc57e7201181154eb436 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:19:19 +0200 Subject: [PATCH 5/9] Do not include xran internal data: not needed --- cmake_targets/tools/MODULES/Findxran.cmake | 5 +---- radio/fhi_72/oaioran.c | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake_targets/tools/MODULES/Findxran.cmake b/cmake_targets/tools/MODULES/Findxran.cmake index 1ade3ac522..369f04753f 100644 --- a/cmake_targets/tools/MODULES/Findxran.cmake +++ b/cmake_targets/tools/MODULES/Findxran.cmake @@ -126,12 +126,9 @@ find_package_handle_standard_args(xran VERSION_VAR xran_VERSION ) -# in proper usage of cmake, include directory should only contain "api", but not header files under "src" directory; -# however, we use xran_dev_get_ctx() and xran_dev_get_ctx_by_id() functions which are defined in xran_common.h; -# since xran_common.h is under "src" directory, we have to include it in ${xran_INCLUDE_DIRS} if(xran_FOUND) set(xran_LIBRARIES ${xran_LIBRARY}) - set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR} ${xran_INCLUDE_DIR}/../src) + set(xran_INCLUDE_DIRS ${xran_INCLUDE_DIR}) endif() if(xran_FOUND AND NOT TARGET xran::xran) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index ee213f4301..fc9f58a492 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -35,7 +35,6 @@ #include "xran_sync_api.h" #include "oran_isolate.h" #include "oran-init.h" -#include "xran_common.h" #include "oaioran.h" #include From 02bc14d8c176b77698220b77d6a84eb74311c7b8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 09:18:34 +0200 Subject: [PATCH 6/9] get xran stats Get xran stats in the trx_oran_get_stats function and use trx_oran_get_stats upon stopping and ending RF. Co-authored-by: Romain Beurdouche --- executables/main_ru.c | 16 ++++++++++++++++ executables/nr-ru.c | 3 +++ executables/nr-softmodem.c | 14 ++++++++++++++ executables/nr-uesoftmodem.c | 8 +++++++- radio/fhi_72/oran_isolate.c | 5 +++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/executables/main_ru.c b/executables/main_ru.c index 86a26f9ac3..3579c26f7a 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -97,11 +97,19 @@ void exit_function(const char *file, const char *function, const int line, const oai_exit = 1; if (ru_m.rfdevice.trx_end_func) { + if (ru_m.rfdevice.trx_get_stats_func) { + ru_m.rfdevice.trx_get_stats_func(&ru_m.rfdevice); + ru_m.rfdevice.trx_get_stats_func = NULL; + } ru_m.rfdevice.trx_end_func(&ru_m.rfdevice); ru_m.rfdevice.trx_end_func = NULL; } if (ru_m.ifdevice.trx_end_func) { + if (ru_m.ifdevice.trx_get_stats_func) { + ru_m.ifdevice.trx_get_stats_func(&ru_m.ifdevice); + ru_m.ifdevice.trx_get_stats_func = NULL; + } ru_m.ifdevice.trx_end_func(&ru_m.ifdevice); ru_m.ifdevice.trx_end_func = NULL; } @@ -363,11 +371,19 @@ int main ( int argc, char **argv ) end_configmodule(uniqCfg); if (ru->rfdevice.trx_end_func) { + if (ru->rfdevice.trx_get_stats_func) { + ru->rfdevice.trx_get_stats_func(&ru->rfdevice); + ru->rfdevice.trx_get_stats_func = NULL; + } ru->rfdevice.trx_end_func(&ru->rfdevice); ru->rfdevice.trx_end_func = NULL; } if (ru->ifdevice.trx_end_func) { + if (ru->ifdevice.trx_get_stats_func) { + ru->ifdevice.trx_get_stats_func(&ru->ifdevice); + ru->ifdevice.trx_get_stats_func = NULL; + } ru->ifdevice.trx_end_func(&ru->ifdevice); ru->ifdevice.trx_end_func = NULL; } diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 411caf9a63..8f29ce4749 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1371,6 +1371,9 @@ int start_rf(RU_t *ru) { } int stop_rf(RU_t *ru) { + if (ru->rfdevice.trx_get_stats_func) { + ru->rfdevice.trx_get_stats_func(&ru->rfdevice); + } ru->rfdevice.trx_end_func(&ru->rfdevice); return 0; } diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 332e06e7af..602606039a 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -207,11 +207,19 @@ void exit_function(const char *file, const char *function, const int line, const for (ru_id=0; ru_idrfdevice.trx_end_func) { + if (RC.ru[ru_id]->rfdevice.trx_get_stats_func) { + RC.ru[ru_id]->rfdevice.trx_get_stats_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_get_stats_func = NULL; + } RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); RC.ru[ru_id]->rfdevice.trx_end_func = NULL; } if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + if (RC.ru[ru_id]->ifdevice.trx_get_stats_func) { + RC.ru[ru_id]->ifdevice.trx_get_stats_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_get_stats_func = NULL; + } RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); RC.ru[ru_id]->ifdevice.trx_end_func = NULL; } @@ -423,11 +431,17 @@ int stop_L1(module_id_t gnb_id) 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); + } if (ru->rfdevice.trx_stop_func) { ru->rfdevice.trx_stop_func(&ru->rfdevice); LOG_I(GNB_APP, "turned off RU rfdevice\n"); } + if (ru->ifdevice.trx_get_stats_func) { + ru->ifdevice.trx_get_stats_func(&ru->rfdevice); + } if (ru->ifdevice.trx_stop_func) { ru->ifdevice.trx_stop_func(&ru->ifdevice); LOG_I(GNB_APP, "turned off RU ifdevice\n"); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index f1e94e9e55..fad251b060 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -170,8 +170,12 @@ void exit_function(const char *file, const char *function, const int line, const if (PHY_vars_UE_g && PHY_vars_UE_g[0]) { for(CC_id=0; CC_idrfdevice.trx_end_func) + if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) { + if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func) { + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } } } @@ -591,6 +595,8 @@ int main(int argc, char **argv) ret = pthread_join(phy_vars->stat_thread, NULL); AssertFatal(ret == 0, "pthread_join error %d, errno %d (%s)\n", ret, errno, strerror(errno)); } + if (phy_vars->rfdevice.trx_get_stats_func) + phy_vars->rfdevice.trx_get_stats_func(&phy_vars->rfdevice); if (phy_vars->rfdevice.trx_end_func) phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice); } diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 7ceec513c6..4a141275d7 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -103,6 +103,11 @@ int trx_oran_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) int trx_oran_get_stats(openair0_device *device) { + uint64_t total_time, used_time; + uint32_t num_core_used, core_used[64]; + uint32_t ret = xran_get_time_stats(&total_time, &used_time, &num_core_used, &core_used[0], 0); + if (ret == 0) + LOG_I(HW, "xran_get_time_stats(): total thread time %ld, total time essential tasks %ld, num cores used %d\n", total_time, used_time, num_core_used); printf("ORAN: %s\n", __FUNCTION__); return (0); } From d3283c4819e885a6165e5b893b62dad358c362dc Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 25 Jun 2025 13:45:07 +0000 Subject: [PATCH 7/9] feat(oran_fhlib_5g): F release works with DPDK21+ Modify xran F release patch to make it compile and run with DPDK 21+ (tested with DPDK 22.11) --- .../F/oaioran_F.patch | 315 +++++++++++++++++- 1 file changed, 307 insertions(+), 8 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index b8d09cf862..8157172d85 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -259,7 +259,7 @@ index 46e0e1d..409ef4b 100644 int xran_prepare_iq_symbol_portion( struct rte_mbuf *mbuf, diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c -index f5b2fd6..144a65e 100644 +index f5b2fd6..2eccc6e 100644 --- a/fhi_lib/lib/ethernet/ethdi.c +++ b/fhi_lib/lib/ethernet/ethdi.c @@ -37,7 +37,10 @@ @@ -273,7 +273,33 @@ index f5b2fd6..144a65e 100644 #include #include #include -@@ -325,8 +328,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -185,14 +188,24 @@ static void check_port_link_status(uint8_t portid) + printf("Port %d Link Up - speed %u " + "Mbps - %s\n", (uint8_t)portid, + (unsigned)link.link_speed, ++#if (RTE_VER_YEAR >= 21) ++ (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ? ++ ("full-duplex") : ("half-duplex\n") ++#else + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? +- ("full-duplex") : ("half-duplex\n")); ++ ("full-duplex") : ("half-duplex\n") ++#endif ++ ); + else + printf("Port %d Link Down\n", + (uint8_t)portid); + } + /* clear all_ports_up flag if any link down */ ++#if (RTE_VER_YEAR >= 21) ++ if (link.link_status == RTE_ETH_LINK_DOWN) { ++#else + if (link.link_status == ETH_LINK_DOWN) { ++#endif + all_ports_up = 0; + break; + } +@@ -325,8 +338,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, char bbdev_wdev[32] = ""; char bbdev_vdev[32] = ""; char iova_mode[32] = "--iova-mode=pa"; @@ -284,7 +310,7 @@ index f5b2fd6..144a65e 100644 char ring_name[32] = ""; int32_t xran_port = -1; queueid_t qi = 0; -@@ -336,7 +339,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -336,7 +349,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, cpu = sched_getcpu(); node = numa_node_of_cpu(cpu); @@ -293,7 +319,7 @@ index f5b2fd6..144a65e 100644 "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; if (io_cfg == NULL) -@@ -481,11 +484,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -481,11 +494,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring"); @@ -307,7 +333,7 @@ index f5b2fd6..144a65e 100644 } } } else { -@@ -555,7 +560,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -555,7 +570,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING, rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0); PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring"); @@ -317,7 +343,7 @@ index f5b2fd6..144a65e 100644 return 1; diff --git a/fhi_lib/lib/ethernet/ethernet.c b/fhi_lib/lib/ethernet/ethernet.c -index edda598..791256c 100644 +index edda598..77e5ca7 100644 --- a/fhi_lib/lib/ethernet/ethernet.c +++ b/fhi_lib/lib/ethernet/ethernet.c @@ -37,7 +37,10 @@ @@ -331,6 +357,78 @@ index edda598..791256c 100644 #include #include #include +@@ -149,13 +152,22 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + static uint16_t nb_txd = BURST_SIZE; + struct rte_ether_addr addr; + struct rte_eth_rxmode rxmode = { ++#if (RTE_VER_YEAR >= 21) ++ .mtu = MAX_RX_LEN, ++#else + .split_hdr_size = 0, + .max_rx_pkt_len = MAX_RX_LEN, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME ++#endif + }; + struct rte_eth_txmode txmode = { ++#if (RTE_VER_YEAR >= 21) ++ .mq_mode = RTE_ETH_MQ_TX_NONE, ++ .offloads = RTE_ETH_TX_OFFLOAD_MULTI_SEGS ++#else + .mq_mode = ETH_MQ_TX_NONE, + .offloads = DEV_TX_OFFLOAD_MULTI_SEGS ++#endif + }; + struct rte_eth_conf port_conf = { + .rxmode = rxmode, +@@ -174,8 +186,13 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + uint32_t num_mbufs = 0; + + if (mtu <= 1500) { ++#if (RTE_VER_YEAR >= 21) ++ rxmode.offloads &= ~RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO; ++ rxmode.mtu = RTE_ETHER_MAX_LEN; ++#else + rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME; + rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN; ++#endif + data_room_size = MBUF_POOL_ELM_SMALL; + } + +@@ -184,10 +201,19 @@ void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu) + drv_name = dev_info.driver_name; + printf("initializing port %d for TX, drv=%s\n", p_id, drv_name); + +- if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE){ ++#if (RTE_VER_YEAR >= 21) ++ if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) ++#else ++ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) ++#endif ++ { + printf("set DEV_TX_OFFLOAD_MBUF_FAST_FREE\n"); + port_conf.txmode.offloads |= ++#if (RTE_VER_YEAR >= 21) ++ RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; ++#else + DEV_TX_OFFLOAD_MBUF_FAST_FREE; ++#endif + } + + rte_eth_macaddr_get(p_id, &addr); +@@ -293,8 +319,13 @@ void xran_add_eth_hdr_vlan(struct rte_ether_addr *dst, uint16_t ethertype, struc + PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed"); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb->port, &h->src_addr); /* set source addr */ ++ h->dst_addr = *dst; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb->port, &h->s_addr); /* set source addr */ + h->d_addr = *dst; /* set dst addr */ ++#endif + h->ether_type = rte_cpu_to_be_16(ethertype); /* ethertype too */ + #if 0 + struct rte_ether_addr *s = &h->s_addr; diff --git a/fhi_lib/lib/src/xran_bfp_ref.cpp b/fhi_lib/lib/src/xran_bfp_ref.cpp index e6d3067..8e0abee 100644 --- a/fhi_lib/lib/src/xran_bfp_ref.cpp @@ -565,7 +663,7 @@ index 789c6fd..a768efb 100644 #include #include diff --git a/fhi_lib/lib/src/xran_delay_measurement.c b/fhi_lib/lib/src/xran_delay_measurement.c -index 4c943c8..d9e7983 100644 +index 4c943c8..7db51a8 100644 --- a/fhi_lib/lib/src/xran_delay_measurement.c +++ b/fhi_lib/lib/src/xran_delay_measurement.c @@ -23,7 +23,10 @@ @@ -579,6 +677,155 @@ index 4c943c8..d9e7983 100644 #include #include #include +@@ -572,16 +575,28 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed"); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(port_id, &h->src_addr); /* set source addr */ ++#else + rte_eth_macaddr_get(port_id, &h->s_addr); /* set source addr */ ++#endif + + if (p_xran_dev_ctx->fh_init.io_cfg.id) + { + // rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_du_addr[port_id],&h->d_addr); ++#if (RTE_VER_YEAR >= 21) ++ h->dst_addr = ctx->entities[port_id][ID_O_DU]; /* set dst addr */ ++#else + h->d_addr = ctx->entities[port_id][ID_O_DU]; /* set dst addr */ ++#endif + } + else + { ++#if (RTE_VER_YEAR >= 21) ++ h->dst_addr = ctx->entities[port_id][ID_O_RU]; /* set dst addr */ ++#else + h->d_addr = ctx->entities[port_id][ID_O_RU]; /* set dst addr */ ++#endif + // rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_ru_addr[port_id],&h->d_addr); + } + +@@ -752,7 +767,11 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + int8_t *pa = &p_xran_dev_ctx->fh_init.p_o_du_addr[0]; + printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pa[0],pa[1],pa[2],pa[3],pa[4],pa[5]); + #endif ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_du_addr[0], (struct rte_ether_addr *)&h->dst_addr.addr_bytes[0]); ++#else + rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_du_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]); ++#endif + + } + else +@@ -761,13 +780,25 @@ int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, + int8_t *pb = &p_xran_dev_ctx->fh_init.p_o_ru_addr[0]; + printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pb[0],pb[1],pb[2],pb[3],pb[4],pb[5]); + #endif ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_ru_addr[0], (struct rte_ether_addr *)&h->dst_addr.addr_bytes[0]); ++#else + rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_ru_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]); ++#endif + + } + #ifdef XRAN_OWD_DEBUG_PKTS ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pc = &h->src_addr.addr_bytes[0]; ++#else + uint8_t *pc = &h->s_addr.addr_bytes[0]; ++#endif + printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pd = &h->dst_addr.addr_bytes[0]; ++#else + uint8_t *pd = &h->d_addr.addr_bytes[0]; ++#endif + printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]); + #endif + // Copy dest address from above +@@ -862,9 +893,15 @@ int xran_process_delmeas_request(struct rte_mbuf *pkt, void* handle, struct xran + // 11) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // Still need to check ol_flags state and update if necessary + // Compute the delay td12 and save + // Still need to define the DB to save the info and run averages +@@ -872,9 +909,17 @@ int xran_process_delmeas_request(struct rte_mbuf *pkt, void* handle, struct xran + // 12) Send the response right away + #ifdef XRAN_OWD_DEBUG_PKTS + struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr*); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pc = &h->src_addr.addr_bytes[0]; ++#else + uint8_t *pc = &h->s_addr.addr_bytes[0]; ++#endif + printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]); ++#if (RTE_VER_YEAR >= 21) ++ uint8_t *pd = &h->dst_addr.addr_bytes[0]; ++#else + uint8_t *pd = &h->d_addr.addr_bytes[0]; ++#endif + printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]); + // printf("EtherType: %04"PRIx16" \n",&h->ether_type); + #endif +@@ -1100,9 +1145,15 @@ int xran_process_delmeas_rem_request(struct rte_mbuf *pkt, void* handle, struct + // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // 10) Send the response right away + pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) ); + pdm->cmnhdr.bits.ecpri_payl_size = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent +@@ -1177,9 +1228,15 @@ int xran_process_delmeas_rem_request_w_fup(struct rte_mbuf* pkt, void* handle, s + // 7) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + // 8) Duplicate packet to be used for the follow up packet + pkt2 = rte_pktmbuf_copy(pkt1, _eth_mbuf_pool, 0, UINT32_MAX); + // 9) Record the current timestamp when the request with follow up is being sent +@@ -1283,9 +1340,15 @@ int xran_process_delmeas_follow_up(struct rte_mbuf *pkt, void* handle, struct xr + // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame + eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *); + /* Swap dest and src mac addresses. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_ether_addr_copy(ð_hdr->dst_addr, &addr); ++ rte_ether_addr_copy(ð_hdr->src_addr, ð_hdr->dst_addr); ++ rte_ether_addr_copy(&addr, ð_hdr->src_addr); ++#else + rte_ether_addr_copy(ð_hdr->d_addr, &addr); + rte_ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); + rte_ether_addr_copy(&addr, ð_hdr->s_addr); ++#endif + pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) ); + pdm->cmnhdr.bits.ecpri_payl_size = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent + pdm->cmnhdr.bits.ecpri_payl_size = rte_cpu_to_be_16(pdm->cmnhdr.bits.ecpri_payl_size); diff --git a/fhi_lib/lib/src/xran_dev.c b/fhi_lib/lib/src/xran_dev.c index 4acade1..c939edc 100644 --- a/fhi_lib/lib/src/xran_dev.c @@ -1377,7 +1624,7 @@ index 72249bc..6b30084 100644 #include diff --git a/fhi_lib/lib/src/xran_tx_proc.c b/fhi_lib/lib/src/xran_tx_proc.c -index 45a17a8..28c5568 100644 +index 45a17a8..85ce6fa 100644 --- a/fhi_lib/lib/src/xran_tx_proc.c +++ b/fhi_lib/lib/src/xran_tx_proc.c @@ -35,7 +35,11 @@ @@ -1392,6 +1639,58 @@ index 45a17a8..28c5568 100644 #include #include +@@ -1514,7 +1518,11 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 + mb_oran_hdr_ext->buf_addr = ext_buff; + mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); + mb_oran_hdr_ext->buf_len = ext_buff_len; ++#if (RTE_VER_YEAR >= 21) ++ mb_oran_hdr_ext->ol_flags |= RTE_MBUF_F_EXTERNAL; ++#else + mb_oran_hdr_ext->ol_flags |= EXT_ATTACHED_MBUF; ++#endif + mb_oran_hdr_ext->shinfo = p_share_data; + mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; + mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); +@@ -1532,8 +1540,13 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 + + /* Fill in the ethernet header. */ + #ifndef TRANSMIT_BURST ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->src_addr); /* set source addr */ ++ ((struct rte_ether_hdr*)pStart)->dst_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->s_addr); /* set source addr */ + ((struct rte_ether_hdr*)pStart)->d_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#endif + ((struct rte_ether_hdr*)pStart)->ether_type = ETHER_TYPE_ECPRI_BE; /* ethertype */ + #endif + nPktSize = sizeof(struct rte_ether_hdr) +@@ -1878,7 +1891,11 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s + mb_oran_hdr_ext->buf_addr = ext_buff; + mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); + mb_oran_hdr_ext->buf_len = ext_buff_len; ++#if (RTE_VER_YEAR >= 21) ++ mb_oran_hdr_ext->ol_flags |= RTE_MBUF_F_EXTERNAL; ++#else + mb_oran_hdr_ext->ol_flags |= EXT_ATTACHED_MBUF; ++#endif + mb_oran_hdr_ext->shinfo = p_share_data; + mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; + mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); +@@ -1887,8 +1904,13 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s + pStart = (char*)((char*)mb_oran_hdr_ext->buf_addr + mb_oran_hdr_ext->data_off); + + /* Fill in the ethernet header. */ ++#if (RTE_VER_YEAR >= 21) ++ rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->src_addr); /* set source addr */ ++ ((struct rte_ether_hdr*)pStart)->dst_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#else + rte_eth_macaddr_get(mb_oran_hdr_ext->port, &((struct rte_ether_hdr*)pStart)->s_addr); /* set source addr */ + ((struct rte_ether_hdr*)pStart)->d_addr = eth_ctx->entities[vf_id][ID_O_RU]; /* set dst addr */ ++#endif + ((struct rte_ether_hdr*)pStart)->ether_type = ETHER_TYPE_ECPRI_BE; /* ethertype */ + + nPktSize = sizeof(struct rte_ether_hdr) diff --git a/fhi_lib/lib/src/xran_up_api.c b/fhi_lib/lib/src/xran_up_api.c index fe22a1f..3fd369b 100644 --- a/fhi_lib/lib/src/xran_up_api.c From 486726233de97a1ee5de53bb9bd6da1802d9b1ee Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 27 Jun 2025 16:18:27 +0000 Subject: [PATCH 8/9] feat(oran_fhlib_5g): Enable to include a BBDEV device while initializing EAL In order to be usable in parallel of FHI 7.2, BBDEV devices should be included in the EAL initialization that is prformed by xran. This commit adds a way of adding the BBDEV device from OAI. Also fixes an issue with pkgconfig in xran. --- .../F/oaioran_F.patch | 66 +++++++++++++++---- radio/fhi_72/CMakeLists.txt | 2 +- radio/fhi_72/oran-config.c | 41 ++++++++++++ 3 files changed, 95 insertions(+), 14 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index 8157172d85..bec423b95e 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..9ebbcab 100644 +index ac5f471..5efcce3 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,12 +7,12 @@ index ac5f471..9ebbcab 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.3" ++#define VERSIONX "oran_f_release_v1.4" #define APP_O_DU 0 #define APP_O_RU 1 diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile -index eccc4ae..b1b8f4b 100644 +index eccc4ae..a97fdc6 100644 --- a/fhi_lib/lib/Makefile +++ b/fhi_lib/lib/Makefile @@ -23,24 +23,46 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -83,9 +83,9 @@ index eccc4ae..b1b8f4b 100644 RTE_TARGET ?= x86_64-native-linux-icc -RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) +ifeq ($(TARGET), x86) -+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkg-config --cflags-only-I libdpdk) +else ifeq ($(TARGET), armv8) -+RTE_INC := $(pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell pkg-config --cflags-only-I libdpdk) +endif API_DIR := $(PROJECT_DIR)/api @@ -147,6 +147,15 @@ index eccc4ae..b1b8f4b 100644 ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc) CPP_FLAGS += -fp-model fast=2 -no-prec-div -no-prec-sqrt -fast-transcendentals -restrict +@@ -150,7 +187,7 @@ CPP_FLAGS += -fp-model fast -march=icelake-server -mintrinsic-promote -Wno-unus + endif + + +-INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) ++INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) $(RTE_INC) + DEF := + ifeq ($(MLOG),1) + INC += -I$(MLOG_DIR)/source @@ -186,8 +223,13 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC)) AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS)) @@ -164,7 +173,7 @@ index eccc4ae..b1b8f4b 100644 CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h -index bacf597..8bd7c66 100644 +index bacf597..1dd6d66 100644 --- a/fhi_lib/lib/api/xran_fh_o_du.h +++ b/fhi_lib/lib/api/xran_fh_o_du.h @@ -141,7 +141,7 @@ extern "C" { @@ -176,7 +185,15 @@ index bacf597..8bd7c66 100644 #define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ #define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ -@@ -1193,6 +1193,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, +@@ -419,6 +419,7 @@ struct xran_io_cfg { + uint16_t num_rxq; /**< number of RX queues per VF */ + char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */ + char *bbdev_dev[1]; /**< BBDev dev name */ ++ char *bbdev_vfio_vf_token[1]; /**< BBDev dev token */ + int32_t bbdev_mode; /**< DPDK for BBDev */ + uint32_t dpdkIoVaMode; /**< IOVA Mode */ + uint32_t dpdkMemorySize; /**< DPDK max memory allocation */ +@@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, */ int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); @@ -259,7 +276,7 @@ index 46e0e1d..409ef4b 100644 int xran_prepare_iq_symbol_portion( struct rte_mbuf *mbuf, diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c -index f5b2fd6..2eccc6e 100644 +index f5b2fd6..8fb0ec2 100644 --- a/fhi_lib/lib/ethernet/ethdi.c +++ b/fhi_lib/lib/ethernet/ethdi.c @@ -37,7 +37,10 @@ @@ -299,8 +316,11 @@ index f5b2fd6..2eccc6e 100644 all_ports_up = 0; break; } -@@ -325,8 +338,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -323,10 +336,11 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + uint64_t nWorkerCore = 1; + uint32_t coreNum = sysconf(_SC_NPROCESSORS_CONF); char bbdev_wdev[32] = ""; ++ char bbdev_vfio_vf_token[64] = ""; char bbdev_vdev[32] = ""; char iova_mode[32] = "--iova-mode=pa"; - char socket_mem[32] = "--socket-mem=8192"; @@ -310,16 +330,36 @@ index f5b2fd6..2eccc6e 100644 char ring_name[32] = ""; int32_t xran_port = -1; queueid_t qi = 0; -@@ -336,7 +349,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -336,8 +350,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, cpu = sched_getcpu(); node = numa_node_of_cpu(cpu); - char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", +- "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; + char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", "--no-telemetry", - "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev}; ++ "--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev, bbdev_vfio_vf_token}; if (io_cfg == NULL) -@@ -481,11 +494,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + return 0; +@@ -347,11 +361,17 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, + // hw-accelerated bbdev + printf("hw-accelerated bbdev %s\n", io_cfg->bbdev_dev[0]); + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "-a%s", io_cfg->bbdev_dev[0]); ++ if (io_cfg->bbdev_vfio_vf_token[0] != NULL) { ++ snprintf(bbdev_vfio_vf_token, RTE_DIM(bbdev_vfio_vf_token), "--vfio-vf-token=%s", io_cfg->bbdev_vfio_vf_token[0]); ++ } + } else if (io_cfg->bbdev_mode == XRAN_BBDEV_MODE_HW_OFF){ + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "%s", "--vdev=baseband_turbo_sw"); + } else if (io_cfg->bbdev_mode == XRAN_BBDEV_MODE_HW_SW){ + printf("software and hw-accelerated bbdev %s\n", io_cfg->bbdev_dev[0]); + snprintf(bbdev_wdev, RTE_DIM(bbdev_wdev), "-a%s", io_cfg->bbdev_dev[0]); ++ if (io_cfg->bbdev_vfio_vf_token[0] != NULL) { ++ snprintf(bbdev_vfio_vf_token, RTE_DIM(bbdev_vfio_vf_token), "--vfio-vf-token=%s", io_cfg->bbdev_vfio_vf_token[0]); ++ } + snprintf(bbdev_vdev, RTE_DIM(bbdev_vdev), "%s", "--vdev=baseband_turbo_sw"); + } else { + rte_panic("Cannot init DPDK incorrect [bbdev_mode %d]\n", io_cfg->bbdev_mode); +@@ -481,11 +501,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX, rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring"); @@ -333,7 +373,7 @@ index f5b2fd6..2eccc6e 100644 } } } else { -@@ -555,7 +570,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, +@@ -555,7 +577,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg, ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING, rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0); PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring"); diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index a874d4cc01..a49f38adee 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(oran_fhlib_5g MODULE ) set(E_VERSION 5.1.5) -set(F_VERSION 6.1.3) +set(F_VERSION 6.1.4) find_package(xran REQUIRED) if(xran_VERSION VERSION_EQUAL E_VERSION) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 891634dbfc..ed8f37f857 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -461,6 +461,11 @@ static uint64_t get_u64_mask(const paramdef_t *pd) return mask; } +#ifdef 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) { DevAssert(fhip != NULL); @@ -474,8 +479,44 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in for (int i = 0; i < num_dev; ++i) { io_cfg->dpdk_dev[i] = strdup(gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->strlistptr[i]); // VFs devices } +#ifdef F_RELEASE + io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 + io_cfg->bbdev_vfio_vf_token[0] = 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, "_t2", 3) == 0) { + uint32_t eal_init_bbdev = 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[] = { + {"eal_init_bbdev", NULL, 0, .uptr = &eal_init_bbdev, .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_t2"); + + if (eal_init_bbdev != 0) { + AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_t2.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); + io_cfg->bbdev_vfio_vf_token[0] = &bbdev_vfio_vf_token[0]; // BBDev dev token; max devices = 1 + } else { + io_cfg->bbdev_vfio_vf_token[0] = 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 + } +#elif defined(E_RELEASE) io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev +#endif int dpdk_iova_mode_idx = config_paramidx_fromname((paramdef_t *)fhip, nump, ORAN_CONFIG_DPDK_IOVA_MODE); AssertFatal(dpdk_iova_mode_idx >= 0,"Index for dpdk_iova_mode config option not found!"); io_cfg->dpdkIoVaMode = config_get_processedint(config_get_if(), (paramdef_t *)&fhip[dpdk_iova_mode_idx]); // IOVA mode From 8e33727c370bd7cd01561ffbb8d6b408e9495899 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 30 Jun 2025 14:01:08 +0000 Subject: [PATCH 9/9] feat(oran_fhlib_5g): pkgconfig fix for E release E release had the same issue of not using pkgconfig properly as F release. This issue was fixed in F release when enabling its compatibility with DPDK 21+. This commit brings this fix to E release. --- .../E/oaioran_E.patch | 17 ++++++++++------- radio/fhi_72/CMakeLists.txt | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch b/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch index baa5378673..8d0610892a 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index 7508117..ce17ebd 100644 +index 7508117..318508b 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,12 +7,12 @@ index 7508117..ce17ebd 100644 #include -#define VERSIONX "oran_e_maintenance_release_v1.0" -+#define VERSIONX "oran_e_maintenance_release_v1.5" ++#define VERSIONX "oran_e_maintenance_release_v1.6" #define APP_O_DU 0 #define APP_O_RU 1 diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile -index de141bf..fa2923f 100644 +index de141bf..c2a448d 100644 --- a/fhi_lib/lib/Makefile +++ b/fhi_lib/lib/Makefile @@ -23,12 +23,25 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -50,9 +50,9 @@ index de141bf..fa2923f 100644 -RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) +ifeq ($(TARGET), x86) -+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkg-config --cflags-only-I libdpdk) +else ifeq ($(TARGET), armv8) -+RTE_INC := $(pkgconf --cflags-only-I libdpdk) ++RTE_INC := $(shell pkg-config --cflags-only-I libdpdk) +endif API_DIR := $(PROJECT_DIR)/api SRC_DIR := $(PROJECT_DIR)/src @@ -85,7 +85,7 @@ index de141bf..fa2923f 100644 CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ -fdata-sections \ -@@ -112,12 +132,21 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ +@@ -112,14 +132,23 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ -fPIC \ -Wall \ -Wimplicit-function-declaration \ @@ -110,8 +110,11 @@ index de141bf..fa2923f 100644 + -Werror -Wno-unused-variable -std=c++14 +endif - INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) +-INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) -I$(RTE_INC) ++INC := -I$(API_DIR) -I$(ETH_DIR) -I$(SRC_DIR) $(RTE_INC) DEF := + ifeq ($(MLOG),1) + INC += -I$(MLOG_DIR)/source @@ -150,8 +179,13 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC)) AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS)) diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index a49f38adee..3b0f16d2a4 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(oran_fhlib_5g MODULE oran-init.c ) -set(E_VERSION 5.1.5) +set(E_VERSION 5.1.6) set(F_VERSION 6.1.4) find_package(xran REQUIRED)