From d5fceb8e1fd3d6599d938531caa7799b656376f1 Mon Sep 17 00:00:00 2001 From: Teodora Date: Mon, 3 Feb 2025 17:46:08 +0100 Subject: [PATCH] Parsing RU M-plane info to xran --- radio/fhi_72/oran-config.c | 132 +++++++++++++++++++++++++++++------- radio/fhi_72/oran-config.h | 2 +- radio/fhi_72/oran_isolate.c | 5 +- 3 files changed, 113 insertions(+), 26 deletions(-) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index ba8fb2fcea..71804c5298 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -32,6 +32,10 @@ #include "stdio.h" #include "string.h" +#ifdef OAI_MPLANE +#include "mplane/ru-mplane-api.h" +#endif + static void print_fh_eowd_cmn(unsigned index, const struct xran_ecpri_del_meas_cmn *eowd_cmn) { printf("\ @@ -522,6 +526,38 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in return true; } +#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) +{ + xran_mplane_t *xran_mplane = &ru_session_list->ru_session[0].xran_mplane; + switch (cat) { + case XRAN_CATEGORY_A: + eaxcid_conf->mask_cuPortId = xran_mplane->du_port_bitmask; + eaxcid_conf->mask_bandSectorId = xran_mplane->band_sector_bitmask; + eaxcid_conf->mask_ccId = xran_mplane->ccid_bitmask; + eaxcid_conf->mask_ruPortId = xran_mplane->ru_port_bitmask; + eaxcid_conf->bit_cuPortId = xran_mplane->du_port; + eaxcid_conf->bit_bandSectorId = xran_mplane->band_sector; // total number of band sectors supported by O-RU should be retrieved by M-plane - && + eaxcid_conf->bit_ccId = xran_mplane->ccid; // total number of CC supported by O-RU should be retrieved by M-plane - + eaxcid_conf->bit_ruPortId = xran_mplane->ru_port; + 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; +} +#else static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran_category cat) { /* CUS specification, section 3.1.3.1.6 @@ -540,8 +576,8 @@ static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran eaxcid_conf->mask_ccId = 0x00f0; eaxcid_conf->mask_ruPortId = 0x000f; 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_bandSectorId = 0; // total number of band sectors supported by O-RU should be retrieved by M-plane - && + eaxcid_conf->bit_ccId = 0; // total number of CC supported by O-RU should be retrieved by M-plane - eaxcid_conf->bit_ruPortId = 0; break; case XRAN_CATEGORY_B: @@ -560,6 +596,7 @@ static bool set_fh_eaxcid_conf(struct xran_eaxcid_config *eaxcid_conf, enum xran return true; } +#endif uint8_t *get_ether_addr(const char *addr, struct rte_ether_addr *ether_addr) { @@ -573,7 +610,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, enum xran_category xran_cat) +static bool set_fh_init(void *mplane_api, struct xran_fh_init *fh_init, enum xran_category xran_cat) { memset(fh_init, 0, sizeof(*fh_init)); @@ -606,30 +643,46 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca const int nfh = sizeofArray(FHconfigs); config_getlist(config_get_if(), &FH_ConfigList, FHconfigs, nfh, aprefix); - int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs +#ifdef OAI_MPLANE + ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api; + int num_rus = ru_session_list->num_rus; + fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs + if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus)) + return false; + if (!set_fh_eaxcid_conf_mplane(&fh_init->eAxCId_conf, xran_cat, ru_session_list)) + return false; + /* 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 = ru_session_list->ru_session[0].xran_mplane.mtu; // we suppose that each RU supports the same MTU size + int num_ru_addr = (fh_init->io_cfg.one_vf_cu_plane) ? num_rus : 2*num_rus; + fh_init->p_o_ru_addr = calloc(num_ru_addr, sizeof(struct rte_ether_addr)); + AssertFatal(fh_init->p_o_ru_addr != NULL, "out of memory\n"); + for (int i = 0; i < num_rus; i++) { + struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr; + for (int j = 0; j < num_ru_addr/num_rus; j++) { + if (get_ether_addr(ru_session_list->ru_session[i].xran_mplane.ru_mac_addr, &ea[i+j]) == NULL) { + printf("could not read ethernet address '%s' for RU!\n", ru_session_list->ru_session[i].xran_mplane.ru_mac_addr); + return false; + } + } + } +#else + int num_rus = FH_ConfigList.numelt; // based on the number of fh_config sections -> number of RUs + fh_init->xran_ports = num_rus; // since we use xran as O-DU, xran_ports is set to the number of RUs if (!set_fh_io_cfg(&fh_init->io_cfg, fhip, nump, num_rus)) return false; if (!set_fh_eaxcid_conf(&fh_init->eAxCId_conf, xran_cat)) return false; - - 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; - it is 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; - - 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"); + char **ru_addrs = gpd(fhip, nump, ORAN_CONFIG_RU_ADDR)->strlistptr; for (int i = 0; i < num_ru_addr; ++i) { struct rte_ether_addr *ea = (struct rte_ether_addr *)fh_init->p_o_ru_addr; if (get_ether_addr(ru_addrs[i], &ea[i]) == NULL) { @@ -637,7 +690,14 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca return false; } } +#endif + 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; + it is necessary */ + fh_init->filePrefix = strdup(*gpd(fhip, nump, ORAN_CONFIG_FILE_PREFIX)->strptr); + fh_init->p_o_du_addr = NULL; // DPDK retreives DU MAC address within the xran library with rte_eth_macaddr_get() function fh_init->totalBfWeights = 0; // only used if id = O_RU (for emulation); C-plane extension types; section 5.4.6 of CUS spec #ifdef F_RELEASE @@ -656,7 +716,8 @@ static bool set_fh_init(struct xran_fh_init *fh_init, enum xran_category xran_ca // this is a hack int g_kbar; -static bool set_fh_prach_config(const openair0_config_t *oai0, +static bool set_fh_prach_config(void *mplane_api, + const openair0_config_t *oai0, const uint32_t max_num_ant, const paramdef_t *prachp, int nprach, @@ -692,8 +753,13 @@ static bool set_fh_prach_config(const openair0_config_t *oai0, xran assumes PRACH offset >= max(Ntx, Nrx). However, we made a workaround that xran supports PRACH eAxC IDs same as PUSCH eAxC IDs. This is achieved with is_prach and filter_id parameters in the patch. 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; + prach_config->eAxC_offset = xran_mplane->prach_offset; +#else uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; +#endif g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr; @@ -722,17 +788,24 @@ static bool set_fh_frame_config(const openair0_config_t *oai0, struct xran_frame return true; } -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) +static bool set_fh_ru_config(void *mplane_api, 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; // 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 +#ifdef OAI_MPLANE + xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api; + ru_config->iqWidth = xran_mplane->iq_width; + ru_config->iqWidth_PRACH = xran_mplane->iq_width; +#else 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; // 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"); +#endif + ru_config->compMeth = ru_config->iqWidth < 16 ? XRAN_COMPMETHOD_BLKFLOAT : XRAN_COMPMETHOD_NONE; // compression method 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; // FFT Size ru_config->byteOrder = XRAN_NE_BE_BYTE_ORDER; // order of bytes in int16_t in buffer; big or little endian @@ -757,7 +830,7 @@ static bool set_maxmin_pd(const paramdef_t *pd, int num, const char *name, uint1 return true; } -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) +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) { 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); @@ -847,14 +920,14 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, 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, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf)) + if (!set_fh_prach_config(mplane_api, 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, xran_cat, &fh_config->ru_conf)) + if (!set_fh_ru_config(mplane_api, rup, oai0->split7.fftSize, nru, xran_cat, &fh_config->ru_conf)) return false; fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder @@ -889,24 +962,35 @@ static bool set_fh_config(int ru_idx, int num_rus, enum xran_category xran_cat, return true; } -bool get_xran_config(const openair0_config_t *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config) +bool get_xran_config(void *mplane_api, const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config) { /* 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)) { + if (!set_fh_init(mplane_api, fh_init, xran_cat)) { printf("could not read FHI 7.2/ORAN config\n"); return false; } +#ifdef OAI_MPLANE + ru_session_list_t *ru_session_list = (ru_session_list_t *)mplane_api; 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, xran_cat, openair0_cfg, &fh_config[o_xu_id])) { + xran_mplane_t *xran_mplane = &ru_session_list->ru_session[o_xu_id].xran_mplane; + if (!set_fh_config(xran_mplane, o_xu_id, fh_init->xran_ports, xran_cat, openair0_cfg, &fh_config[o_xu_id])) { + MP_LOG_I("could not read FHI 7.2/RU-specific config\n"); + return false; + } + } +#else + for (int32_t o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) { + if (!set_fh_config(NULL, 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; } } +#endif return true; } diff --git a/radio/fhi_72/oran-config.h b/radio/fhi_72/oran-config.h index c5a086638f..bbe934e757 100644 --- a/radio/fhi_72/oran-config.h +++ b/radio/fhi_72/oran-config.h @@ -29,7 +29,7 @@ struct xran_fh_init; struct xran_fh_config; struct openair0_config; -bool get_xran_config(const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config); +bool get_xran_config(void *mplane_api, const struct openair0_config *openair0_cfg, struct xran_fh_init *fh_init, struct xran_fh_config *fh_config); void print_fh_init(const struct xran_fh_init *fh_init); void print_fh_config(const struct xran_fh_config *fh_config); diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index a5e2d5baf7..3a63045817 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -344,8 +344,11 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d } eth->mplane_priv = (void *)&ru_session_list; + + success = get_xran_config((void *)&ru_session_list, openair0_cfg, &fh_init, fh_config); + AssertFatal(success, "[MPLANE] Cannot configure xran with M-plane info.\n"); #else - success = get_xran_config(openair0_cfg, &fh_init, fh_config); + success = get_xran_config(NULL, openair0_cfg, &fh_init, fh_config); AssertFatal(success, "cannot get configuration for xran\n"); #endif