X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=fhi_lib%2Flib%2Fsrc%2Fxran_cp_api.c;fp=fhi_lib%2Flib%2Fsrc%2Fxran_cp_api.c;h=d42b22b457226f77d03ad93964d8dfe1686305c6;hp=0000000000000000000000000000000000000000;hb=4745e5c88ba931c6d71cb6d8c681f76cf364eac5;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925 diff --git a/fhi_lib/lib/src/xran_cp_api.c b/fhi_lib/lib/src/xran_cp_api.c new file mode 100644 index 0000000..d42b22b --- /dev/null +++ b/fhi_lib/lib/src/xran_cp_api.c @@ -0,0 +1,1086 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +* +* 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. +* +*******************************************************************************/ + + +/** + * @brief This file provides the API functions to build Control Plane Messages + * for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01. + * + * @file xran_cp_api.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include + +#include "xran_common.h" +#include "xran_transport.h" +#include "xran_cp_api.h" +#include "xran_hash.h" +#include "xran_printf.h" + + +struct xran_sectioninfo_db { + uint32_t max_num; + uint32_t cur_index; +#if defined(XRAN_CP_USES_HASHTABLE) + struct rte_hash *hash; +#endif + struct xran_section_info *list; + }; + + +static struct xran_sectioninfo_db *sectiondb[XRAN_DIR_MAX]; + +int xran_cp_init_sectiondb(void *pHandle) +{ + int i, j, k; + uint32_t size; + uint16_t cid; + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + for(i=0; i < XRAN_DIR_MAX; i++) { + size = (xran_get_num_cc(pHandle) * num_eAxc * sizeof(struct xran_sectioninfo_db)); + print_log("Allocation Size for Section DB : %d (%dx%dx%ld)", size + , xran_get_num_cc(pHandle) + , num_eAxc + , sizeof(struct xran_sectioninfo_db)); + sectiondb[i] = malloc(size); + + if(sectiondb[i] == NULL) { + print_err("Allocation Failed for Section DB!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + for(j=0; j < xran_get_num_cc(pHandle); j++) { // CC + for(k=0; k < num_eAxc; k++) { // antenna + ptr = sectiondb[i] + num_eAxc*j + k; + + ptr->max_num = xran_get_max_sections(pHandle); + ptr->cur_index = 0; + + // allicate array to store section information + size = sizeof(struct xran_section_info)*xran_get_max_sections(pHandle); + print_log("Allocation Size for list : %d (%ldx%d)", size, + sizeof(struct xran_section_info), + xran_get_max_sections(pHandle)); + ptr->list = malloc(size); + if(ptr-> list == NULL) { + print_err("Allocation Failed for Section DB!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + +#if defined(XRAN_CP_USES_HASHTABLE) + // Create hash table for section information + cid = rte_be_to_cpu_16(xran_compose_cid(xran_get_llscuid(pHandle), xran_get_sectorid(pHandle), j, k)); + print_log("Creating hash for %04X", cid); + ptr->hash = xran_section_init_hash(i, cid, xran_get_max_sections(pHandle)); +#endif + } + } + } + + return (XRAN_ERRCODE_OK); +} + +int xran_cp_free_sectiondb(void *pHandle) +{ + int i, j, k; + uint32_t size; + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + for(i=0; i < XRAN_DIR_MAX; i++) { + for(j=0; j < xran_get_num_cc(pHandle); j++) { // CC + for(k=0; k < num_eAxc; k++) { // antenna + ptr = sectiondb[i] + num_eAxc*j + k; + +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_free_hash(ptr->hash); +#endif + if(ptr->list != NULL) + free(ptr->list); + else print_err("list is NULL"); + } + } + if(sectiondb[i] != NULL) + free(sectiondb[i]); + else print_err("sectiondb[%d] is NULL", i); + } + + return (XRAN_ERRCODE_OK); +} + +static struct xran_sectioninfo_db *xran_get_section_db(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + + if(unlikely(dir>=XRAN_DIR_MAX)) { + print_err("Invalid direction - %d", dir); + return (NULL); + } + + if(unlikely(cc_id >= xran_get_num_cc(pHandle))) { + print_err("Invalid CC id - %d", cc_id); + return (NULL); + } + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + if(unlikely(ruport_id >= num_eAxc)) { + print_err("Invalid eAxC id - %d", ruport_id); + return (NULL); + } + + ptr = sectiondb[dir] + xran_get_num_eAxc(pHandle)*cc_id + ruport_id; + + return(ptr); +} + +static struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index) +{ + if(unlikely(ptr == NULL)) + return (NULL); + + if(unlikely(ptr->max_num < index)) { + print_err("Index is out of range - %d", index); + return (NULL); + } + + return(&(ptr->list[index])); +} + +int xran_cp_add_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + struct xran_section_info *info) +{ + struct xran_sectioninfo_db *ptr; + struct xran_section_info *list; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(ptr->cur_index >= ptr->max_num)) { + print_err("No more space to add section information!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + list = xran_get_section_info(ptr, ptr->cur_index); + + rte_memcpy(list, info, sizeof(struct xran_section_info)); +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_add_hash(ptr->hash, info->id, ptr->cur_index); +#endif + + ptr->cur_index++; + + return (XRAN_ERRCODE_OK); +} + +int xran_cp_add_multisection_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + uint8_t num_sections, struct xran_section_gen_info *gen_info) +{ + int i; + struct xran_sectioninfo_db *ptr; + struct xran_section_info *list; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(ptr->cur_index >= (ptr->max_num+num_sections))) { + print_err("No more space to add section information!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + list = xran_get_section_info(ptr, ptr->cur_index); + + for(i=0; ihash, gen_info[i].info.id, ptr->cur_index); +#endif + ptr->cur_index++; + } + + return (XRAN_ERRCODE_OK); +} + +struct xran_section_info *xran_cp_find_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + uint16_t section_id) +{ + int index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (NULL); + +#if defined(XRAN_CP_USES_HASHTABLE) + index = xran_section_lookup(ptr->hash, section_id); + if(unlikely(index > ptr->max_num)) { + print_err("Invalid index - %d", index); + return (NULL); + } + + if(index < 0) { + print_dbg("No section ID in the list - %d", section_id); + return (NULL); + } + + return (xran_get_section_info(ptr, index)); +#else + for(index=0; indexcur_index; index++) { + if(ptr->list[index].id == section_id) { + print_dbg("Found section info %04X", section_id); + return (xran_get_section_info(ptr, index)); + } + } + + print_dbg("No section ID in the list - %d", section_id); + return (NULL); +#endif + +} + +struct xran_section_info *xran_cp_iterate_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, uint32_t *next) +{ + int index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (NULL); + +#if defined(XRAN_CP_USES_HASHTABLE) + index = xran_section_iterate(ptr->hash, next); + if(unlikely(index > ptr->max_num)) { + print_err("Invalid index - %d", index); + return (NULL); + } + + if(index < 0) { + print_dbg("No section ID in the list - %d", section_id); + return (NULL); + } + + return (xran_get_section_info(ptr, index)); +#else + index = *next; + if(*next < ptr->cur_index) { + (*next)++; + return (xran_get_section_info(ptr, index)); + } + else + print_dbg("No more sections in the list"); + + return (NULL); +#endif +} + +int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + int i, index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (-1); + + return (ptr->cur_index); +} + +int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + struct xran_sectioninfo_db *ptr; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + ptr->cur_index = 0; +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_reset_hash(ptr->hash); +#endif + + return (XRAN_ERRCODE_OK); +} + +int xran_dump_sectiondb(void) +{ + // TODO: + return (0); +} + + +// Cyclic Prefix Length 5.4.4.14 +// CP_length = cpLength * Ts * 2^u, Ts = 1/30.72MHz, if u is N/A, it shall be zero +#define CPLEN_TS (30720000) +inline uint16_t xran_get_cplength(int cpLength, int uval) // uval = -1 for N/A +{ + return ((cpLength * ((uval<0)?0:(2<>1); +} + + +/** + * @brief Fill the section body of type 0 in C-Plane packet + * + * @param section + * A pointer to the section in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section0( + struct xran_cp_radioapp_section0 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s0.reMask = params->info.reMask; + section->hdr.u.s0.numSymbol = params->info.numSymbol; + section->hdr.u.s0.reserved = 0; + + // for network byte order + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 0 in C-Plane packet + * + * @param s0hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section0_hdr( + struct xran_cp_radioapp_section0_header *s0hdr, + struct xran_cp_gen_params *params) + +{ + s0hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset); + s0hdr->frameStructure.fftSize = params->hdr.fftSize; + s0hdr->frameStructure.uScs = params->hdr.scs; + s0hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength); + s0hdr->reserved = 0; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief Fill the section body of type 1 in C-Plane packet + * Extension is not supported. + * + * @param section + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section1( + struct xran_cp_radioapp_section1 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s1.reMask = params->info.reMask; + section->hdr.u.s1.numSymbol = params->info.numSymbol; + section->hdr.u.s1.beamId = params->info.beamId; + + if(params->info.ef) { + // TODO: need to handle extension + print_err("Extension is not supported!"); + section->hdr.u.s1.ef = 0; +// section->hdr.u.s1.ef = params->info.ef; + } + else + section->hdr.u.s1.ef = 0; + + // for network byte order + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 1 in C-Plane packet + * + * @param s1hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section1_hdr( + struct xran_cp_radioapp_section1_header *s1hdr, + struct xran_cp_gen_params *params) +{ + s1hdr->udComp.udIqWidth = params->hdr.iqWidth; + s1hdr->udComp.udCompMeth = params->hdr.compMeth; + s1hdr->reserved = 0; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief Fill the section body of type 3 in C-Plane packet + * Extension is not supported. + * + * @param section + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section3( + struct xran_cp_radioapp_section3 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s3.reMask = params->info.reMask; + section->hdr.u.s3.numSymbol = params->info.numSymbol; + section->hdr.u.s3.beamId = params->info.beamId; + + section->freqOffset = rte_cpu_to_be_32(params->info.freqOffset)>>8; + section->reserved = 0; + + if(params->info.ef) { + // TODO: need to handle extension + print_err("Extension is not supported!"); + section->hdr.u.s3.ef = 0; +// section->hdr.u.s3.ef = params->info.ef; + } + else + section->hdr.u.s3.ef = 0; + + // for network byte order (header, 8 bytes) + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 3 in C-Plane packet + * + * @param s3hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section3_hdr( + struct xran_cp_radioapp_section3_header *s3hdr, + struct xran_cp_gen_params *params) + +{ + s3hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset); + s3hdr->frameStructure.fftSize = params->hdr.fftSize; + s3hdr->frameStructure.uScs = params->hdr.scs; + s3hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength); + s3hdr->udComp.udIqWidth = params->hdr.iqWidth; + s3hdr->udComp.udCompMeth = params->hdr.compMeth; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief add sections to C-Plane packet + * Section type 1 and 3 are supported. + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params) +{ + int i, ret; + uint32_t totalen; + void *section; + int section_size; + int (*xran_prepare_section_func)(void *section, void *params); + + + totalen = 0; + switch(params->sectionType) { + case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */ + section_size = sizeof(struct xran_cp_radioapp_section0); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section0; + break; + + case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */ + section_size = sizeof(struct xran_cp_radioapp_section1); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section1; + break; + + case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */ + section_size = sizeof(struct xran_cp_radioapp_section3); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section3; + break; + + case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */ + case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */ + case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */ + default: + section_size = 0; + xran_prepare_section_func = NULL; + print_err("Section Type %d is not supported!", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(xran_prepare_section_func == NULL)) { + print_err("Section Type %d is not supported!", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + for(i=0; inumSections; i++) { + section = rte_pktmbuf_append(mbuf, section_size); + if(section == NULL) { + print_err("Fail to allocate the space for section[%d]!", i); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + if(unlikely(xran_prepare_section_func((void *)section, + (void *)¶ms->sections[i]) < 0)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + totalen += section_size; + } + + return (totalen); +} + +/** + * @brief fill the information of a radio application header in a C-Plane packet + * + * @param apphdr + * A pointer to the application header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static inline int xran_prepare_radioapp_common_header( + struct xran_cp_radioapp_common_header *apphdr, + struct xran_cp_gen_params *params) +{ + +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) { + print_err("Invalid direction!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) { + print_err("Invalid Slot ID!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid Symbol ID!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + apphdr->dataDirection = params->dir; + apphdr->payloadVer = XRAN_PAYLOAD_VER; + apphdr->filterIndex = params->hdr.filterIdx; + apphdr->frameId = params->hdr.frameId; + apphdr->subframeId = params->hdr.subframeId; + apphdr->slotId = params->hdr.slotId; + apphdr->startSymbolId = params->hdr.startSymId; + apphdr->numOfSections = params->numSections; + apphdr->sectionType = params->sectionType; + + // radio app header has common parts of 4bytes for all section types + *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr)); + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief add a radio application header in a C-Plane packet + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params) +{ + int ret; + uint32_t totalen; + struct xran_cp_radioapp_common_header *apphdr; + int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params); + + +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) { + print_err("Invalid Section Type - %d", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + switch(params->sectionType) { + case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr; + totalen = sizeof(struct xran_cp_radioapp_section0_header); + break; + + case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr; + totalen = sizeof(struct xran_cp_radioapp_section1_header); + break; + + case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr; + totalen = sizeof(struct xran_cp_radioapp_section3_header); + break; + + case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported + case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported + case XRAN_CP_SECTIONTYPE_7: // LAA, not supported + default: + print_err("Section Type %d is not supported!", params->sectionType); + xran_prepare_radioapp_section_hdr_func = NULL; + totalen = 0; + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen); + if(unlikely(apphdr == NULL)) { + print_err("Fail to reserve the space for radio application header!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + ret = xran_prepare_radioapp_common_header(apphdr, params); + if(unlikely(ret < 0)) { + return (ret); + } + + if(likely(xran_prepare_radioapp_section_hdr_func)) { + xran_prepare_radioapp_section_hdr_func(apphdr, params); + } + else { + print_err("xran_prepare_radioapp_section_hdr_func is NULL!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + return (totalen); +} + +/** + * @brief Create a C-Plane packet + * Transport layer fragmentation is not supported. + * + * @ingroup xran_cp_pkt + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @param CC_ID + * Component Carrier ID for this C-Plane message + * @param Ant_ID + * Antenna ID(RU Port ID) for this C-Plane message + * @param seq_id + * Sequence ID for this C-Plane message + * @return + * 0 on success; non zero on failure + */ +int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf, + struct xran_cp_gen_params *params, + uint8_t CC_ID, uint8_t Ant_ID, + uint8_t seq_id) +{ + int ret; + uint32_t payloadlen; + struct xran_ecpri_hdr *ecpri_hdr; + + + ecpri_hdr = (struct xran_ecpri_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr)); + if(unlikely(ecpri_hdr == NULL)) { + print_err("Fail to allocate the space for eCPRI hedaer!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER; + ecpri_hdr->ecpri_resv = 0; // should be zero + ecpri_hdr->ecpri_concat = 0; + ecpri_hdr->ecpri_mesg_type = ECPRI_RT_CONTROL_DATA; + ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID); + ecpri_hdr->ecpri_seq_id.seq_id = seq_id; + + /* TODO: Transport layer fragmentation is not supported */ + ecpri_hdr->ecpri_seq_id.sub_seq_id = 0; + ecpri_hdr->ecpri_seq_id.e_bit = 1; + + payloadlen = 0; + + ret = xran_append_radioapp_header(mbuf, params); + if(ret < 0) { + return (ret); + } + payloadlen += ret; + + ret = xran_append_control_section(mbuf, params); + if(ret < 0) { + return (ret); + } + payloadlen += ret; + +// printf("Total Payload length = %d\n", payloadlen); + ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(payloadlen); + + return (XRAN_ERRCODE_OK); +} + +/////////////////////////////////////// +// for Debug +int xran_parse_cp_pkt(struct rte_mbuf *mbuf, struct xran_cp_gen_params *result) +{ + struct xran_ecpri_hdr *ecpri_hdr; + struct xran_cp_radioapp_common_header *apphdr; + int i, ret; + int extlen; + + + ret = 0; + ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *); + if(ecpri_hdr == NULL) { + print_err("Invalid packet - eCPRI hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + /* Process eCPRI header. */ + if(ecpri_hdr->ecpri_ver != XRAN_ECPRI_VER) { + print_err("Invalid eCPRI version - %d", ecpri_hdr->ecpri_ver); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(ecpri_hdr->ecpri_resv != 0) { + print_err("Invalid reserved field - %d", ecpri_hdr->ecpri_resv); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(ecpri_hdr->ecpri_mesg_type != ECPRI_RT_CONTROL_DATA) { + print_err("Not C-Plane Message - %d", ecpri_hdr->ecpri_mesg_type); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } +#if 0 + printf("[CPlane] [%04X:%03d-%3d-%d] len=%5d\n", + rte_be_to_cpu_16(ecpri_hdr->ecpri_xtc_id), + ecpri_hdr->ecpri_seq_id.seq_id, ecpri_hdr->ecpri_seq_id.sub_seq_id, + ecpri_hdr->ecpri_seq_id.e_bit, + rte_be_to_cpu_16(ecpri_hdr->ecpri_payl_size)); +#endif + + /* Process radio header. */ + apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr)); + if(apphdr == NULL) { + print_err("Invalid packet - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr)); + + if(apphdr->payloadVer != XRAN_PAYLOAD_VER) { + print_err("Invalid Payload version - %d", apphdr->payloadVer); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + result->dir = apphdr->dataDirection; + result->hdr.filterIdx = apphdr->filterIndex; + result->hdr.frameId = apphdr->frameId; + result->hdr.subframeId = apphdr->subframeId; + result->hdr.slotId = apphdr->slotId; + result->hdr.startSymId = apphdr->startSymbolId; + result->sectionType = apphdr->sectionType; + result->numSections = apphdr->numOfSections; + + switch(apphdr->sectionType) { + case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted + { + struct xran_cp_radioapp_section0_header *hdr; + struct xran_cp_radioapp_section0 *section; + + hdr = (struct xran_cp_radioapp_section0_header*)apphdr; + + result->hdr.fftSize = rte_be_to_cpu_16(hdr->timeOffset); + result->hdr.scs = hdr->frameStructure.fftSize; + result->hdr.timeOffset = hdr->frameStructure.uScs; + result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength); + //hdr->reserved; /* should be zero */ + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header)); + if(section == NULL) { + print_err("Invalid packet 0 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s0.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s0.reMask; + //section->hdr.u.s0.reserved; /* should be zero */ + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0)); + if(section == NULL) { + print_err("Invalid packet 0 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels + { + struct xran_cp_radioapp_section1_header *hdr; + struct xran_cp_radioapp_section1 *section; + + hdr = (struct xran_cp_radioapp_section1_header*)apphdr; + + result->hdr.iqWidth = hdr->udComp.udIqWidth; + result->hdr.compMeth = hdr->udComp.udCompMeth; + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header)); + if(section == NULL) { + print_err("Invalid packet 1 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s1.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s1.reMask; + result->sections[i].info.beamId = section->hdr.u.s1.beamId; + result->sections[i].info.ef = section->hdr.u.s1.ef; + + if(section->hdr.u.s1.ef) { + // TODO: handle section extension + extlen = 0; + } + else extlen = 0; + + section = (void *)rte_pktmbuf_adj(mbuf, + sizeof(struct xran_cp_radioapp_section1)+extlen); + if(section == NULL) { + print_err("Invalid packet 1 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels + { + struct xran_cp_radioapp_section3_header *hdr; + struct xran_cp_radioapp_section3 *section; + + hdr = (struct xran_cp_radioapp_section3_header*)apphdr; + + result->hdr.timeOffset = rte_be_to_cpu_16(hdr->timeOffset); + result->hdr.scs = hdr->frameStructure.uScs; + result->hdr.fftSize = hdr->frameStructure.fftSize; + result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength); + result->hdr.iqWidth = hdr->udComp.udIqWidth; + result->hdr.compMeth = hdr->udComp.udCompMeth; + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header)); + if(section == NULL) { + print_err("Invalid packet 3 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s3.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s3.reMask; + result->sections[i].info.beamId = section->hdr.u.s3.beamId; + result->sections[i].info.ef = section->hdr.u.s3.ef; + result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8; + + if(section->reserved) { + print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(section->hdr.u.s3.ef) { + // TODO: handle section extension + extlen = 0; + } + else extlen = 0; + + section = (void *)rte_pktmbuf_adj(mbuf, + sizeof(struct xran_cp_radioapp_section3)+extlen); + if(section == NULL) { + print_err("Invalid packet 3 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported + case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported + case XRAN_CP_SECTIONTYPE_7: // LAA, not supported + default: + ret = -XRAN_ERRCODE_INVALIDPARAM; + print_err("Non-supported Section Type - %d", apphdr->sectionType); + } + +#if 0 + printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n", + result->dir?"DL":"UL", + result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId, + result->sectionType, result->numSections, + result->hdr.startSymId, + result->hdr.filterIdx, + result->hdr.iqWidth, result->hdr.compMeth); + + for(i=0; inumSections; i++) { + printf(" >> %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02X numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n", + i, result->sections[i].info.id, + result->sections[i].info.rb, + result->sections[i].info.symInc, result->sections[i].info.numSymbol, + result->sections[i].info.startPrbc, result->sections[i].info.numPrbc, + result->sections[i].info.reMask, + result->sections[i].info.beamId, + result->sections[i].info.freqOffset, + result->sections[i].info.ef); +// result->sections[i].info.type + } +#endif + + return(ret); +} +