Remove support for xran F release

This commit is contained in:
Teodora Vladić
2026-06-02 15:07:23 +02:00
parent 26efcc4989
commit cf7990b55a
11 changed files with 37 additions and 2587 deletions

View File

@@ -73,11 +73,9 @@ Supported libxran releases:
| Vendor |
|-----------------------------------------|
| `oran_f_release_v1.0` |
| `oran_k_release_v1.0` |
**Note**: The libxran driver of OAI identifies the above F release version as
"6.1.0" (F is the sixth letter, then 1.0), and the above K release as "11.1.0".
**Note**: The libxran driver of OAI identifies the above K release as "11.1.0".
### Configure your server
@@ -307,7 +305,7 @@ timedatectl set-ntp false
### DPDK (Data Plane Development Kit)
Download DPDK version 20.11.9 (F release) or 24.11.4 (K release).
Download DPDK version 24.11.4 (K release).
```bash
# on debian
@@ -315,14 +313,12 @@ sudo apt install wget xz-utils libnuma-dev libibverbs-dev rdma-core python3-pyel
# on Fedora/RHEL
sudo dnf install wget xz numactl-devel rdma-core-devel libibverbs-devel python3-pyelftools meson
cd
wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz # F release
wget http://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz # K release
```
#### DPDK Compilation and Installation
```bash
tar xvf dpdk-20.11.9.tar.xz && cd dpdk-stable-20.11.9 # F release
tar xvf dpdk-24.11.4.tar.xz && cd dpdk-stable-24.11.4 # K release
meson build
@@ -390,7 +386,6 @@ pkg-config --libs libdpdk --static
Go back to the version folder you used to build and install
```
cd ~/dpdk-stable-20.11.9 # F release
cd ~/dpdk-stable-24.11.4 # K release
sudo ninja deinstall -C build
```
@@ -406,17 +401,6 @@ cd ~/openairinterface5g/
### Build ORAN Fronthaul Interface Library
Download ORAN FHI DU library, checkout the correct version, and apply the correct patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches`).
#### F release
```bash
git clone https://github.com/openairinterface/o-du-phy.git ~/phy
cd ~/phy
git checkout oran_f_release_v1.0
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch
```
#### K release
```bash
git clone https://github.com/openairinterface/o-du-phy.git ~/phy
@@ -435,7 +419,6 @@ target, set as well the environment variable `TARGET=armv8`.
```bash
cd ~/phy/fhi_lib/lib
make clean
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # F release
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-24.11.4/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # K release
...
[AR] build/libxran.so
@@ -522,7 +505,7 @@ Note that you might also call cmake directly instead of using `build_oai`:
```
cd ~/openairinterface5g
mkdir build && cd build
# build RAN after manually building xran F or K release
# build RAN after manually building xran K release
cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
# build RAN and xran K release automatically
cmake .. -GNinja -DOAI_FHI72=ON -Dxran_DOWNLOAD=ON

View File

@@ -18,7 +18,6 @@ add_library(oran_fhlib_5g MODULE
oran-init.c
)
set(F_VERSION 6.1.9)
set(K_VERSION 11.1.1)
add_boolean_option(xran_DOWNLOAD OFF "Download and build xran library" OFF)
@@ -26,9 +25,9 @@ add_boolean_option(xran_DOWNLOAD OFF "Download and build xran library" OFF)
find_package(xran)
if(xran_FOUND)
if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6)
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION} or K version ${K_VERSION}")
elseif(xran_VERSION VERSION_EQUAL F_VERSION)
target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE)
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to K version ${K_VERSION}")
elseif(xran_VERSION VERSION_GREATER_EQUAL 6 AND xran_VERSION VERSION_LESS 7)
message(FATAL_ERROR "xran F release not supported starting from tag 2026.w25.\nPlease switch to K version ${K_VERSION}")
elseif(xran_VERSION VERSION_EQUAL K_VERSION)
if(dpdk_VERSION VERSION_LESS 22)
message(FATAL_ERROR "DPDK version miniminum 22 required for K release, but found ${dpdk_VERSION}")

View File

@@ -10,9 +10,9 @@ add_dependencies(oran_fhlib_5g_mplane oran_fhlib_5g)
if(xran_FOUND)
if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6)
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION} or K version ${K_VERSION}")
elseif(xran_VERSION VERSION_EQUAL F_VERSION)
target_compile_definitions(oran_fhlib_5g_mplane PRIVATE F_RELEASE)
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to K version ${K_VERSION}")
elseif(xran_VERSION VERSION_GREATER_EQUAL 6 AND xran_VERSION VERSION_LESS 7)
message(FATAL_ERROR "xran F release not supported starting from tag 2026.w25.\nPlease switch to K version ${K_VERSION}")
elseif(xran_VERSION VERSION_EQUAL K_VERSION)
target_compile_definitions(oran_fhlib_5g_mplane PRIVATE K_RELEASE)
endif()

View File

@@ -32,20 +32,14 @@
// Declare variable useful for the send buffer function
volatile bool first_call_set = false;
int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id
#if defined K_RELEASE
, uint8_t mu
#endif
);
int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id, uint8_t mu);
#include "common/utils/LOG/log.h"
extern notifiedFIFO_t oran_sync_fifo;
#define MAX_QUEUE_LENGTH_NO_JUMP 3
atomic_int xran_queue_length = 0;
atomic_int xran_queue_prach_length = 0;
#if defined K_RELEASE
extern notifiedFIFO_t oran_sync_fifo_prach;
#endif
/* Prints TX_TOTAL, RX_TOTAL, RX_ON_TIME, RX_ERR_DROP counters every 128 frames. */
void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
@@ -56,11 +50,7 @@ void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
const struct xran_fh_init *fh_init = get_xran_fh_init();
for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
#if defined F_RELEASE
if ((frame & 0x7f) == 0 && slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) {
#elif defined K_RELEASE
if ((frame & 0x7f) == 0 && slot == 0 && xran_get_common_counters(gxran_handle[o_xu_id], &x_counters[o_xu_id]) == XRAN_STATUS_SUCCESS) {
#endif
LOG_I(HW,
"[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n",
"o-du ",
@@ -81,7 +71,6 @@ void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
x_counters[o_xu_id].rx_pusch_packets[rxant],
rxant,
x_counters[o_xu_id].rx_prach_packets[rxant]);
#if defined K_RELEASE
LOG_I(HW,
"[%s%d][drop errors %7d ecpri errors %7d cp errors %7d up errors %7d pusch errors %7d prach errors %7d]\n",
"o_du",
@@ -92,7 +81,6 @@ void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
x_counters[o_xu_id].rx_err_up,
x_counters[o_xu_id].rx_err_pusch,
x_counters[o_xu_id].rx_err_prach);
#endif
if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id])
old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter;
if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id])
@@ -105,11 +93,7 @@ void print_fhi_counters(ru_info_t *ru, const int frame, const int slot)
* 1/4, 1/2, 3/4, all symbols of a slot arrived. Currently, only used to get
* timing information and unblock another thread in xran_fh_rx_read_slot()
* through a message queue on a full slot boundary. */
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
)
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status, uint8_t mu)
{
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
@@ -119,13 +103,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
const struct xran_fh_init *fh_init = get_xran_fh_init();
int num_ports = fh_init->xran_ports;
#if defined K_RELEASE
const int slots_in_sf = 1 << mu;
#elif defined F_RELEASE
/* assuming all RUs have the same numerology */
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
const int slots_in_sf = 1 << fh_cfg->frame_conf.nNumerology;
#endif
const int sf_in_frame = 10;
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
@@ -140,26 +118,6 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
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))
#if defined F_RELEASE
for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) {
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++) {
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++) {
LOG_D(HW, "cb pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) {
struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm];
pRbElm->nSecDesc[sym_id] = 0; // number of section descriptors per symbol; M-plane info <supported-section-types>
}
}
}
}
}
#endif
// if xran did not call xran_physide_dl_tti callback, it's not ready yet.
// wait till first callback to advance counters, because otherwise users
// would see periodic output with only "0" in stats counters
@@ -183,7 +141,6 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
info->tti = tti;
info->sl = slot2;
info->f = frame;
#if defined K_RELEASE
info->mu = mu;
for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) {
@@ -200,7 +157,6 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
}
}
}
#endif
LOG_D(HW, "Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot);
atomic_fetch_add(&xran_queue_length, 1);
pushNotifiedFIFO(&oran_sync_fifo, req);
@@ -211,13 +167,8 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
} // rx_sym == 7
}
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
)
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status, uint8_t mu)
{
#if defined K_RELEASE
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
static int32_t last_slot = -1;
@@ -291,18 +242,11 @@ void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
last_slot = slot2;
// last_frame = frame;
} // rx_sym == 7
#elif defined F_RELEASE
rte_pause();
#endif
}
/** @details Only used to unblock timing in oai_xran_fh_rx_callback()/oai_xran_fh_rx_prach_callback()
* on first call. */
int oai_physide_dl_tti_call_back(void *param
#if defined K_RELEASE
, uint8_t mu
#endif
)
int oai_physide_dl_tti_call_back(void *param, uint8_t mu)
{
if (!first_call_set)
LOG_I(HW, "first_call set from phy cb\n");
@@ -315,11 +259,9 @@ int oai_physide_dl_tti_call_back(void *param
* before writing.
*
* Function is blocking and waits for next frame/slot combination. It is unblocked
* by oai_xran_fh_rx_prach_callback(). If K_RELEASE, it writes the current slot into parameters
* frame/slot. If F_RELEASE, it takes the frame/slot. */
* by oai_xran_fh_rx_prach_callback(). It writes the current slot into parameters frame/slot. */
int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int *slot)
{
#if defined K_RELEASE
// pull next even from oran_sync_fifo_prach if any
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo_prach);
atomic_fetch_sub(&xran_queue_prach_length, 1);
@@ -345,27 +287,18 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
*slot = info->sl;
*frame = info->f;
uint8_t mu = info->mu;
#endif
prach_item_t p;
fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index};
if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
#if defined F_RELEASE
uint8_t mu = fh_cfg->frame_conf.nNumerology;
#elif defined K_RELEASE
uint8_t mu = fh_cfg->nNumerology[0];
#endif
int slots_per_subframe = 1 << mu;
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)
#if defined K_RELEASE
, mu
#endif
); // `p.slot` = slot in which PRACH is scheduled
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe), mu); // `p.slot` = slot in which PRACH is scheduled
if (is_prach_slot) {
ru->prach_buf = p.prach_buf;
ru->nb_prach_rx = p.nb_rx;
@@ -374,9 +307,7 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot);
}
} else {
#if defined K_RELEASE
delNotifiedFIFO_elt(res);
#endif
return (0);
}
@@ -401,11 +332,7 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
int prach_end_sym = prach_info.N_dur + prach_start_sym;
struct xran_ru_config *ru_conf = &fh_cfg->ru_conf;
#if defined K_RELEASE
int slots_per_frame = 10 << mu;
#elif defined F_RELEASE
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
#endif
int tti = slots_per_frame * (*frame) + (*slot);
@@ -419,7 +346,6 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru);
// hardcoded to use only first prach occasion
dst = (int16_t *)ru->prach_buf[aa - ru->start_prach_rx][0];
#if defined K_RELEASE
struct xran_prb_map * pPrbMap = (struct xran_prb_map *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pPrbMap->sFrontHaulRxPacketCtrl[sym_idx];
int32_t nRxPkt = info->nRxPkt[cc_id][aa][sym_idx];
@@ -440,9 +366,6 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
}
}
num_prbu = p_rx_packet_ctl->nRBSize[0];
#elif defined F_RELEASE
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
#endif
/* convert Network order to host order */
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
if (sym_idx == prach_start_sym) {
@@ -494,9 +417,7 @@ int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int
// constant pace, but prach_l1rx_queue emptied as fast as possible,
// see rx_func()
DevAssert(success);
#if defined K_RELEASE
delNotifiedFIFO_elt(res);
#endif
return (0);
}
@@ -590,26 +511,16 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
*slot = info->sl;
*frame = info->f;
#if defined K_RELEASE
uint8_t mu = info->mu;
#endif
// return(0);
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
#if defined K_RELEASE
int slots_per_frame = 10 << mu;
#elif defined F_RELEASE
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
#endif
int tti = slots_per_frame * (*frame) + (*slot);
const struct xran_fh_init *fh_init = get_xran_fh_init();
#if defined K_RELEASE
int fftsize = 1 << fh_cfg->perMu[mu].nULFftSize;
#elif defined F_RELEASE
int fftsize = 1 << fh_cfg->nULFftSize;
#endif
int slot_offset_rxdata = 3 & (*slot);
uint32_t slot_size = 4 * 14 * fftsize;
@@ -643,7 +554,6 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
int start_totalRB = pRbMap->prbMap[0].nRBStart;
int32_t local_dst[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64)));
#if defined K_RELEASE
struct xran_prb_elm *pRbElm = &pRbMap->prbMap[0];
struct xran_rx_packet_ctl *p_rx_packet_ctl = &pRbMap->sFrontHaulRxPacketCtrl[sym_idx];
uint32_t one_rb_size =
@@ -664,28 +574,6 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
LOG_D(HW, "p_rx_packet_ctl[%d] startRB[%d]:numRB[%d]\n", pkt_idx, startRB, numRB);
{
{
#elif defined F_RELEASE
LOG_D(HW, "[%d.%d] pRbMap->nPrbElm %d\n", *frame, *slot, pRbMap->nPrbElm);
for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
int numRB, startRB;
uint8_t *pData;
struct xran_section_desc *p_sec_desc = NULL;
struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm];
// UP_nRBSize & UP_nRBStart are for DL U-plane only
LOG_D(HW, "[%d.%d] idxElm[%d] startSym[%d]:numSym[%d] UP_startRB[%d]:UP_numRB[%d] sym_idx[%d] ant_id[%d] pRbElm->nRBStart[%d]:pRbElm->nRBSize[%d]\n", *frame, *slot, idxElm, pRbElm->nStartSymb, pRbElm->numSymb, pRbElm->UP_nRBStart, pRbElm->UP_nRBSize, sym_idx, ant_id, pRbElm->nRBStart, pRbElm->nRBSize);
for (int idxDesc = 0; idxDesc < XRAN_MAX_FRAGMENT; idxDesc++) {
p_sec_desc = &pRbElm->sec_desc[sym_idx][idxDesc];
if (p_sec_desc == NULL)
continue;
if (sym_idx >= pRbElm->nStartSymb && sym_idx < pRbElm->nStartSymb + pRbElm->numSymb) {
if (!p_sec_desc->pCtrl)
continue;
pData = p_sec_desc->pData;
numRB = p_sec_desc->num_prbu;
startRB = p_sec_desc->start_prbu;
// num_prbu & start_prbu are for UL U-plane only
LOG_D(HW, "p_sec_desc[%d] startRB[%d]:numRB[%d]\n", idxDesc, startRB, numRB);
#endif
ptr = pData;
pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize));
if (ptr == NULL || pos == NULL)
@@ -744,9 +632,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
} // sym_ind
} // ant_ind
} // vv_inf
#if defined K_RELEASE
delNotifiedFIFO_elt(res);
#endif
return (0);
}
@@ -764,12 +650,8 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
const struct xran_fh_init *fh_init = get_xran_fh_init();
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
#if defined K_RELEASE
uint8_t mu_number = fh_cfg->mu_number[0];
int fftsize = 1 << fh_cfg->perMu[mu_number].nDLFftSize;
#elif defined F_RELEASE
int fftsize = 1 << fh_cfg->nDLFftSize;
#endif
int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports;
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
@@ -800,11 +682,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
int numRB, startRB;
numRB = pRbElm->UP_nRBSize;
startRB = pRbElm->UP_nRBStart;
#if defined F_RELEASE
p_sec_desc = &pRbElm->sec_desc[sym_idx][0];
#elif defined K_RELEASE
p_sec_desc = &pRbElm->sec_desc[sym_idx];
#endif
LOG_D(HW, "pPrbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, startRB, numRB);
// For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx.
if (fh_cfg->RunSlotPrbMapBySymbolEnable && (sym_idx < pRbElm->nStartSymb || sym_idx >= pRbElm->nStartSymb + pRbElm->numSymb) && !p_sec_desc->pCtrl)
@@ -877,11 +755,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
// E-bit = 1 => each ethernet frame is considered as the last fragment;
// a group of PRBs per each symbol is encapsulated in one ethernet frame.
// => seems that the RUs don't check for E-bit
#if defined F_RELEASE
p_sec_desc = &p_prbMapElm->sec_desc[sym_idx][0];
#elif defined K_RELEASE
p_sec_desc = &p_prbMapElm->sec_desc[sym_idx];
#endif
int16_t startRB = p_prbMapElm->UP_nRBStart;
int16_t numRB = p_prbMapElm->UP_nRBSize;

View File

@@ -12,30 +12,16 @@ typedef struct {
uint32_t tti;
uint32_t sl;
uint32_t f;
#if defined K_RELEASE
uint8_t mu;
// the first column can expand to XRAN_MAX_SECTOR_NR for the support of multiple CCs
int32_t nRxPkt[1][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
#endif
} oran_sync_info_t;
/** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
);
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status, uint8_t mu);
/** @brief xran callback for fronthaul PRACH RX, see xran_5g_prach_req(). */
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status
#if defined K_RELEASE
, uint8_t mu
#endif
);
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status, uint8_t mu);
/** @brief xran callback for time alignment, see xran_reg_physide_cb(). */
int oai_physide_dl_tti_call_back(void *param
#if defined K_RELEASE
, uint8_t mu
#endif
);
int oai_physide_dl_tti_call_back(void *param, uint8_t mu);
#endif /* OAIORAN_H */

View File

@@ -152,13 +152,9 @@ void print_fh_init(const struct xran_fh_init *fh_init)
{
printf("xran_fh_init:\n");
print_fh_init_io_cfg(&fh_init->io_cfg);
#if defined K_RELEASE
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
print_fh_init_eaxcid_conf(&fh_init->eAxCId_conf[o_xu_id]);
}
#elif defined F_RELEASE
print_fh_init_eaxcid_conf(&fh_init->eAxCId_conf);
#endif
printf("\
xran_ports %d\n\
dpdkBasebandFecMode %d\n\
@@ -187,9 +183,7 @@ void print_fh_init(const struct xran_fh_init *fh_init)
static void print_prach_config(const struct xran_prach_config *prach_conf)
{
printf("\
"
#if defined K_RELEASE
" prach_config:\n\
prach_config:\n\
nPrachConfIdx %d\n\
nPrachSubcSpacing %d\n\
nPrachZeroCorrConf %d\n\
@@ -211,24 +205,6 @@ static void print_prach_config(const struct xran_prach_config *prach_conf)
suboffset %d\n\
numSubCarriers %d\n\
nRep %d\n",
#elif defined F_RELEASE
" prach_config:\n\
nPrachConfIdx %d\n\
nPrachSubcSpacing %d\n\
nPrachZeroCorrConf %d\n\
nPrachRestrictSet %d\n\
nPrachRootSeqIdx %d\n\
nPrachFreqStart %d\n\
nPrachFreqOffset %d\n\
nPrachFilterIdx %d\n\
startSymId %d\n\
lastSymId %d\n\
startPrbc %d\n\
numPrbc %d\n\
timeOffset %d\n\
freqOffset %d\n\
eAxC_offset %d\n",
#endif
prach_conf->nPrachConfIdx,
prach_conf->nPrachSubcSpacing,
prach_conf->nPrachZeroCorrConf,
@@ -243,7 +219,6 @@ static void print_prach_config(const struct xran_prach_config *prach_conf)
prach_conf->numPrbc,
prach_conf->timeOffset,
prach_conf->freqOffset,
#if defined K_RELEASE
prach_conf->prachEaxcOffset,
prach_conf->nprachformat,
prach_conf->periodicity,
@@ -251,9 +226,6 @@ static void print_prach_config(const struct xran_prach_config *prach_conf)
prach_conf->suboffset,
prach_conf->numSubCarriers,
prach_conf->nRep
#elif defined F_RELEASE
prach_conf->eAxC_offset
#endif
);
printf("\
nPrachConfIdxLTE %d\n",
@@ -264,18 +236,10 @@ static void print_srs_config(const struct xran_srs_config *srs_conf)
{
printf("\
srs_config:\n\
symbMask %04x\n"
#if defined K_RELEASE
" srsEaxcOffset %d\n",
#elif defined F_RELEASE
" eAxC_offset %d\n",
#endif
symbMask %04x\n\
srsEaxcOffset %d\n",
srs_conf->symbMask,
#if defined K_RELEASE
srs_conf->srsEaxcOffset
#elif defined F_RELEASE
srs_conf->eAxC_offset
#endif
);
}
@@ -283,15 +247,9 @@ static void print_frame_config(const struct xran_frame_config *frame_conf)
{
printf("\
frame_conf:\n\
nFrameDuplexType %s\n"
#if defined F_RELEASE
" nNumerology %d\n"
#endif
" nTddPeriod %d\n",
nFrameDuplexType %s\n\
nTddPeriod %d\n",
frame_conf->nFrameDuplexType == XRAN_TDD ? "TDD" : "FDD",
#if defined F_RELEASE
frame_conf->nNumerology,
#endif
frame_conf->nTddPeriod);
for (int i = 0; i < frame_conf->nTddPeriod; ++i) {
printf(" sSlotConfig[%d]: ", i);
@@ -303,11 +261,7 @@ static void print_frame_config(const struct xran_frame_config *frame_conf)
}
}
static void print_ru_config(
#if defined K_RELEASE
uint8_t mu_number,
#endif
const struct xran_ru_config *ru_conf)
static void print_ru_config(uint8_t mu_number, const struct xran_ru_config *ru_conf)
{
printf("\
ru_config:\n\
@@ -317,13 +271,9 @@ static void print_ru_config(
iqWidth %d\n\
compMeth %d\n\
iqWidth_PRACH %d\n\
compMeth_PRACH %d\n"
#if defined K_RELEASE
" fftSize[mu_number] %d\n"
#elif defined F_RELEASE
" fftSize %d\n"
#endif
" byteOrder %s\n\
compMeth_PRACH %d\n\
fftSize[mu_number] %d\n\
byteOrder %s\n\
iqOrder %s\n\
xran_max_frame %d\n",
ru_conf->xranTech == XRAN_RAN_5GNR ? "NR" : "LTE",
@@ -333,17 +283,12 @@ static void print_ru_config(
ru_conf->compMeth,
ru_conf->iqWidth_PRACH,
ru_conf->compMeth_PRACH,
#if defined K_RELEASE
ru_conf->fftSize[mu_number],
#elif defined F_RELEASE
ru_conf->fftSize,
#endif
ru_conf->byteOrder == XRAN_NE_BE_BYTE_ORDER ? "network/BE" : "CPU/LE",
ru_conf->iqOrder == XRAN_I_Q_ORDER ? "I_Q" : "Q_I",
ru_conf->xran_max_frame);
}
#if defined K_RELEASE
void print_fh_per_mu_cfg(const struct xran_fh_per_mu_cfg *perMu)
{
printf("\
@@ -413,7 +358,6 @@ void print_fh_per_mu_cfg(const struct xran_fh_per_mu_cfg *perMu)
perMu->nbIotUlScs,
perMu->adv_tx_time);
}
#endif
void print_fh_config(const struct xran_fh_config *fh_config)
{
@@ -425,14 +369,8 @@ void print_fh_config(const struct xran_fh_config *fh_config)
nCC %d\n\
neAxc %d\n\
neAxcUl %d\n\
nAntElmTRx %d\n"
#if defined F_RELEASE
" nDLFftSize %d\n\
nULFftSize %d\n\
nDLRBs %d\n\
nULRBs %d\n"
#endif
" nDLAbsFrePointA %d\n\
nAntElmTRx %d\n\
nDLAbsFrePointA %d\n\
nULAbsFrePointA %d\n\
nDLCenterFreqARFCN %d\n\
nULCenterFreqARFCN %d\n\
@@ -444,65 +382,17 @@ void print_fh_config(const struct xran_fh_config *fh_config)
fh_config->neAxc,
fh_config->neAxcUl,
fh_config->nAntElmTRx,
#if defined F_RELEASE
fh_config->nDLFftSize,
fh_config->nULFftSize,
fh_config->nDLRBs,
fh_config->nULRBs,
#endif
fh_config->nDLAbsFrePointA,
fh_config->nULAbsFrePointA,
fh_config->nDLCenterFreqARFCN,
fh_config->nULCenterFreqARFCN,
fh_config->ttiCb,
fh_config->ttiCbParam);
#if defined K_RELEASE
uint8_t mu_number = fh_config->mu_number[0];
print_fh_per_mu_cfg(&fh_config->perMu[mu_number]);
#endif
#if defined F_RELEASE
printf("\
Tadv_cp_dl %d\n\
T2a_min_cp_dl %d\n\
T2a_max_cp_dl %d\n\
T2a_min_cp_ul %d\n\
T2a_max_cp_ul %d\n\
T2a_min_up %d\n\
T2a_max_up %d\n\
Ta3_min %d\n\
Ta3_max %d\n\
T1a_min_cp_dl %d\n\
T1a_max_cp_dl %d\n\
T1a_min_cp_ul %d\n\
T1a_max_cp_ul %d\n\
T1a_min_up %d\n\
T1a_max_up %d\n\
Ta4_min %d\n\
Ta4_max %d\n",
fh_config->Tadv_cp_dl,
fh_config->T2a_min_cp_dl,
fh_config->T2a_max_cp_dl,
fh_config->T2a_min_cp_ul,
fh_config->T2a_max_cp_ul,
fh_config->T2a_min_up,
fh_config->T2a_max_up,
fh_config->Ta3_min,
fh_config->Ta3_max,
fh_config->T1a_min_cp_dl,
fh_config->T1a_max_cp_dl,
fh_config->T1a_min_cp_ul,
fh_config->T1a_max_cp_ul,
fh_config->T1a_min_up,
fh_config->T1a_max_up,
fh_config->Ta4_min,
fh_config->Ta4_max);
#endif
printf("\
enableCP %d\n"
#if defined F_RELEASE
" prachEnable %d\n"
#endif
" srsEnable %d\n\
enableCP %d\n\
srsEnable %d\n\
puschMaskEnable %d\n\
puschMaskSlot %d\n\
debugStop %d\n\
@@ -511,9 +401,6 @@ void print_fh_config(const struct xran_fh_config *fh_config)
GPS_Alpha %d\n\
GPS_Beta %d\n",
fh_config->enableCP,
#if defined F_RELEASE
fh_config->prachEnable,
#endif
fh_config->srsEnable,
fh_config->puschMaskEnable,
fh_config->puschMaskSlot,
@@ -529,16 +416,9 @@ void print_fh_config(const struct xran_fh_config *fh_config)
fh_config->srsEnableCp,
fh_config->SrsDelaySym);
#if defined F_RELEASE
print_prach_config(&fh_config->prach_conf);
#endif
print_srs_config(&fh_config->srs_conf);
print_frame_config(&fh_config->frame_conf);
print_ru_config(
#if defined K_RELEASE
mu_number,
#endif
&fh_config->ru_conf);
print_ru_config(mu_number, &fh_config->ru_conf);
printf("\
bbdev_enc %p\n\
@@ -569,7 +449,6 @@ void print_fh_config(const struct xran_fh_config *fh_config)
fh_config->dssEnable,
fh_config->dssPeriod);
#if defined K_RELEASE
printf("\
numMUs %d\n\
mu_number[0] %d\n\
@@ -577,7 +456,6 @@ void print_fh_config(const struct xran_fh_config *fh_config)
fh_config->numMUs,
fh_config->mu_number[0],
fh_config->nNumerology[0]);
#endif
}
static void get_u128_mask(const paramdef_t *pd, uint64_t *u0t63, uint64_t *u64t127)
@@ -612,41 +490,6 @@ 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
}
#if defined 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, "_aal", 4) == 0) {
uint32_t is_t2 = 0; // If not 0 then include the BBDEV device in the EAL init for FHI
char *dpdk_dev = NULL; // PCI address of the card
char *vfio_vf_token = NULL; // vfio token for the bbdev card
paramdef_t LoaderParams[] = {
{"is_t2", NULL, 0, .uptr = &is_t2, .defuintval = 0, TYPE_UINT, 0, NULL},
{"dpdk_dev", NULL, 0, .strptr = &dpdk_dev, .defstrval = NULL, TYPE_STRING, 0, NULL},
{"vfio_vf_token", NULL, 0, .strptr = &vfio_vf_token, .defstrval = NULL, TYPE_STRING, 0, NULL}
};
config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_aal");
if (!is_t2) {
AssertFatal(dpdk_dev!=NULL, "nrLDPC_coding_aal.dpdk_dev was not provided");
snprintf(&bbdev_dev[0], sizeof(bbdev_dev), "%s", dpdk_dev);
io_cfg->bbdev_dev[0] = &bbdev_dev[0]; // BBDev dev name; max devices = 1
if(vfio_vf_token != NULL) {
snprintf(&bbdev_vfio_vf_token[0], sizeof(bbdev_vfio_vf_token), "%s", vfio_vf_token);
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
}
#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
@@ -664,10 +507,8 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
io_cfg->io_sleep = 0; // enable sleep on PMD cores; 0 -> no sleep
io_cfg->nEthLinePerPort = *gpd(fhip, nump, ORAN_CONFIG_NETHPERPORT)->uptr; // 1, 2, 3 total number of links per O-RU (Fronthaul Ethernet link)
io_cfg->nEthLineSpeed = *gpd(fhip, nump, ORAN_CONFIG_NETHSPEED)->uptr; // 10G,25G,40G,100G speed of Physical connection on O-RU
#if defined K_RELEASE
io_cfg->num_mbuf_alloc = NUM_MBUFS; // number of mbuf allocated by DPDK (optimal is n = (2^q - 1))
io_cfg->num_mbuf_vf_alloc = NUM_MBUFS_VF; // number of mbuf allocated by DPDK (optimal is n = (2^q - 1))
#endif
io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_rus); // C-plane and U-plane use one VF
/* eCPRI One-Way Delay Measurements common settings for O-DU and O-RU;
@@ -698,7 +539,6 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
return true;
}
#if defined K_RELEASE
static bool set_fh_bbdev_params(struct xran_fh_init *fh_init)
{
struct xran_io_cfg *io_cfg = &fh_init->io_cfg;
@@ -738,7 +578,6 @@ static bool set_fh_bbdev_params(struct xran_fh_init *fh_init)
return true;
}
#endif
#ifdef OAI_MPLANE
static bool set_fh_eaxcid_conf_mplane(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat, const ru_session_list_t *ru_session_list)
@@ -863,17 +702,12 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
return false;
#if defined K_RELEASE
if (!set_fh_bbdev_params(fh_init))
return false;
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf[o_xu_id], xran_cat, ru_session_list))
return false;
}
#elif defined F_RELEASE
if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf, xran_cat, ru_session_list))
return false;
#endif
/* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
communicated in a single xRAN network layer transaction. Based on the MTU size, xran calculates the number
@@ -898,17 +732,12 @@ static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xra
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus))
return false;
#if defined K_RELEASE
if (!set_fh_bbdev_params(fh_init))
return false;
for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) {
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf[o_xu_id], xran_cat))
return false;
}
#elif defined F_RELEASE
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat))
return false;
#endif
/* maximum transmission unit (MTU) is the size of the largest protocol data unit (PDU) that can be
communicated in a single xRAN network layer transaction. Based on the MTU size, xran calculates the number
@@ -1004,18 +833,10 @@ static bool set_fh_prach_config(void *mplane_api,
Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU. */
#ifdef OAI_MPLANE
xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
#if defined F_RELEASE
prach_config->eAxC_offset = xran_mplane->prach_offset;
#elif defined K_RELEASE
prach_config->prachEaxcOffset = xran_mplane->prach_offset;
#endif
#else
const paramdef_t *pd = gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET);
#if defined F_RELEASE
prach_config->eAxC_offset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
#elif defined K_RELEASE
prach_config->prachEaxcOffset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
#endif
#endif
g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr;
@@ -1027,10 +848,6 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame
{
const split7_config_t *s7cfg = &oai0->split7;
frame_config->nFrameDuplexType = oai0->duplex_mode == duplex_mode_TDD ? XRAN_TDD : XRAN_FDD; // Frame Duplex type: 0 -> FDD, 1 -> TDD
#if defined F_RELEASE
frame_config->nNumerology = oai0->nr_scs_for_raster; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz
3 -> 120kHz, 4 -> 240kHz */
#endif
if (frame_config->nFrameDuplexType == XRAN_FDD)
return true;
@@ -1047,11 +864,7 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame
return true;
}
static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat
#if defined K_RELEASE
, uint8_t mu_number
#endif
, struct xran_ru_config *ru_config)
static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat, uint8_t mu_number, struct xran_ru_config *ru_config)
{
ru_config->xranTech = XRAN_RAN_5GNR; // 5GNR or LTE
ru_config->xranCat = xran_cat; // mode: Catergory A or Category B
@@ -1073,11 +886,7 @@ static bool set_fh_ru_config(void *mplane_api, const paramdef_t *rup, uint16_t f
ru_config->compMeth_PRACH = ru_config->iqWidth_PRACH < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method for PRACH
AssertFatal(fftSize > 0, "FFT size cannot be 0\n");
#if defined K_RELEASE
ru_config->fftSize[mu_number] = fftSize; // FFT Size
#elif defined F_RELEASE
ru_config->fftSize = fftSize; // FFT Size
#endif
ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER; // order of bytes in int16_t in buffer; big or little endian
ru_config->iqOrder = XRAN_I_Q_ORDER; // order of IQs in the buffer
ru_config->xran_max_frame = 0; // max frame number supported; if not specified, default of 1023 is used
@@ -1100,7 +909,6 @@ static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint1
return true;
}
#if defined K_RELEASE
static bool set_fh_per_mu_cfg(void *mplane_api, int ru_idx, int num_rus, const openair0_config_t *oai0, struct xran_fh_per_mu_cfg *perMu)
{
char aprefix[MAX_OPTNAME_SIZE] = {0};
@@ -1174,7 +982,6 @@ static bool set_activeMUs(xran_active_numerologies_per_tti *p_activeMUs, uint8_t
}
return true;
}
#endif
static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_category xran_cat, const openair0_config_t *oai0, struct xran_fh_config *fh_config)
{
@@ -1223,18 +1030,8 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->sector_id = 0; // Band sector ID for FH; not used in xran
fh_config->nCC = 1; // number of Component carriers supported on FH; M-plane info
fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
#if defined K_RELEASE
fh_config->neAxcUl = oai0->rx_num_channels / num_rus; // number of eAxc supported on one CC for UL direction = PUSCH
#elif defined F_RELEASE
fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B
#endif
fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B
#if defined F_RELEASE
fh_config->nDLFftSize = oai0->split7.fftSize; // DL FFT size; not used in xran
fh_config->nULFftSize = oai0->split7.fftSize; // UL FFT size; not used in xran
fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB; used in oaioran.c/oran-init.c; not used in xran, neither in E nor in F release
fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; used in oaioran.c/oran-init.c; in xran E release not used so the patch fixes it, but in xran F release this value is properly used
#endif
fh_config->nDLAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
fh_config->nULAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
fh_config->nDLCenterFreqARFCN = 0; // center frequency for DL in NR-ARFCN; not used in xran
@@ -1242,66 +1039,30 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->ttiCb = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call
fh_config->ttiCbParam = NULL; // check tti_to_phy_cb(), tx_cp_dl_cb() and tx_cp_ul_cb => first_call
#if defined K_RELEASE
uint8_t mu_number = oai0->nr_scs_for_raster;
if(!set_fh_per_mu_cfg(mplane_api, ru_idx, num_rus, oai0, &fh_config->perMu[mu_number]))
return false;
#endif
#if defined F_RELEASE
/* DU delay profile */
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &fh_config->T1a_min_cp_dl, &fh_config->T1a_max_cp_dl)) // E - min not used in xran, max yes; F - both min and max are used in xran
return false;
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_UL, &fh_config->T1a_min_cp_ul, &fh_config->T1a_max_cp_ul)) // both E and F - min not used in xran, max yes
return false;
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_UP, &fh_config->T1a_min_up, &fh_config->T1a_max_up)) // both E and F - min not used in xran, max yes
return false;
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &fh_config->Ta4_min, &fh_config->Ta4_max)) // both E and F - min not used in xran, max yes
return false;
#endif
fh_config->enableCP = 1; // enable C-plane
#if defined F_RELEASE
fh_config->prachEnable = 1; // enable PRACH
#endif
fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B
// For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it.
#if defined F_RELEASE
fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B
fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B
#endif
fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU
fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU
#if defined K_RELEASE
fh_config->csirsEnable = 0; // enable CSI-RS (Cat B specific)
#elif defined F_RELEASE
fh_config->cp_vlan_tag = 0; // C-plane VLAN tag; not used in xran; needed for M-plane
fh_config->up_vlan_tag = 0; // U-plane VLAN tag; not used in xran; needed for M-plane
#endif
fh_config->debugStop = 0; // enable auto stop; only used if id = O_RU
fh_config->debugStopCount = 0; // enable auto stop after number of Tx packets; not used in xran
fh_config->DynamicSectionEna = 0; // enable dynamic C-Plane section allocation
fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha
fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100
#if defined K_RELEASE
fh_config->numMUs = 1;
fh_config->mu_number[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
fh_config->nNumerology[0] = mu_number; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz, 4 -> 240kHz */
#elif defined F_RELEASE
if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf))
return false;
#endif
/* SRS only used if XRAN_CATEGORY_B
Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */
// fh_config->srs_conf = {0};
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
return false;
if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat
#if defined K_RELEASE
, mu_number
#endif
, &fh_config->ru_conf))
if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat, mu_number, &fh_config->ru_conf))
return false;
fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder
@@ -1330,11 +1091,9 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->dssEnable = 0; // enable DSS (extension-9)
fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR
// fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled
#if defined K_RELEASE
if (!set_activeMUs(&activeMUs, oai0->nr_scs_for_raster))
return false;
fh_config->activeMUs = &activeMUs;
#endif
return true;
}

View File

@@ -27,11 +27,7 @@
// structure holding allocated memory for ports (multiple DUs) and sectors
// (multiple CCs)
static oran_port_instance_t gPortInst[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR];
#if defined F_RELEASE
void *gxran_handle;
#elif defined K_RELEASE
void *gxran_handle[XRAN_PORTS_NUM];
#endif
static struct xran_fh_init g_fh_init = {0};
static struct xran_fh_config g_fh_config[XRAN_PORTS_NUM] = {0};
@@ -85,22 +81,15 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
e->nStartSymb = start_sym;
e->numSymb = num_sym;
e->nRBStart = 0;
#if defined K_RELEASE
uint8_t mu_number = f->mu_number[0];
e->nRBSize = (dir == XRAN_DIR_DL) ? f->perMu[mu_number].nDLRBs : f->perMu[mu_number].nULRBs;
#elif defined F_RELEASE
e->nRBSize = (dir == XRAN_DIR_DL) ? f->nDLRBs : f->nULRBs;
#endif
e->nBeamIndex = 0;
e->compMethod = f->ru_conf.compMeth;
e->iqWidth = f->ru_conf.iqWidth;
#if defined K_RELEASE
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
#endif
return prbmap;
}
#if defined K_RELEASE
static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f)
{
struct xran_prb_map prbmap = {
@@ -123,7 +112,6 @@ static struct xran_prb_map get_xran_prb_map_prach(const struct xran_fh_config *f
memset(&prbmap.sFrontHaulRxPacketCtrl, 0, XRAN_NUM_OF_SYMBOL_PER_SLOT * sizeof(struct xran_rx_packet_ctl));
return prbmap;
}
#endif
static uint32_t next_power_2(uint32_t num)
{
@@ -255,12 +243,8 @@ static void oran_allocate_cplane_buffers(void *instHandle,
if (prb_conf->nTddPeriod != 0 && (j % prb_conf->nTddPeriod) == prb_conf->mixed_slot_index)
src = &prb_conf->mixedSlotMap;
if (fh_config->RunSlotPrbMapBySymbolEnable) {
#if defined K_RELEASE
uint8_t mu_number = fh_config->mu_number[0];
xran_init_PrbMap_by_symbol_from_cfg(src, ptr, mtu, fh_config->perMu[mu_number].nDLRBs);
#elif defined F_RELEASE
xran_init_PrbMap_by_symbol_from_cfg(src, ptr, mtu, fh_config->nDLRBs);
#endif
} else {
xran_init_PrbMap_from_cfg(src, ptr, mtu);
}
@@ -302,9 +286,7 @@ static void oran_allocate_buffers(void *handle,
// DL/UL PRB mapping depending on the duplex mode
struct xran_prb_map dlPm = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, 14);
struct xran_prb_map ulPm = get_xran_prb_map(fh_config, XRAN_DIR_UL, 0, 14);
#if defined K_RELEASE
struct xran_prb_map prachPm = get_xran_prb_map_prach(fh_config);
#endif
struct xran_prb_map dlPmMixed = {0};
struct xran_prb_map ulPmMixed = {0};
uint32_t idx = 0;
@@ -332,7 +314,6 @@ static void oran_allocate_buffers(void *handle,
uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu);
uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
#if defined K_RELEASE
oran_cplane_prb_config prachConf = {
.nTddPeriod = fh_config->frame_conf.nTddPeriod,
.mixed_slot_index = idx,
@@ -342,14 +323,9 @@ static void oran_allocate_buffers(void *handle,
uint32_t numPrbElmPrach = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&prachPm, mtu);
uint32_t size_of_prb_map_prach = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElmPrach);
#endif
// PDSCH
#if defined K_RELEASE
const uint32_t txBufSize = get_nSW_ToFpga_FTH_TxBufferLen(fh_config->nNumerology[0], fh_config->max_sections_per_slot);
#elif defined F_RELEASE
const uint32_t txBufSize = get_nSW_ToFpga_FTH_TxBufferLen(fh_config->frame_conf.nNumerology, fh_config->max_sections_per_slot);
#endif
oran_allocate_uplane_buffers(pi->instanceHandle, bl->src, bl->bufs.tx, xran_max_antenna_nr, txBufSize);
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->srccp,
@@ -362,11 +338,7 @@ static void oran_allocate_buffers(void *handle,
&dlConf);
// PUSCH
#if defined K_RELEASE
const uint32_t rxBufSize = get_nFpgaToSW_FTH_RxBufferLen(fh_config->nNumerology[0]);
#elif defined F_RELEASE
const uint32_t rxBufSize = get_nFpgaToSW_FTH_RxBufferLen(fh_config->frame_conf.nNumerology);
#endif
oran_allocate_uplane_buffers(pi->instanceHandle, bl->dst, bl->bufs.rx, xran_max_antenna_nr, rxBufSize);
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->dstcp,
@@ -381,7 +353,6 @@ static void oran_allocate_buffers(void *handle,
// PRACH
const uint32_t prachBufSize = PRACH_PLAYBACK_BUFFER_BYTES;
oran_allocate_uplane_buffers(pi->instanceHandle, bl->prachdst, bl->bufs.prach, xran_max_antenna_nr, prachBufSize);
#if defined K_RELEASE
oran_allocate_cplane_buffers(pi->instanceHandle,
bl->prachdstdecomp,
bl->bufs.prachdecomp,
@@ -391,19 +362,6 @@ static void oran_allocate_buffers(void *handle,
fh_config,
size_of_prb_map_prach,
&prachConf);
#elif defined F_RELEASE
// PRACH decomp buffer does not have separate DPDK-allocated memory pool
// bufs, it points to the same pool as the prach buffer. Unclear to me why
for (uint32_t a = 0; a < xran_max_antenna_nr; ++a) {
for (uint32_t j = 0; j < XRAN_N_FE_BUF_LEN; ++j) {
bl->prachdstdecomp[a][j].pBuffers = &bl->bufs.prachdecomp[a][j];
for (uint32_t k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++k) {
struct xran_flat_buffer *fb = &bl->prachdstdecomp[a][j].pBuffers[k];
fb->pData = bl->prachdst[a][j].pBuffers[k].pData;
}
}
}
#endif
struct xran_buffer_list *src[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
struct xran_buffer_list *srccp[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
@@ -422,35 +380,23 @@ static void oran_allocate_buffers(void *handle,
}
}
#if defined K_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag, fh_config->nNumerology[0]);
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag, fh_config->nNumerology[0]);
#elif defined F_RELEASE
xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag);
xran_5g_prach_req(pi->instanceHandle, prachdst, prachdstdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag);
#endif
}
void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_config *xran_fh_config)
{
int32_t xret = 0;
#if defined K_RELEASE
xran_mem_mgr_leak_detector_init();
#endif
print_fh_init(xran_fh_init);
#if defined F_RELEASE
xret = xran_init(0, NULL, xran_fh_init, NULL, &gxran_handle);
#elif defined K_RELEASE
xret = xran_init(0, NULL, xran_fh_init, NULL, gxran_handle);
#endif
if (xret != XRAN_STATUS_SUCCESS) {
printf("xran_init failed %d\n", xret);
exit(-1);
}
#if defined K_RELEASE
for (int32_t o_xu_id = 0; o_xu_id < xran_fh_init->xran_ports; o_xu_id++) {
if (gxran_handle[o_xu_id] == NULL) {
printf("xran_init for RU%d failed\n", o_xu_id);
@@ -459,16 +405,11 @@ void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_conf
printf("RU%d handle = %p\n", o_xu_id, gxran_handle[o_xu_id]);
}
}
#endif
/** process all the O-RU|O-DU for use case */
for (int32_t o_xu_id = 0; o_xu_id < xran_fh_init->xran_ports; o_xu_id++) {
print_fh_config(&xran_fh_config[o_xu_id]);
#if defined F_RELEASE
xret = xran_open(gxran_handle, &xran_fh_config[o_xu_id]);
#elif defined K_RELEASE
xret = xran_open(gxran_handle[o_xu_id], &xran_fh_config[o_xu_id]);
#endif
if (xret != XRAN_STATUS_SUCCESS) {
printf("xran_open failed %d\n", xret);
exit(-1);
@@ -481,36 +422,17 @@ void *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_conf
pi->prach_tag = tag;
pi->pusch_tag = tag;
#if defined K_RELEASE
oran_allocate_buffers(gxran_handle[0], o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
if ((xret = xran_timingsource_reg_tticb(NULL, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
printf("xran_timingsource_reg_tticb failed %d\n", xret);
exit(-1);
}
#elif defined F_RELEASE
LOG_W(HW, "Please be aware that F release support will be removed in the future. Consider switching to K release.\n");
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) {
printf("xran_reg_physide_cb failed %d\n", xret);
exit(-1);
}
#endif
// retrieve and store prach duration
#if defined K_RELEASE
uint8_t mu = xran_fh_config[o_xu_id].nNumerology[0];
uint8_t idx = xran_fh_config[o_xu_id].perMu[mu].prach_conf.nPrachConfIdx;
#elif defined F_RELEASE
uint8_t idx = xran_fh_config[o_xu_id].prach_conf.nPrachConfIdx;
#endif
const struct xran_frame_config *fc = &xran_fh_config[o_xu_id].frame_conf;
g_prach_info[o_xu_id] = get_nr_prach_occasion_info_from_index(idx,
#if defined K_RELEASE
mu > 2 ? FR2 : FR1,
#elif defined F_RELEASE
fc->nNumerology > 2 ? FR2 : FR1,
#endif
fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD);
g_prach_info[o_xu_id] = get_nr_prach_occasion_info_from_index(idx, mu > 2 ? FR2 : FR1, fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD);
}
// store config after xran initialization -- xran makes modifications to

View File

@@ -41,11 +41,7 @@ typedef struct oran_port_instance_t {
} oran_port_instance_t;
extern struct xran_fh_config gxran_fh_config[XRAN_PORTS_NUM];
#if defined F_RELEASE
extern void *gxran_handle;
#elif defined K_RELEASE
extern void *gxran_handle[XRAN_PORTS_NUM];
#endif
void *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh_config);

View File

@@ -37,9 +37,7 @@ typedef struct {
} oran_eth_state_t;
notifiedFIFO_t oran_sync_fifo;
#if defined K_RELEASE
notifiedFIFO_t oran_sync_fifo_prach;
#endif
int trx_oran_start(openair0_device_t *device)
{
@@ -48,7 +46,6 @@ int trx_oran_start(openair0_device_t *device)
oran_eth_state_t *s = device->priv;
// Start ORAN
#if defined K_RELEASE
if (xran_timingsource_start() != 0) {
printf("%s:%d:%s: Start timing source failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
@@ -64,25 +61,16 @@ int trx_oran_start(openair0_device_t *device)
}
xran_mem_mgr_leak_detector_display(0);
#endif
#if defined F_RELEASE
if (xran_start(s->oran_priv) != 0) {
printf("%s:%d:%s: Start ORAN failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
#elif defined K_RELEASE
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
if (xran_start(((void **)s->oran_priv)[port_id]) != 0) {
printf("%s:%d:%s: Start ORAN port ID %d failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__, port_id);
exit(1);
}
}
#endif
printf("Start ORAN. Done\n");
#if defined K_RELEASE
for (int32_t cc_id = 0; cc_id < s->nCC; cc_id++) {
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
if (xran_activate_cc(port_id, cc_id) != 0) {
@@ -93,7 +81,6 @@ int trx_oran_start(openair0_device_t *device)
}
}
}
#endif
return 0;
}
@@ -102,14 +89,10 @@ void trx_oran_end(openair0_device_t *device)
{
printf("ORAN: %s\n", __FUNCTION__);
oran_eth_state_t *s = device->priv;
#if defined K_RELEASE
xran_shutdown(s->oran_priv);
#endif
xran_close(s->oran_priv);
#if defined K_RELEASE
xran_cleanup();
xran_mem_mgr_leak_detector_destroy();
#endif
}
int trx_oran_stop(openair0_device_t *device)
@@ -117,7 +100,6 @@ int trx_oran_stop(openair0_device_t *device)
printf("ORAN: %s\n", __FUNCTION__);
oran_eth_state_t *s = device->priv;
#if defined K_RELEASE
for (int32_t cc_id = 0; cc_id < s->nCC; cc_id++) {
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
xran_deactivate_cc(port_id, cc_id);
@@ -125,15 +107,10 @@ int trx_oran_stop(openair0_device_t *device)
}
xran_timingsource_stop();
#endif
#if defined F_RELEASE
xran_stop(s->oran_priv);
#elif defined K_RELEASE
for (int32_t port_id = 0; port_id < s->num_ports; port_id++) {
xran_stop(((void **)s->oran_priv)[port_id]);
}
#endif
#ifdef OAI_MPLANE
printf("[MPLANE] Stopping M-plane.\n");
@@ -290,11 +267,6 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
/* Secondly, process PRACH packets */
int f_prach, sl_prach;
#if defined F_RELEASE
// no PRACH callback (no queue) in F release so use the expected combination
f_prach = *frame;
sl_prach = *slot;
#endif
ret = xran_fh_rx_prach_read_slot(ru->gNB_list[0], &ru_info, &f_prach, &sl_prach);
if (ret != 0) {
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX PRACH function \n", f_prach, sl_prach);
@@ -446,9 +418,7 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device_t
// create message queues for ORAN sync
initNotifiedFIFO(&oran_sync_fifo);
#if defined K_RELEASE
initNotifiedFIFO(&oran_sync_fifo_prach);
#endif
eth->e.flags = ETH_RAW_IF4p5_MODE;
eth->e.compression = NO_COMPRESS;

View File

@@ -50,8 +50,8 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot);
/** @brief Reads RX data PRACH of next slot.
*
* @param ru pointer to structure keeping pointers to OAI data.
* @param frame input for F_RELEASE, output for K_RELEASE.
* @param slot input for F_RELEASE, output for K_RELEASE. */
* @param frame output of the frame which has been read.
* @param slot output of the slot which has been read. */
int xran_fh_rx_prach_read_slot(PHY_VARS_gNB *gNB, ru_info_t *ru, int *frame, int *slot);
/** @brief Writes TX data (PDSCH) of given slot. */
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp);