From f30453968f2f09429fe4b366bf7dc4e24174c7aa Mon Sep 17 00:00:00 2001 From: Teodora Date: Tue, 12 Nov 2024 16:38:42 +0100 Subject: [PATCH] xran integration improvements - identification of each parameter in fh_init and fh_config structs - identification of unused parameters in xran library - identification of parameters used for CAT A O-RU => CAT B not supported in this release --- radio/fhi_72/oran-config.c | 370 ++++++++++++++++++------------------- radio/fhi_72/oran-params.h | 4 +- 2 files changed, 183 insertions(+), 191 deletions(-) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 23649b18b7..4f828b8a1a 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -27,6 +27,7 @@ #include "xran_fh_o_du.h" #include "xran_cp_api.h" #include "rte_ether.h" +#include #include "stdio.h" #include "string.h" @@ -234,13 +235,14 @@ void print_fh_init(const struct xran_fh_init *fh_init) dpdkBasebandFecMode %d\n\ dpdkBasebandDevice %s\n\ filePrefix %s\n\ - mtu %d\n", + mtu %d\n\ + p_o_du_addr %s\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); + fh_init->mtu, + fh_init->p_o_du_addr); print_ether_addr(" p_o_ru_addr", fh_init->xran_ports * fh_init->io_cfg.num_vfs, (struct rte_ether_addr *)fh_init->p_o_ru_addr); printf("\ totalBfWeights %d\n", @@ -448,15 +450,19 @@ void print_fh_config(const struct xran_fh_config *fh_config) 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\ + tx_cp_eAxC2Vf %p\n\ + tx_up_eAxC2Vf %p\n\ + rx_cp_eAxC2Vf %p\n\ + rx_up_eAxC2Vf %p\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->tx_cp_eAxC2Vf, + fh_config->tx_up_eAxC2Vf, + fh_config->rx_cp_eAxC2Vf, + fh_config->rx_up_eAxC2Vf, fh_config->log_level, fh_config->max_sections_per_slot, fh_config->max_sections_per_symbol); @@ -483,52 +489,66 @@ static uint64_t get_u64_mask(const paramdef_t *pd) return mask; } -static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, int nump) +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); 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 = *gpd(fhip, nump, ORAN_CONFIG_DPDK_MEM_SIZE)->uptr; - 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 + io_cfg->id = 0; // 0 -> xran as O-DU; 1 -> xran as O-RU + io_cfg->num_vfs = num_dev; // number of VFs for C-plane and U-plane (should be even); max = XRAN_VF_MAX + io_cfg->num_rxq = 1; // number of RX queues per VF + for (int i = 0; i < num_dev; ++i) { + io_cfg->dpdk_dev[i] = strdup(gpd(fhip, nump, ORAN_CONFIG_DPDK_DEVICES)->strlistptr[i]); // VFs devices + } + io_cfg->bbdev_dev[0] = NULL; // BBDev dev name; max devices = 1 + io_cfg->bbdev_mode = XRAN_BBDEV_NOT_USED; // DPDK for BBDev + io_cfg->dpdkIoVaMode = 0; // IOVA mode + io_cfg->dpdkMemorySize = *gpd(fhip, nump, ORAN_CONFIG_DPDK_MEM_SIZE)->uptr; // DPDK max memory allocation + + /* the following core assignment is needed for rte_eal_init() function within xran library; + these parameters are machine specific */ + io_cfg->core = *gpd(fhip, nump, ORAN_CONFIG_IO_CORE)->iptr; // core used for IO; absolute CPU core ID for xran library, it should be an isolated core + io_cfg->system_core = *gpd(fhip, nump, ORAN_CONFIG_SYSTEM_CORE)->iptr; // absolute CPU core ID for DPDK control threads, it should be an isolated core + io_cfg->pkt_proc_core = get_u64_mask(gpd(fhip, nump, ORAN_CONFIG_WORKER_CORES)); // worker mask 0-63 + io_cfg->pkt_proc_core_64_127 = 0x0; // worker mask 64-127; to be used if machine supports more than 64 cores + io_cfg->pkt_aux_core = 0; // sample app says 0 = "do not start" + io_cfg->timing_core = *gpd(fhip, nump, ORAN_CONFIG_IO_CORE)->iptr; // core used by xran + + // io_cfg->port[XRAN_VF_MAX] // VFs ports; filled within xran library + 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 + io_cfg->one_vf_cu_plane = (io_cfg->num_vfs == num_rus); // C-plane and U-plane use one VF + + /* use owdm to calculate T12 and T34 -> CUS specification, section 2.3.3.3 */ + // io_cfg->eowd_cmn[2] // ecpri one-way delay measurements common settings for O-DU and O-RU + // io_cfg->eowd_port[2][XRAN_VF_MAX] // ecpri owd measurements per port variables for O-DU and O-RU return true; } static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat) { - // values taken from sample app + /* CUS specification, section 3.1.3.1.6 + DU_port_ID - used to differentiate processing units at O-DU (e.g., different baseband cards). + BandSector_ID - aggregated cell identifier (distinguishes bands and sectors supported by the O-RU). + CC_ID - distinguishes Carrier Components supported by the O-RU. + RU_Port_ID - designates logical flows such as data layers or spatial streams, and logical flows such as separate + numerologies (e.g. PRACH) or signaling channels requiring special antenna assignments such as SRS. + The assignment of the DU_port_ID, BandSector_ID, CC_ID, and RU_Port_ID + as part of the eAxC ID is done solely by the O-DU via the M-plane. + Each ID field has a flexible bit allocation, but the total eAxC ID field length is fixed, 16 bits. */ 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_cuPortId = 0; + eaxcid_conf->bit_bandSectorId = 0; // total number of band sectors supported by O-RU should be retreived by M-plane - && + eaxcid_conf->bit_ccId = 0; // total number of CC supported by O-RU should be retreived by M-plane - eaxcid_conf->bit_ruPortId = 0; break; case XRAN_CATEGORY_B: @@ -560,7 +580,7 @@ uint8_t *get_ether_addr(const char *addr, struct rte_ether_addr *ether_addr) return NULL; } -static bool set_fh_init(struct xran_fh_init *fh_init) +static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_cat) { memset(fh_init, 0, sizeof(*fh_init)); @@ -588,42 +608,28 @@ static bool set_fh_init(struct xran_fh_init *fh_init) 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)) + int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs + + if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus)) return false; - if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, XRAN_CATEGORY_A)) + if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat)) 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->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs + fh_init->dpdkBasebandFecMode = 0; // DPDK Baseband FEC device mode (0-SW, 1-HW); not used in xran + fh_init->dpdkBasebandDevice = NULL; // DPDK Baseband device address; not used in xran + /* used to specify a unique prefix for shared memory, and files created by multiple DPDK processes; + is it necessary */ + fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr); + /* 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. Supported 1500 bytes and 9600 bytes (Jumbo Frame); + xran only checks if (MTU <= 1500), therefore setting any value > 1500, xran assumes 9600 value is used */ fh_init->mtu = *gpd(fhip, nump, ORAN_CONFIG_MTU)->uptr; - // 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_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function + + int num_ru_addr = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->numelt; fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr)); char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr; AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n"); @@ -634,42 +640,12 @@ static bool set_fh_init(struct xran_fh_init *fh_init) return false; } } - fh_init->totalBfWeights = 32; + + fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec 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 @@ -678,73 +654,82 @@ static enum xran_cp_filterindex get_prach_filterindex_fr1(duplex_mode_t mode, in int g_kbar; static bool set_fh_prach_config(const openair0_config_t *oai0, + const uint32_t max_num_ant, 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->nPrachConfIdx = s7cfg->prach_index; // PRACH Configuration Index + prach_config->nPrachSubcSpacing = oai0->nr_scs_for_raster; // 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz, 3 -> 120kHz + prach_config->nPrachZeroCorrConf = 0; // PRACH zeroCorrelationZoneConfig; should be saved from config file; not used in xran + prach_config->nPrachRestrictSet = 0; /* PRACH restrictedSetConfig; should be saved from config file; 0 = unrestricted, + 1 = restricted type A, 2=restricted type B; not used in xran */ + prach_config->nPrachRootSeqIdx = 0; // PRACH Root Sequence Index; should be saved from config file; 1 = 839, 2 = 139; not used in xran + prach_config->nPrachFreqStart = s7cfg->prach_freq_start; // PRACH frequency start (MSG1) + prach_config->nPrachFreqOffset = (s7cfg->prach_freq_start * 12 - oai0->num_rb_dl * 6) * 2; // PRACH frequency offset + prach_config->nPrachFilterIdx = 0; /* PRACH filter index; not used in xran; + in E release hardcoded to XRAN_FILTERINDEX_PRACH_ABC (preamble format A1~3, B1~4, C0, C2) + in F release properly calculated */ + + /* Return values after initialization */ 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; + + /* xran defines PDSCH eAxC IDs as [0...Ntx-1]; + xran defines PUSCH eAxC IDs as [0...Nrx-1]; + PRACH offset must be >= max(Ntx, Nrx) */ + uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; + prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; 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->nFrameDuplexType = oai0->duplex_mode == duplex_mode_TDD ? XRAN_TDD : XRAN_FDD; // Frame Duplex type: 0 -> FDD, 1 -> TDD + frame_config->nNumerology = oai0->nr_scs_for_raster; /* 0 -> 15kHz, 1 -> 30kHz, 2 -> 60kHz + 3 -> 120kHz, 4 -> 240kHz */ + + if (frame_config->nFrameDuplexType == XRAN_FDD) + return true; + + // TDD periodicity frame_config->nTddPeriod = s7cfg->n_tdd_period; + // TDD Slot configuration 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, uint16_t fftSize, int nru, struct xran_ru_config *ru_config) +static bool set_fh_ru_config(const paramdef_t *rup, uint16_t fftSize, int nru, enum xran_category xran_cat, 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; + ru_config->xranTech = XRAN_RAN_5GNR; // 5GNR or LTE + ru_config->xranCat = xran_cat; // mode: Catergory A or Category B + ru_config->xranCompHdrType = XRAN_COMP_HDR_TYPE_STATIC; // dynamic or static udCompHdr handling + ru_config->iqWidth = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH)->uptr; // IQ bit width 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; + ru_config->compMeth = ru_config->iqWidth < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method + ru_config->iqWidth_PRACH = *gpd(rup, nru, ORAN_RU_CONFIG_IQWIDTH_PRACH)->uptr; // IQ bit width for PRACH 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->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"); - ru_config->fftSize = fftSize; - ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER; - ru_config->iqOrder = XRAN_I_Q_ORDER; - ru_config->xran_max_frame = 0; + ru_config->fftSize = fftSize; // FFT Size + 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 return true; } @@ -764,14 +749,12 @@ static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint1 return true; } -extern uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); -static bool set_fh_config(int ru_idx, int num_rus, const openair0_config_t *oai0, struct xran_fh_config *fh_config) +static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, 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]); @@ -782,12 +765,6 @@ static bool set_fh_config(int ru_idx, int num_rus, const openair0_config_t *oai0 DevAssert(oai0->nr_scs_for_raster > 0); AssertFatal(oai0->threequarter_fs == 0, "cannot use three-quarter sampling with O-RAN 7.2 split\n"); - // 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}; @@ -819,30 +796,30 @@ static bool set_fh_config(int ru_idx, int num_rus, const openair0_config_t *oai0 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)) + fh_config->dpdk_port = ru_idx; // DPDK port number used for FH + 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) + fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B + fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B + fh_config->nDLFftSize = 0; // DL FFT size; not used in xran + fh_config->nULFftSize = 0; // UL FFT size; not used in xran + fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB + fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; in xran not used as id = O_DU, but used in oaioran.c/oran-init.c + 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 + fh_config->nULCenterFreqARFCN = 0; // center frequency for UL in NR-ARFCN; not used in xran + 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 + fh_config->Tadv_cp_dl = *gpd(fhp, nfh, ORAN_FH_CONFIG_TADV_CP_DL)->uptr; // not used in xran + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_DL, &fh_config->T2a_min_cp_dl, &fh_config->T2a_max_cp_dl)) // not used in xran 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)) + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_CP_UL, &fh_config->T2a_min_cp_ul, &fh_config->T2a_max_cp_ul)) // not used in xran return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_UP, &fh_config->T2a_min_up, &fh_config->T2a_max_up)) + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_T2A_UP, &fh_config->T2a_min_up, &fh_config->T2a_max_up)) // not used in xran return false; - if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA3, &fh_config->Ta3_min, &fh_config->Ta3_max)) + if (!set_maxmin_pd(fhp, nfh, ORAN_FH_CONFIG_TA3, &fh_config->Ta3_min, &fh_config->Ta3_max)) // not used in xran 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; @@ -852,50 +829,67 @@ static bool set_fh_config(int ru_idx, int num_rus, const openair0_config_t *oai0 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; + fh_config->enableCP = 1; // enable C-plane + fh_config->prachEnable = 1; // enable PRACH + fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B + 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 + fh_config->cp_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_CP_VLAN_TAG)->uptr; // C-plane VLAN tag; not used in xran; needed for M-plane + fh_config->up_vlan_tag = *gpd(fhp, nfh, ORAN_FH_CONFIG_UP_VLAN_TAG)->uptr; // U-plane VLAN tag; not used in xran; needed for M-plane + fh_config->debugStop = 0; // enable auto stop; not used in xran + 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; not used in xran + 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 (!set_fh_prach_config(oai0, prachp, nprach, &fh_config->prach_conf)) - return false; - if (!set_fh_srs_config(&fh_config->srs_conf)) + if (!set_fh_prach_config(oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf)) return false; + /* 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(rup, oai0->split7.fftSize, nru, &fh_config->ru_conf)) + if (!set_fh_ru_config(rup, oai0->split7.fftSize, nru, xran_cat, &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; + fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder + fh_config->bbdev_dec = NULL; // call back to poll BBDev decoder + + /* CUS specification, section 3.1.3.1.6 + This parameter is an eAxC identifier (eAxC ID) and identifies the specific data flow associated with each + C-Plane (ecpriRtcid) or U-Plane (ecpriPcid) message. + Each of bellow parameters is a matrix [XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR] */ + // fh_config->tx_cp_eAxC2Vf // mapping of C-Plane (ecpriRtcid) to VF; not used in xran + // fh_config->tx_up_eAxC2Vf // mapping of U-Plane (ecpriPcid) to VF; not used in xran + // fh_config->rx_cp_eAxC2Vf // mapping of C-Plane (ecpriRtcid) to VF; not used in xran + // fh_config->rx_up_eAxC2Vf // mapping of U-Plane (ecpriPcid) to VF; not used in xran + + fh_config->log_level = 1; // configuration of log level; 1 -> enabled + + /* Parameters that should be retreived via M-plane + O-RU defines them for Section Type 1 (Most DL/UL radio channels) and 3 (PRACH and mixed-numerology channels) + Note: When PRACH having same numerology as other UL channels, Section type 1 can alternatively be used by O-DU for PRACH signaling. + In this case, O-RU is not expected to perform any PRACH specific processing. */ + fh_config->max_sections_per_slot = 0; // not used in xran + fh_config->max_sections_per_symbol = 0; // not used in xran return true; } bool get_xran_config(const openair0_config_t *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config) { - if (!set_fh_init(fh_init)) { + /* This xran integration release is only valid for O-RU CAT A. + Therefore, each FH parameter is hardcoded to CAT A. + If you are interested in CAT B, please be aware that parameters of fh_init and fh_config structs must be modified accordingly. */ + enum xran_category xran_cat = XRAN_CATEGORY_A; + + if (!set_fh_init(fh_init, xran_cat)) { printf("could not read FHI 7.2/ORAN config\n"); return false; } for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) { - if (!set_fh_config(o_xu_id, fh_init->xran_ports, openair0_cfg, &fh_config[o_xu_id])) { + if (!set_fh_config(o_xu_id, fh_init->xran_ports, xran_cat, openair0_cfg, &fh_config[o_xu_id])) { printf("could not read FHI 7.2/RU-specific config\n"); return false; } diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index ff8058f9ca..e9de03660c 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -31,7 +31,6 @@ #define ORAN_CONFIG_SYSTEM_CORE "system_core" #define ORAN_CONFIG_IO_CORE "io_core" #define ORAN_CONFIG_WORKER_CORES "worker_cores" -#define ORAN_CONFIG_DU_ADDR "du_addr" #define ORAN_CONFIG_RU_ADDR "ru_addr" #define ORAN_CONFIG_MTU "mtu" #define ORAN_CONFIG_FILE_PREFIX "file_prefix" @@ -47,9 +46,8 @@ {ORAN_CONFIG_SYSTEM_CORE, "DPDK control threads core\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {ORAN_CONFIG_IO_CORE, "DPDK Core used for IO\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=4, TYPE_INT, 0}, \ {ORAN_CONFIG_WORKER_CORES, "CPU Cores to use for workers\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=NULL,TYPE_UINTARRAY, 0}, \ - {ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ {ORAN_CONFIG_RU_ADDR, "Ether addr of RU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \ - {ORAN_CONFIG_MTU, "MTU of Eth interface\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \ + {ORAN_CONFIG_MTU, "MTU of Eth interface\n", 0, .uptr=NULL, .defuintval=1500, TYPE_UINT, 0}, \ {ORAN_CONFIG_FILE_PREFIX, "DPDK file-prefix\n", 0, .strptr=NULL, .defstrval="wls_0", TYPE_STRING, 0}, \ {ORAN_CONFIG_NETHPERPORT, "number of links per port\n", 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0}, \ {ORAN_CONFIG_NETHSPEED, "ethernet speed link\n", 0, .uptr=NULL, .defuintval=10, TYPE_UINT, 0}, \