887 lines
29 KiB
C
887 lines
29 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
#include "oran-config.h"
|
|
#include "oran-params.h"
|
|
#include "common/utils/assertions.h"
|
|
#include "common_lib.h"
|
|
|
|
#include "xran_fh_o_du.h"
|
|
#include "xran_cp_api.h"
|
|
#include "rte_ether.h"
|
|
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
|
|
static void print_fh_eowd_cmn(unsigned index, const struct xran_ecpri_del_meas_cmn *eowd_cmn)
|
|
{
|
|
printf("\
|
|
eowd_cmn[%u]:\n\
|
|
initiator_en %d\n\
|
|
numberOfSamples %d\n\
|
|
filterType %d\n\
|
|
responseTo %ld\n\
|
|
measVf %d\n\
|
|
measState %d\n\
|
|
measId %d\n\
|
|
measMethod %d\n\
|
|
owdm_enable %d\n\
|
|
owdm_PlLength %d\n",
|
|
index,
|
|
eowd_cmn->initiator_en,
|
|
eowd_cmn->numberOfSamples,
|
|
eowd_cmn->filterType,
|
|
eowd_cmn->responseTo,
|
|
eowd_cmn->measVf,
|
|
eowd_cmn->measState,
|
|
eowd_cmn->measId,
|
|
eowd_cmn->measMethod,
|
|
eowd_cmn->owdm_enable,
|
|
eowd_cmn->owdm_PlLength);
|
|
}
|
|
|
|
static void print_fh_eowd_port(unsigned index, unsigned vf, const struct xran_ecpri_del_meas_port *eowd_port)
|
|
{
|
|
printf("\
|
|
eowd_port[%u][%u]:\n\
|
|
t1 %ld\n\
|
|
t2 %ld\n\
|
|
tr %ld\n\
|
|
delta %ld\n\
|
|
portid %d\n\
|
|
runMeas %d\n\
|
|
currentMeasID %d\n\
|
|
msState %d\n\
|
|
numMeas %d\n\
|
|
txDone %d\n\
|
|
rspTimerIdx %ld\n\
|
|
delaySamples [%ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld]\n\
|
|
delayAvg %ld\n",
|
|
index,
|
|
vf,
|
|
eowd_port->t1,
|
|
eowd_port->t2,
|
|
eowd_port->tr,
|
|
eowd_port->delta,
|
|
eowd_port->portid,
|
|
eowd_port->runMeas,
|
|
eowd_port->currentMeasID,
|
|
eowd_port->msState,
|
|
eowd_port->numMeas,
|
|
eowd_port->txDone,
|
|
eowd_port->rspTimerIdx,
|
|
eowd_port->delaySamples[0],
|
|
eowd_port->delaySamples[1],
|
|
eowd_port->delaySamples[2],
|
|
eowd_port->delaySamples[3],
|
|
eowd_port->delaySamples[4],
|
|
eowd_port->delaySamples[5],
|
|
eowd_port->delaySamples[6],
|
|
eowd_port->delaySamples[7],
|
|
eowd_port->delaySamples[8],
|
|
eowd_port->delaySamples[9],
|
|
eowd_port->delaySamples[10],
|
|
eowd_port->delaySamples[11],
|
|
eowd_port->delaySamples[12],
|
|
eowd_port->delaySamples[13],
|
|
eowd_port->delaySamples[14],
|
|
eowd_port->delaySamples[15],
|
|
eowd_port->delayAvg);
|
|
}
|
|
|
|
static void print_fh_init_io_cfg(const struct xran_io_cfg *io_cfg)
|
|
{
|
|
printf("\
|
|
io_cfg:\n\
|
|
id %d (%s)\n\
|
|
num_vfs %d\n\
|
|
num_rxq %d\n\
|
|
dpdk_dev [%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s]\n\
|
|
bbdev_dev %s\n\
|
|
bbdev_mode %d\n\
|
|
dpdkIoVaMode %d\n\
|
|
dpdkMemorySize %d\n",
|
|
io_cfg->id,
|
|
io_cfg->id == 0 ? "O-DU" : "O-RU",
|
|
io_cfg->num_vfs,
|
|
io_cfg->num_rxq,
|
|
io_cfg->dpdk_dev[XRAN_UP_VF],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF1],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF1],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF2],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF2],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF3],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF3],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF4],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF4],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF5],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF5],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF6],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF6],
|
|
io_cfg->dpdk_dev[XRAN_UP_VF7],
|
|
io_cfg->dpdk_dev[XRAN_CP_VF7],
|
|
io_cfg->bbdev_dev[0],
|
|
io_cfg->bbdev_mode,
|
|
io_cfg->dpdkIoVaMode,
|
|
io_cfg->dpdkMemorySize);
|
|
|
|
printf("\
|
|
core %d\n\
|
|
system_core %d\n\
|
|
pkt_proc_core %016lx\n\
|
|
pkt_proc_core_64_127 %016lx\n\
|
|
pkt_aux_core %d\n\
|
|
timing_core %d\n\
|
|
port [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, ]\n\
|
|
io_sleep %d\n\
|
|
nEthLinePerPort %d\n\
|
|
nEthLineSpeed %d\n\
|
|
one_vf_cu_plane %d\n",
|
|
io_cfg->core,
|
|
io_cfg->system_core,
|
|
io_cfg->pkt_proc_core,
|
|
io_cfg->pkt_proc_core_64_127,
|
|
io_cfg->pkt_aux_core,
|
|
io_cfg->timing_core,
|
|
io_cfg->port[XRAN_UP_VF],
|
|
io_cfg->port[XRAN_CP_VF],
|
|
io_cfg->port[XRAN_UP_VF1],
|
|
io_cfg->port[XRAN_CP_VF1],
|
|
io_cfg->port[XRAN_UP_VF2],
|
|
io_cfg->port[XRAN_CP_VF2],
|
|
io_cfg->port[XRAN_UP_VF3],
|
|
io_cfg->port[XRAN_CP_VF3],
|
|
io_cfg->port[XRAN_UP_VF4],
|
|
io_cfg->port[XRAN_CP_VF4],
|
|
io_cfg->port[XRAN_UP_VF5],
|
|
io_cfg->port[XRAN_CP_VF5],
|
|
io_cfg->port[XRAN_UP_VF6],
|
|
io_cfg->port[XRAN_CP_VF6],
|
|
io_cfg->port[XRAN_UP_VF7],
|
|
io_cfg->port[XRAN_CP_VF7],
|
|
io_cfg->io_sleep,
|
|
io_cfg->nEthLinePerPort,
|
|
io_cfg->nEthLineSpeed,
|
|
io_cfg->one_vf_cu_plane);
|
|
print_fh_eowd_cmn(0, &io_cfg->eowd_cmn[0]);
|
|
print_fh_eowd_cmn(1, &io_cfg->eowd_cmn[1]);
|
|
for (int i = 0; i < 2; ++i)
|
|
for (int v = 0; v < io_cfg->num_vfs; ++v)
|
|
print_fh_eowd_port(i, v, &io_cfg->eowd_port[i][v]);
|
|
}
|
|
|
|
static void print_fh_init_eaxcid_conf(const struct xran_eaxcid_config *eaxcid_conf)
|
|
{
|
|
printf("\
|
|
eAxCId_conf:\n\
|
|
mask_cuPortId 0x%04x\n\
|
|
mask_bandSectorId 0x%04x\n\
|
|
mask_ccId 0x%04x\n\
|
|
mask_ruPortId 0x%04x\n\
|
|
bit_cuPortId %d\n\
|
|
bit_bandSectorId %d\n\
|
|
bit_ccId %d\n\
|
|
bit_ruPortId %d\n",
|
|
eaxcid_conf->mask_cuPortId,
|
|
eaxcid_conf->mask_bandSectorId,
|
|
eaxcid_conf->mask_ccId,
|
|
eaxcid_conf->mask_ruPortId,
|
|
eaxcid_conf->bit_cuPortId,
|
|
eaxcid_conf->bit_bandSectorId,
|
|
eaxcid_conf->bit_ccId,
|
|
eaxcid_conf->bit_ruPortId);
|
|
}
|
|
|
|
static void print_ether_addr(const char *pre, int num_ether, const struct rte_ether_addr *addrs)
|
|
{
|
|
printf("%s [", pre);
|
|
for (int i = 0; i < num_ether; ++i) {
|
|
char buf[18];
|
|
rte_ether_format_addr(buf, 18, &addrs[i]);
|
|
printf("%s", buf);
|
|
if (i != num_ether - 1)
|
|
printf(", ");
|
|
}
|
|
printf("]\n");
|
|
}
|
|
|
|
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);
|
|
print_fh_init_eaxcid_conf(&fh_init->eAxCId_conf);
|
|
printf("\
|
|
xran_ports %d\n\
|
|
dpdkBasebandFecMode %d\n\
|
|
dpdkBasebandDevice %s\n\
|
|
filePrefix %s\n\
|
|
mtu %d\n",
|
|
fh_init->xran_ports,
|
|
fh_init->dpdkBasebandFecMode,
|
|
fh_init->dpdkBasebandDevice,
|
|
fh_init->filePrefix,
|
|
fh_init->mtu);
|
|
print_ether_addr(" p_o_du_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_du_addr);
|
|
print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr);
|
|
printf("\
|
|
totalBfWeights %d\n",
|
|
fh_init->totalBfWeights);
|
|
}
|
|
|
|
static void print_prach_config(const struct xran_prach_config *prach_conf)
|
|
{
|
|
printf("\
|
|
prach_config:\n\
|
|
nPrachConfIdx %d\n\
|
|
nPrachSubcSpacing %d\n\
|
|
nPrachZeroCorrConf %d\n\
|
|
nPrachRestrictSet %d\n\
|
|
nPrachRootSeqIdx %d\n\
|
|
nPrachFreqStart %d\n\
|
|
nPrachFreqOffset %d\n\
|
|
nPrachFilterIdx %d\n\
|
|
startSymId %d\n\
|
|
lastSymId %d\n\
|
|
startPrbc %d\n\
|
|
numPrbc %d\n\
|
|
timeOffset %d\n\
|
|
freqOffset %d\n\
|
|
eAxC_offset %d\n",
|
|
prach_conf->nPrachConfIdx,
|
|
prach_conf->nPrachSubcSpacing,
|
|
prach_conf->nPrachZeroCorrConf,
|
|
prach_conf->nPrachRestrictSet,
|
|
prach_conf->nPrachRootSeqIdx,
|
|
prach_conf->nPrachFreqStart,
|
|
prach_conf->nPrachFreqOffset,
|
|
prach_conf->nPrachFilterIdx,
|
|
prach_conf->startSymId,
|
|
prach_conf->lastSymId,
|
|
prach_conf->startPrbc,
|
|
prach_conf->numPrbc,
|
|
prach_conf->timeOffset,
|
|
prach_conf->freqOffset,
|
|
prach_conf->eAxC_offset);
|
|
}
|
|
|
|
static void print_srs_config(const struct xran_srs_config *srs_conf)
|
|
{
|
|
printf("\
|
|
srs_config:\n\
|
|
symbMask %04x\n\
|
|
eAxC_offset %d\n",
|
|
srs_conf->symbMask,
|
|
srs_conf->eAxC_offset);
|
|
}
|
|
|
|
static void print_frame_config(const struct xran_frame_config *frame_conf)
|
|
{
|
|
printf("\
|
|
frame_conf:\n\
|
|
nFrameDuplexType %s\n\
|
|
nNumerology %d\n\
|
|
nTddPeriod %d\n",
|
|
frame_conf->nFrameDuplexType == XRAN_TDD ? "TDD" : "FDD",
|
|
frame_conf->nNumerology,
|
|
frame_conf->nTddPeriod);
|
|
for (int i = 0; i < frame_conf->nTddPeriod; ++i) {
|
|
printf(" sSlotConfig[%d]: ", i);
|
|
for (int s = 0; s < XRAN_NUM_OF_SYMBOL_PER_SLOT; ++s) {
|
|
uint8_t nSymbolType = frame_conf->sSlotConfig[i].nSymbolType[s];
|
|
printf("%c", nSymbolType == 0 ? 'D' : (nSymbolType == 1 ? 'U' : 'G'));
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
static void print_ru_config(const struct xran_ru_config *ru_conf)
|
|
{
|
|
printf("\
|
|
ru_config:\n\
|
|
xranTech %s\n\
|
|
xranCat %s\n\
|
|
xranCompHdrType %s\n\
|
|
iqWidth %d\n\
|
|
compMeth %d\n\
|
|
iqWidth_PRACH %d\n\
|
|
compMeth_PRACH %d\n\
|
|
fftSize %d\n\
|
|
byteOrder %s\n\
|
|
iqOrder %s\n\
|
|
xran_max_frame %d\n",
|
|
ru_conf->xranTech == XRAN_RAN_5GNR ? "NR" : "LTE",
|
|
ru_conf->xranCat == XRAN_CATEGORY_A ? "A" : "B",
|
|
ru_conf->xranCompHdrType == XRAN_COMP_HDR_TYPE_DYNAMIC ? "dynamic" : "static",
|
|
ru_conf->iqWidth,
|
|
ru_conf->compMeth,
|
|
ru_conf->iqWidth_PRACH,
|
|
ru_conf->compMeth_PRACH,
|
|
ru_conf->fftSize,
|
|
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);
|
|
}
|
|
|
|
void print_fh_config(const struct xran_fh_config *fh_config)
|
|
{
|
|
printf("xran_fh_config:\n");
|
|
printf("\
|
|
dpdk_port %d\n\
|
|
sector_id %d\n\
|
|
nCC %d\n\
|
|
neAxc %d\n\
|
|
neAxcUl %d\n\
|
|
nAntElmTRx %d\n\
|
|
nDLFftSize %d\n\
|
|
nULFftSize %d\n\
|
|
nDLRBs %d\n\
|
|
nULRBs %d\n\
|
|
nDLAbsFrePointA %d\n\
|
|
nULAbsFrePointA %d\n\
|
|
nDLCenterFreqARFCN %d\n\
|
|
nULCenterFreqARFCN %d\n\
|
|
ttiCb %p\n\
|
|
ttiCbParam %p\n",
|
|
fh_config->dpdk_port,
|
|
fh_config->sector_id,
|
|
fh_config->nCC,
|
|
fh_config->neAxc,
|
|
fh_config->neAxcUl,
|
|
fh_config->nAntElmTRx,
|
|
fh_config->nDLFftSize,
|
|
fh_config->nULFftSize,
|
|
fh_config->nDLRBs,
|
|
fh_config->nULRBs,
|
|
fh_config->nDLAbsFrePointA,
|
|
fh_config->nULAbsFrePointA,
|
|
fh_config->nDLCenterFreqARFCN,
|
|
fh_config->nULCenterFreqARFCN,
|
|
fh_config->ttiCb,
|
|
fh_config->ttiCbParam);
|
|
|
|
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);
|
|
|
|
printf("\
|
|
enableCP %d\n\
|
|
prachEnable %d\n\
|
|
srsEnable %d\n\
|
|
puschMaskEnable %d\n\
|
|
puschMaskSlot %d\n\
|
|
cp_vlan_tag %d\n\
|
|
up_vlan_tag %d\n\
|
|
debugStop %d\n\
|
|
debugStopCount %d\n\
|
|
DynamicSectionEna %d\n\
|
|
GPS_Alpha %d\n\
|
|
GPS_Beta %d\n",
|
|
fh_config->enableCP,
|
|
fh_config->prachEnable,
|
|
fh_config->srsEnable,
|
|
fh_config->puschMaskEnable,
|
|
fh_config->puschMaskSlot,
|
|
fh_config->cp_vlan_tag,
|
|
fh_config->up_vlan_tag,
|
|
fh_config->debugStop,
|
|
fh_config->debugStopCount,
|
|
fh_config->DynamicSectionEna,
|
|
fh_config->GPS_Alpha,
|
|
fh_config->GPS_Beta);
|
|
|
|
print_prach_config(&fh_config->prach_conf);
|
|
print_srs_config(&fh_config->srs_conf);
|
|
print_frame_config(&fh_config->frame_conf);
|
|
print_ru_config(&fh_config->ru_conf);
|
|
|
|
printf("\
|
|
bbdev_enc %p\n\
|
|
bbdev_dec %p\n\
|
|
tx_cp_eAxC2Vf [not implemented by fhi_lib]\n\
|
|
tx_up_eAxC2Vf [not implemented by fhi_lib]\n\
|
|
rx_cp_eAxC2Vf [not implemented by fhi_lib]\n\
|
|
rx_up_eAxC2Vf [not implemented by fhi_lib]\n\
|
|
log_level %d\n\
|
|
max_sections_per_slot %d\n\
|
|
max_sections_per_symbol %d\n",
|
|
fh_config->bbdev_enc,
|
|
fh_config->bbdev_dec,
|
|
fh_config->log_level,
|
|
fh_config->max_sections_per_slot,
|
|
fh_config->max_sections_per_symbol);
|
|
}
|
|
|
|
static const paramdef_t *gpd(const paramdef_t *pd, int num, const char *name)
|
|
{
|
|
/* the config module does not know const-correctness... */
|
|
int idx = config_paramidx_fromname((paramdef_t *)pd, num, (char *)name);
|
|
DevAssert(idx >= 0);
|
|
return &pd[idx];
|
|
}
|
|
|
|
static uint64_t get_u64_mask(const paramdef_t *pd)
|
|
{
|
|
DevAssert(pd != NULL);
|
|
AssertFatal(pd->numelt > 0, "no entries for creation of mask\n");
|
|
uint64_t mask = 0;
|
|
for (int i = 0; i < pd->numelt; ++i) {
|
|
int num = pd->iptr[i];
|
|
AssertFatal(num >= 0 && num < 64, "cannot put element of %d in 64-bit mask\n", num);
|
|
mask |= 1 << num;
|
|
}
|
|
return mask;
|
|
}
|
|
|
|
static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump)
|
|
{
|
|
DevAssert(fhip != NULL);
|
|
int num_dev = gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->numelt;
|
|
AssertFatal(num_dev > 0, "need to provide DPDK devices for O-RAN 7.2 Fronthaul\n");
|
|
AssertFatal(num_dev < 17, "too many DPDK devices for O-RAN 7.2 Fronthaul\n");
|
|
|
|
io_cfg->id = 0; // 0 = O-DU
|
|
io_cfg->num_vfs = num_dev;
|
|
io_cfg->num_rxq = 2; // Assume two HW RX queues per RU
|
|
for (int i = 0; i < num_dev; ++i)
|
|
io_cfg->dpdk_dev[i] = strdup(gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->strlistptr[i]);
|
|
//io_cfg->bbdev_dev = NULL;
|
|
io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // none
|
|
io_cfg->dpdkIoVaMode = 0; /* IOVA mode */
|
|
io_cfg->dpdkMemorySize = 0; /* DPDK memory size */
|
|
io_cfg->core = *gpd(fhip, nump, ORAN_CONFIG_IO_CORE)->iptr;
|
|
io_cfg->system_core = *gpd(fhip, nump, ORAN_CONFIG_SYSTEM_CORE)->iptr;
|
|
io_cfg->pkt_proc_core = get_u64_mask(gpd(fhip, nump, ORAN_CONFIG_WORKER_CORES));
|
|
io_cfg->pkt_proc_core_64_127 = 0x0; // bitmap 0 -> no core
|
|
io_cfg->pkt_aux_core = 0; /* sapmle app says 0 = "do not start" */
|
|
io_cfg->timing_core = *gpd(fhip, nump, ORAN_CONFIG_IO_CORE)->iptr; /* sample app: equal to io_core */
|
|
//io_cfg->port = {0}; // all 0
|
|
io_cfg->io_sleep = 0; // no sleep
|
|
io_cfg->nEthLinePerPort = *gpd(fhip, nump, ORAN_CONFIG_NETHPERPORT)->uptr;
|
|
io_cfg->nEthLineSpeed = *gpd(fhip, nump, ORAN_CONFIG_NETHSPEED)->uptr;
|
|
io_cfg->one_vf_cu_plane = 0; // false: C/U-plane don't share VF
|
|
// io_cfg->eowd_cmn[0] // all 0
|
|
// io_cfg->eowd_cmn[1] // all 0
|
|
// io_cfg->eowd_port[0]... // all 0
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat)
|
|
{
|
|
// values taken from sample app
|
|
switch (cat) {
|
|
case XRAN_CATEGORY_A:
|
|
eaxcid_conf->mask_cuPortId = 0xf000;
|
|
eaxcid_conf->mask_bandSectorId = 0x0f00;
|
|
eaxcid_conf->mask_ccId = 0x00f0;
|
|
eaxcid_conf->mask_ruPortId = 0x000f;
|
|
eaxcid_conf->bit_cuPortId = 12;
|
|
eaxcid_conf->bit_bandSectorId = 8;
|
|
eaxcid_conf->bit_ccId = 4;
|
|
eaxcid_conf->bit_ruPortId = 0;
|
|
break;
|
|
case XRAN_CATEGORY_B:
|
|
eaxcid_conf->mask_cuPortId = 0xf000;
|
|
eaxcid_conf->mask_bandSectorId = 0x0c00;
|
|
eaxcid_conf->mask_ccId = 0x0300;
|
|
eaxcid_conf->mask_ruPortId = 0x000f;
|
|
eaxcid_conf->bit_cuPortId = 12;
|
|
eaxcid_conf->bit_bandSectorId = 10;
|
|
eaxcid_conf->bit_ccId = 8;
|
|
eaxcid_conf->bit_ruPortId = 0;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint8_t *get_ether_addr(const char *addr, struct rte_ether_addr *ether_addr)
|
|
{
|
|
#pragma GCC diagnostic push
|
|
// the following line disables the deprecated warning
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
int ret = rte_ether_unformat_addr(addr, ether_addr);
|
|
#pragma GCC diagnostic pop
|
|
if (ret == 0)
|
|
return (uint8_t *)ether_addr;
|
|
return NULL;
|
|
}
|
|
|
|
bool set_fh_init(struct xran_fh_init *fh_init)
|
|
{
|
|
memset(fh_init, 0, sizeof(*fh_init));
|
|
|
|
// verify oran section is present: we don't have a list but the below returns
|
|
// numelt > 0 if the block is there
|
|
paramlist_def_t pl = {0};
|
|
strncpy(pl.listname, CONFIG_STRING_ORAN, sizeof(pl.listname) - 1);
|
|
config_getlist(config_get_if(), &pl, NULL, 0, /* prefix */ NULL);
|
|
if (pl.numelt == 0) {
|
|
printf("Configuration section \"%s\" not present: cannot initialize fhi_lib!\n", CONFIG_STRING_ORAN);
|
|
return false;
|
|
}
|
|
|
|
paramdef_t fhip[] = ORAN_GLOBALPARAMS_DESC;
|
|
int nump = sizeofArray(fhip);
|
|
int ret = config_get(config_get_if(), fhip, nump, CONFIG_STRING_ORAN);
|
|
if (ret <= 0) {
|
|
printf("problem reading section \"%s\"\n", CONFIG_STRING_ORAN);
|
|
return false;
|
|
}
|
|
|
|
paramdef_t FHconfigs[] = ORAN_FH_DESC;
|
|
paramlist_def_t FH_ConfigList = {CONFIG_STRING_ORAN_FH};
|
|
char aprefix[MAX_OPTNAME_SIZE] = {0};
|
|
sprintf(aprefix, "%s", CONFIG_STRING_ORAN);
|
|
const int nfh = sizeofArray(FHconfigs);
|
|
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
|
|
int num_rus = FH_ConfigList.numelt;
|
|
int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt;
|
|
int num_du_addr = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->numelt;
|
|
int num_vfs = gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->numelt;
|
|
if (num_ru_addr != num_du_addr) {
|
|
printf("need to have same number of DUs and RUs!\n");
|
|
return false;
|
|
}
|
|
if (num_ru_addr != num_vfs) {
|
|
printf("need to have as many RU/DU entries as DPDK devices (one VF for CP and UP each)\n");
|
|
return false;
|
|
}
|
|
|
|
if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump))
|
|
return false;
|
|
if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, XRAN_CATEGORY_A))
|
|
return false;
|
|
|
|
fh_init->xran_ports = num_rus;
|
|
fh_init->dpdkBasebandFecMode = 0;
|
|
fh_init->dpdkBasebandDevice = NULL;
|
|
fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr); // see DPDK --file-prefix
|
|
fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr;
|
|
|
|
// if multiple RUs: xran_ethdi_init_dpdk_io() iterates over
|
|
// &p_o_ru_addr[i]
|
|
char **du_addrs = gpd(fhip, nump, ORAN_CONFIG_DU_ADDR)->strlistptr;
|
|
fh_init->p_o_du_addr = calloc(num_du_addr, sizeof(struct rte_ether_addr));
|
|
AssertFatal(fh_init->p_o_du_addr != NULL, "out of memory\n");
|
|
for (int i = 0; i < num_du_addr; ++i) {
|
|
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_du_addr;
|
|
if (get_ether_addr(du_addrs[i], &ea[i]) == NULL) {
|
|
printf("could not read ethernet address '%s' for DU!\n", du_addrs[i]);
|
|
return false;
|
|
}
|
|
}
|
|
fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr));
|
|
char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr;
|
|
AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n");
|
|
for (int i = 0; i < num_ru_addr; ++i) {
|
|
struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr;
|
|
if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) {
|
|
printf("could not read ethernet address '%s' for RU!\n", ru_addrs[i]);
|
|
return false;
|
|
}
|
|
}
|
|
fh_init->totalBfWeights = 32;
|
|
|
|
return true;
|
|
}
|
|
|
|
static enum xran_cp_filterindex get_prach_filterindex_fr1(duplex_mode_t mode, int prach_index)
|
|
{
|
|
if (mode == duplex_mode_TDD) {
|
|
// 38.211 table 6.3.3.2-3 "unpaired spectrum" -> TDD
|
|
switch (prach_index) {
|
|
case 0 ... 39:
|
|
case 256 ... 262:
|
|
return XRAN_FILTERINDEX_PRACH_012;
|
|
case 40 ... 66:
|
|
return XRAN_FILTERINDEX_PRACH_3;
|
|
case 67 ... 255:
|
|
return XRAN_FILTERINDEX_PRACH_ABC;
|
|
}
|
|
} else if (mode == duplex_mode_FDD) {
|
|
// 38.211 table 6.3.3.2-2 "paired spectrum" -> FDD
|
|
switch (prach_index) {
|
|
case 0 ... 59:
|
|
return XRAN_FILTERINDEX_PRACH_012;
|
|
case 60 ... 86:
|
|
return XRAN_FILTERINDEX_PRACH_3;
|
|
case 87 ... 255:
|
|
return XRAN_FILTERINDEX_PRACH_ABC;
|
|
default:
|
|
AssertFatal(false, "unknown PRACH index %d\n", prach_index);
|
|
}
|
|
} else {
|
|
AssertFatal(false, "unsupported duplex mode %d\n", mode);
|
|
}
|
|
return XRAN_FILTERINDEX_STANDARD;
|
|
}
|
|
|
|
// PRACH guard interval. Raymond: "[it] is not in the configuration, (i.e. it
|
|
// is deterministic depending on others). LiteON must hard-code this in the
|
|
// O-RU itself, benetel doesn't (as O-RAN specifies). So we will need to tell
|
|
// the driver what the case is and provide"
|
|
// this is a hack
|
|
int g_kbar;
|
|
|
|
static bool set_fh_prach_config(const openair0_config_t *oai0,
|
|
const paramdef_t *prachp,
|
|
int nprach,
|
|
struct xran_prach_config *prach_config)
|
|
{
|
|
const split7_config_t *s7cfg = &oai0->split7;
|
|
|
|
prach_config->nPrachConfIdx = s7cfg->prach_index;
|
|
prach_config->nPrachSubcSpacing = oai0->nr_scs_for_raster;
|
|
prach_config->nPrachZeroCorrConf = 0;
|
|
prach_config->nPrachRestrictSet = 0;
|
|
prach_config->nPrachRootSeqIdx = 0;
|
|
prach_config->nPrachFreqStart = s7cfg->prach_freq_start;
|
|
prach_config->nPrachFreqOffset = (s7cfg->prach_freq_start * 12 - oai0->num_rb_dl * 6) * 2;
|
|
if (oai0->nr_band < 100)
|
|
prach_config->nPrachFilterIdx = get_prach_filterindex_fr1(oai0->duplex_mode, s7cfg->prach_index);
|
|
else
|
|
prach_config->nPrachFilterIdx = XRAN_FILTERINDEX_PRACH_ABC;
|
|
prach_config->startSymId = 0;
|
|
prach_config->lastSymId = 0;
|
|
prach_config->startPrbc = 0;
|
|
prach_config->numPrbc = 0;
|
|
prach_config->timeOffset = 0;
|
|
prach_config->freqOffset = 0;
|
|
prach_config->eAxC_offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr;
|
|
|
|
g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool set_fh_srs_config(struct xran_srs_config *srs_config)
|
|
{
|
|
srs_config->symbMask = 0;
|
|
srs_config->eAxC_offset = 8;
|
|
return true;
|
|
}
|
|
|
|
static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame_config *frame_config)
|
|
{
|
|
const split7_config_t *s7cfg = &oai0->split7;
|
|
frame_config->nFrameDuplexType = oai0->duplex_mode == duplex_mode_TDD ? XRAN_TDD : XRAN_FDD;
|
|
frame_config->nNumerology = oai0->nr_scs_for_raster;
|
|
frame_config->nTddPeriod = s7cfg->n_tdd_period;
|
|
|
|
struct xran_slot_config *sc = &frame_config->sSlotConfig[0];
|
|
for (int slot = 0; slot < frame_config->nTddPeriod; ++slot)
|
|
for (int sym = 0; sym < 14; ++sym)
|
|
sc[slot].nSymbolType[sym] = s7cfg->slot_dirs[slot].sym_dir[sym];
|
|
return true;
|
|
}
|
|
|
|
static bool set_fh_ru_config(const paramdef_t *rup, int nru, struct xran_ru_config *ru_config)
|
|
{
|
|
ru_config->xranTech = XRAN_RAN_5GNR;
|
|
ru_config->xranCat = XRAN_CATEGORY_A;
|
|
ru_config->xranCompHdrType = XRAN_COMP_HDR_TYPE_STATIC;
|
|
ru_config->iqWidth = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH)->uptr;
|
|
AssertFatal(ru_config->iqWidth <= 16, "IQ Width cannot be > 16!\n");
|
|
ru_config->compMeth = ru_config->iqWidth < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE;
|
|
ru_config->iqWidth_PRACH = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH_PRACH)->uptr;
|
|
AssertFatal(ru_config->iqWidth_PRACH <= 16, "IQ Width for PRACH cannot be > 16!\n");
|
|
ru_config->compMeth_PRACH = ru_config->iqWidth_PRACH < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE;
|
|
ru_config->fftSize = *gpd(rup, nru, ORAN_RU_CONFIG_FFT_SIZE)->uptr;
|
|
ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER;
|
|
ru_config->iqOrder = XRAN_I_Q_ORDER;
|
|
ru_config->xran_max_frame = 0;
|
|
return true;
|
|
}
|
|
|
|
static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint16_t *min, uint16_t *max)
|
|
{
|
|
const paramdef_t *p = gpd(pd, num, name);
|
|
if (p->numelt != 2) {
|
|
printf("parameter list \"%s\" should have exactly two parameters (max&min), but has %d\n", name, num);
|
|
return false;
|
|
}
|
|
*min = p->uptr[0];
|
|
*max = p->uptr[1];
|
|
if (*min > *max) {
|
|
printf("min parameter of \"%s\" is larger than max!\n", name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
extern uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
|
|
bool set_fh_config(int ru_idx, int num_rus, const openair0_config_t *oai0, struct xran_fh_config *fh_config)
|
|
{
|
|
AssertFatal(num_rus == 1 || num_rus == 2, "only support 1 or 2 RUs as of now\n");
|
|
AssertFatal(ru_idx < num_rus, "illegal ru_idx %d: must be < %d\n", ru_idx, num_rus);
|
|
DevAssert(oai0->tx_num_channels > 0 && oai0->rx_num_channels > 0);
|
|
DevAssert(oai0->tx_bw > 0 && oai0->rx_bw > 0);
|
|
//AssertFatal(oai0->tx_num_channels == oai0->rx_num_channels, "cannot handle unequal number of TX/RX channels\n");
|
|
DevAssert(oai0->tx_freq[0] > 0);
|
|
for (int i = 1; i < oai0->tx_num_channels; ++i)
|
|
DevAssert(oai0->tx_freq[0] == oai0->tx_freq[i]);
|
|
DevAssert(oai0->rx_freq[0] > 0);
|
|
for (int i = 1; i < oai0->rx_num_channels; ++i)
|
|
DevAssert(oai0->rx_freq[0] == oai0->rx_freq[i]);
|
|
DevAssert(oai0->nr_band > 0);
|
|
DevAssert(oai0->nr_scs_for_raster > 0);
|
|
|
|
// we simply assume that the loading process provides function to_nrarfcn()
|
|
// to calculate the ARFCN numbers from frequency. That is not clean, but the
|
|
// best we can do without copy-pasting the function.
|
|
uint32_t nDLCenterFreqARFCN = to_nrarfcn(oai0->nr_band, oai0->tx_freq[0], oai0->nr_scs_for_raster, oai0->tx_bw);
|
|
uint32_t nULCenterFreqARFCN = to_nrarfcn(oai0->nr_band, oai0->rx_freq[0], oai0->nr_scs_for_raster, oai0->rx_bw);
|
|
|
|
paramdef_t FHconfigs[] = ORAN_FH_DESC;
|
|
paramlist_def_t FH_ConfigList = {CONFIG_STRING_ORAN_FH};
|
|
char aprefix[MAX_OPTNAME_SIZE] = {0};
|
|
sprintf(aprefix, "%s", CONFIG_STRING_ORAN);
|
|
const int nfh = sizeofArray(FHconfigs);
|
|
config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix);
|
|
if (FH_ConfigList.numelt == 0) {
|
|
printf("No configuration section \"%s\" found inside \"%s\": cannot initialize fhi_lib!\n", CONFIG_STRING_ORAN_FH, aprefix);
|
|
return false;
|
|
}
|
|
paramdef_t *fhp = FH_ConfigList.paramarray[ru_idx];
|
|
|
|
paramdef_t rup[] = ORAN_RU_DESC;
|
|
int nru = sizeofArray(rup);
|
|
sprintf(aprefix, "%s.%s.[%d].%s", CONFIG_STRING_ORAN, CONFIG_STRING_ORAN_FH, ru_idx, CONFIG_STRING_ORAN_RU);
|
|
int ret = config_get(config_get_if(), rup, nru, aprefix);
|
|
if (ret < 0) {
|
|
printf("No configuration section \"%s\": cannot initialize fhi_lib!\n", aprefix);
|
|
return false;
|
|
}
|
|
paramdef_t prachp[] = ORAN_PRACH_DESC;
|
|
int nprach = sizeofArray(prachp);
|
|
sprintf(aprefix, "%s.%s.[%d].%s", CONFIG_STRING_ORAN, CONFIG_STRING_ORAN_FH, ru_idx, CONFIG_STRING_ORAN_PRACH);
|
|
ret = config_get(config_get_if(), prachp, nprach, aprefix);
|
|
if (ret < 0) {
|
|
printf("No configuration section \"%s\": cannot initialize fhi_lib!\n", aprefix);
|
|
return false;
|
|
}
|
|
|
|
memset(fh_config, 0, sizeof(*fh_config));
|
|
|
|
fh_config->dpdk_port = ru_idx;
|
|
fh_config->sector_id = 0;
|
|
fh_config->nCC = 1;
|
|
fh_config->neAxc = oai0->tx_num_channels / num_rus;
|
|
fh_config->neAxcUl = oai0->rx_num_channels / num_rus;
|
|
fh_config->nAntElmTRx = oai0->tx_num_channels / num_rus;
|
|
fh_config->nDLFftSize = 0;
|
|
fh_config->nULFftSize = 0;
|
|
fh_config->nDLRBs = oai0->num_rb_dl;
|
|
fh_config->nULRBs = oai0->num_rb_dl;
|
|
fh_config->nDLAbsFrePointA = 0;
|
|
fh_config->nULAbsFrePointA = 0;
|
|
fh_config->nDLCenterFreqARFCN = nDLCenterFreqARFCN;
|
|
fh_config->nULCenterFreqARFCN = nULCenterFreqARFCN;
|
|
fh_config->ttiCb = NULL;
|
|
fh_config->ttiCbParam = NULL;
|
|
fh_config->Tadv_cp_dl = *gpd(fhp, nfh, ORAN_FH_CONFIG_TADV_CP_DL)->uptr;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_DL, &fh_config->T2a_min_cp_dl, &fh_config->T2a_max_cp_dl))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_UL, &fh_config->T2a_min_cp_ul, &fh_config->T2a_max_cp_ul))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_UP, &fh_config->T2a_min_up, &fh_config->T2a_max_up))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA3, &fh_config->Ta3_min, &fh_config->Ta3_max))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_CP_DL, &fh_config->T1a_min_cp_dl, &fh_config->T1a_max_cp_dl))
|
|
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))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T1A_UP, &fh_config->T1a_min_up, &fh_config->T1a_max_up))
|
|
return false;
|
|
if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA4, &fh_config->Ta4_min, &fh_config->Ta4_max))
|
|
return false;
|
|
fh_config->enableCP = 1;
|
|
fh_config->prachEnable = 1;
|
|
fh_config->srsEnable = 0;
|
|
fh_config->puschMaskEnable = 0;
|
|
fh_config->puschMaskSlot = 0;
|
|
fh_config->cp_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_CP_VLAN_TAG)->uptr;
|
|
fh_config->up_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_UP_VLAN_TAG)->uptr;
|
|
fh_config->debugStop = 0;
|
|
fh_config->debugStopCount = 0;
|
|
fh_config->DynamicSectionEna = 0;
|
|
fh_config->GPS_Alpha = 0;
|
|
fh_config->GPS_Beta = 0;
|
|
|
|
if (!set_fh_prach_config(oai0, prachp, nprach, &fh_config->prach_conf))
|
|
return false;
|
|
if (!set_fh_srs_config(&fh_config->srs_conf))
|
|
return false;
|
|
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
|
|
return false;
|
|
if (!set_fh_ru_config(rup, nru, &fh_config->ru_conf))
|
|
return false;
|
|
|
|
fh_config->bbdev_enc = NULL;
|
|
fh_config->bbdev_dec = NULL;
|
|
// fh_config->tx_cp_eAxC2Vf [not implemented by fhi_lib]
|
|
// fh_config->tx_up_eAxC2Vf [not implemented by fhi_lib]
|
|
// fh_config->rx_cp_eAxC2Vf [not implemented by fhi_lib]
|
|
// fh_config->rx_up_eAxC2Vf [not implemented by fhi_lib]
|
|
fh_config->log_level = 1;
|
|
fh_config->max_sections_per_slot = 8;
|
|
fh_config->max_sections_per_symbol = 8;
|
|
|
|
return true;
|
|
}
|