-/******************************************************************************
-*
-* 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 <rte_branch_prediction.h>
-
-#include "xran_common.h"
-#include "xran_transport.h"
-#include "xran_cp_api.h"
-#include "xran_printf.h"
-
-
-/**
- * This structure to store the section information of C-Plane
- * in order to generate and parse corresponding U-Plane */
-struct xran_sectioninfo_db {
- uint32_t cur_index; /**< Current index to store fro this eAXC */
- struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /**< The array of section information */
- };
-
-static struct xran_sectioninfo_db sectiondb[XRAN_MAX_SECTIONDB_CTX][XRAN_DIR_MAX][XRAN_COMPONENT_CARRIERS_MAX][XRAN_MAX_ANTENNA_NR*2];
-
-
-/**
- * @brief Initialize section database.
- * Allocate required memory space to store section information.
- * Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.
- * Total entry size : number of CC * number of antenna * max number of sections * 2(direction)
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @return
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area
- */
-int xran_cp_init_sectiondb(void *pHandle)
-{
- int ctx, dir, cc, ant;
-
- for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)
- for(dir=0; dir < XRAN_DIR_MAX; dir++)
- for(cc=0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)
- for(ant=0; ant < XRAN_MAX_ANTENNA_NR*2; ant++)
- sectiondb[ctx][dir][cc][ant].cur_index = 0;
-
- return (XRAN_STATUS_SUCCESS);
-}
-
-/**
- * @brief Release and free section database
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @return
- * XRAN_STATUS_SUCCESS on success
- */
-int xran_cp_free_sectiondb(void *pHandle)
-{
- return (XRAN_STATUS_SUCCESS);
-}
-
-static inline struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,
- uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
-{
- struct xran_sectioninfo_db *ptr;
-
-
- if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {
- print_err("Invalid Context id - %d", ctx_id);
- return (NULL);
- }
-
- if(unlikely(dir >= XRAN_DIR_MAX)) {
- print_err("Invalid direction - %d", dir);
- return (NULL);
- }
-
- if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {
- print_err("Invalid CC id - %d", cc_id);
- return (NULL);
- }
-
- if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2)) {
- print_err("Invalid eAxC id - %d", ruport_id);
- return (NULL);
- }
-
- ptr = §iondb[ctx_id][dir][cc_id][ruport_id];
-
- return(ptr);
-}
-
-static inline struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
-{
- if(unlikely(ptr == NULL))
- return (NULL);
-
- if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {
- print_err("Index is out of range - %d", index);
- return (NULL);
- }
-
- return(&(ptr->list[index]));
-}
-
-/**
- * @brief Add a section information of C-Plane to dabase.
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @param dir
- * Direction of C-Plane message for the section to store
- * @param cc_id
- * CC ID of C-Plane message for the section to store
- * @param ruport_id
- * RU port ID of C-Plane message for the section to store
- * @param ctx_id
- * Context index for the section database
- * @param info
- * The information of this section to store
- * @return
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect
- * XRAN_STATUS_RESOURCE, if no more space to add on database
- */
-int xran_cp_add_section_info(void *pHandle,
- uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_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, ctx_id);
- if(unlikely(ptr == NULL)) {
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {
- print_err("No more space to add section information!");
- return (XRAN_STATUS_RESOURCE);
- }
-
- list = xran_get_section_info(ptr, ptr->cur_index);
-
- rte_memcpy(list, info, sizeof(struct xran_section_info));
-
- ptr->cur_index++;
-
- return (XRAN_STATUS_SUCCESS);
-}
-
-int xran_cp_add_multisection_info(void *pHandle,
- uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
- struct xran_cp_gen_params *gen_info)
-{
- int i;
- uint8_t dir, num_sections;
- struct xran_sectioninfo_db *ptr;
- struct xran_section_info *list;
-
-
- dir = gen_info->dir;
- num_sections = gen_info->numSections;
-
- ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
- if(unlikely(ptr == NULL)) {
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {
- print_err("No more space to add section information!");
- return (XRAN_STATUS_RESOURCE);
- }
-
- list = xran_get_section_info(ptr, ptr->cur_index);
-
- for(i=0; i<num_sections; i++) {
- rte_memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));
- ptr->cur_index++;
- }
-
- return (XRAN_STATUS_SUCCESS);
-}
-
-/**
- * @brief Find a section information of C-Plane from dabase
- * by given information
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @param dir
- * The direction of the section to find
- * @param cc_id
- * The CC ID of the section to find
- * @param ruport_id
- * RU port ID of the section to find
- * @param ctx_id
- * Context index for the section database
- * @param section_id
- * The ID of section to find
- * @return
- * The pointer of section information if matched section is found
- * NULL if failed to find matched section
- */
-struct xran_section_info *xran_cp_find_section_info(void *pHandle,
- uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
- uint8_t ctx_id, uint16_t section_id)
-{
- int index, num_index;
- struct xran_sectioninfo_db *ptr;
-
-
- ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
- if(unlikely(ptr == NULL))
- return (NULL);
-
- if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)
- num_index = XRAN_MAX_NUM_SECTIONS;
- else
- num_index = ptr->cur_index;
-
- for(index=0; index < num_index; index++) {
- if(ptr->list[index].id == section_id) {
- return (xran_get_section_info(ptr, index));
- }
- }
-
- print_dbg("No section ID in the list - %d", section_id);
- return (NULL);
-}
-
-/**
- * @brief Iterate each section information of C-Plane
- * from the database of eAxC by given information
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @param dir
- * The direction of the section to find
- * @param cc_id
- * The CC ID of the section to find
- * @param ruport_id
- * RU port ID of the section to find
- * @param ctx_id
- * Context index for the section database
- * @param next
- * The pointer to store the position of next entry
- * @return
- * The pointer of section information in the list
- * NULL if reached at the end of the list
- */
-struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,
- uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
- uint8_t ctx_id, uint32_t *next)
-{
- int index;
- struct xran_sectioninfo_db *ptr;
-
-
- ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
- if(unlikely(ptr == NULL))
- return (NULL);
-
- 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);
- }
-}
-
-/**
- * @brief Get the size of stored entries
- * for the database of eAxC by given information
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @param dir
- * The direction of the section to find
- * @param cc_id
- * The CC ID of the section to find
- * @param ruport_id
- * RU port ID of the section to find
- * @param ctx_id
- * Context index for the section database
- * @return
- * The size of stored entries
- * -1 if failed to find matched database
- */
-int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
-{
- int i, index;
- struct xran_sectioninfo_db *ptr;
-
-
- ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
- if(unlikely(ptr == NULL))
- return (-1);
-
- return (ptr->cur_index);
-}
-
-/**
- * @brief Reset a database of eAxC by given information
- *
- * @ingroup xran_cp_pkt
- *
- * @param pHandle
- * handle for xRAN interface, currently not being used
- * @param dir
- * The direction of the section to find
- * @param cc_id
- * The CC ID of the section to find
- * @param ruport_id
- * RU port ID of the section to find
- * @param ctx_id
- * Context index for the section database
- * @return
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if failed to find matched database
- */
-int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
-{
- struct xran_sectioninfo_db *ptr;
-
- ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
- if(unlikely(ptr == NULL)) {
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- ptr->cur_index = 0;
-
- return (XRAN_STATUS_SUCCESS);
-}
-
-
-int xran_dump_sectiondb(void)
-{
- // TODO:
- return (0);
-}
-
-// Cyclic Prefix Length 5.4.4.14
-// CP_length = cpLength * Ts, Ts = 1/30.72MHz
-// i.e cpLength = CP_length / Ts ?
-#define CPLEN_TS (30720000)
-inline uint16_t xran_get_cplength(int CP_length)
-{
- return (CP_length);
-}
-
-// Frequency offset 5.4.5.11
-// frequency_offset = freqOffset * SCS * 0.5
-// i.e freqOffset = (frequency_offset *2 )/ SCS ?
-inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)
-{
- return (freqOffset);
-}
-
-
-static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,
- struct xran_sectionext1_info *params, int last_flag)
-{
- struct xran_cp_radioapp_section_ext1 *ext1;
- uint8_t *data;
- int parm_size, iq_size;
- int total_len;
- static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };
-
-
- total_len = 0;
-
- parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
- ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);
- if(ext1 == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
-
- total_len += parm_size;
-
- ext1->extType = XRAN_CP_SECTIONEXTCMD_1;
- ext1->ef = last_flag;
- ext1->bfwCompMeth = params->bfwCompMeth;
- ext1->bfwIqWidth = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);
-
- switch(params->bfwCompMeth) {
- case XRAN_BFWCOMPMETHOD_BLKFLOAT:
- parm_size = 1;
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- total_len += parm_size;
- *data = (params->bfwCompParam.exponent & 0x0f);
- break;
-
- case XRAN_BFWCOMPMETHOD_BLKSCALE:
- parm_size = 1;
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- total_len += parm_size;
- *data = params->bfwCompParam.blockScaler;
- break;
-
- case XRAN_BFWCOMPMETHOD_ULAW:
- parm_size = 1;
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- total_len += parm_size;
- *data = params->bfwCompParam.compBitWidthShift;
- break;
-
- case XRAN_BFWCOMPMETHOD_BEAMSPACE:
-#if 0
- parm_size = ceil(params->bfwNumber/8)*8;
-#else
- parm_size = params->bfwNumber>>3;
- if(params->bfwNumber%8) parm_size++;
- parm_size *= 8;
-#endif
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
- total_len += parm_size;
- break;
-
- case XRAN_BFWCOMPMETHOD_NONE:
- default:
- parm_size = 0;
- }
-
- iq_size = params->bfwNumber * params->bfwiqWidth * 2;
-#if 0
- parm_size = ceil(iq_size/8);
-#else
- parm_size = iq_size>>3;
- if(iq_size%8) parm_size++;
-#endif
-
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- rte_memcpy(data, params->bfwIQ, parm_size);
-
- total_len += parm_size;
- parm_size = total_len % XRAN_SECTIONEXT_ALIGN;
- if(parm_size) {
- parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 1");
- return (XRAN_STATUS_RESOURCE);
- }
- rte_memcpy(data, zeropad, parm_size);
- total_len += parm_size;
- }
-
- ext1->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
-
- return (total_len);
-}
-
-static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,
- struct xran_sectionext2_info *params, int last_flag)
-{
- struct xran_cp_radioapp_section_ext2 *ext2;
- uint8_t *data;
- int total_len;
- int parm_size;
- uint32_t val, shift_val;
- int val_size;
-
-
- total_len = 0;
-
- parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
- ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
- if(ext2 == NULL) {
- print_err("Fail to allocate the space for section extension 2");
- return (XRAN_STATUS_RESOURCE);
- }
- total_len += parm_size;
-
- ext2->extType = XRAN_CP_SECTIONEXTCMD_2;
- ext2->ef = last_flag;
- ext2->bfZe3ddWidth = params->bfZe3ddWidth;
- ext2->bfAz3ddWidth = params->bfAz3ddWidth;
- ext2->bfZePtWidth = params->bfZePtWidth;
- ext2->bfAzPtWidth = params->bfAzPtWidth;
- ext2->bfaCompResv0 = 0;
- ext2->bfaCompResv1 = 0;
-
- val = 0;
- shift_val = 0;
- if(params->bfAzPtWidth) {
- val += params->bfAzPt;
- shift_val += 8 - (params->bfAzPtWidth+1);
- }
- else
- shift_val += 8;
-
- if(params->bfZePtWidth) {
- val = val << (params->bfZePtWidth+1);
- val += params->bfZePt;
- shift_val += 8 - (params->bfZePtWidth+1);
- }
- else
- shift_val += 8;
-
- if(params->bfAz3ddWidth) {
- val = val << (params->bfAz3ddWidth+1);
- val += params->bfAz3dd;
- shift_val += 8 - (params->bfAz3ddWidth+1);
- }
- else
- shift_val += 8;
-
- if(params->bfZe3ddWidth) {
- val = val << (params->bfZe3ddWidth+1);
- val += params->bfZe3dd;
- shift_val += 8 - (params->bfZe3ddWidth+1);
- }
- else
- shift_val += 8;
-
- if(val) {
- val = val << shift_val;
- val = rte_cpu_to_be_32(val);
- }
-
- val_size = 4 - (shift_val/8); /* ceil(total bit/8) */
- parm_size = val_size + 1; /* additional 1 byte for bfxxSI */
-
- data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
- if(data == NULL) {
- print_err("Fail to allocate the space for section extension 2");
- return (XRAN_STATUS_RESOURCE);
- }
- total_len += parm_size;
-
- rte_memcpy(data, &val, val_size);
- data += val_size;
- *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
-
- ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
- *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
-
- return (total_len);
-}
-
-static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
- struct xran_sectionext4_info *params, int last_flag)
-{
- struct xran_cp_radioapp_section_ext4 *ext4;
- int parm_size;
- int total_len;
- int ret;
-
-
- total_len = 0;
-
- parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
- ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
- if(ext4 == NULL) {
- print_err("Fail to allocate the space for section extension 4");
- return(XRAN_STATUS_RESOURCE);
- }
- else {
- total_len += parm_size;
-
- ext4->extType = XRAN_CP_SECTIONEXTCMD_4;
- ext4->ef = last_flag;
- ext4->modCompScaler = params->modCompScaler;
- ext4->csf = params->csf?1:0;
- ext4->extLen = 1;
-
- *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
- }
-
- return (total_len);
-}
-
-static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
- struct xran_sectionext5_info *params, int last_flag)
-{
- struct xran_cp_radioapp_section_ext5_1 *ext5_1;
- struct xran_cp_radioapp_section_ext5_2 *ext5_2;
- int parm_size;
- int total_len;
- uint32_t *data;
-
-
- total_len = 0;
-
- if(params->num_sets == 1) {
- parm_size = sizeof(struct xran_cp_radioapp_section_ext5_1);
- ext5_1 = (struct xran_cp_radioapp_section_ext5_1 *)rte_pktmbuf_append(mbuf, parm_size);
- if(ext5_1 == NULL) {
- print_err("Fail to allocate the space for section extension 5-1");
- return (XRAN_STATUS_RESOURCE);
- }
- else {
- total_len += parm_size;
-
- ext5_1->extType = XRAN_CP_SECTIONEXTCMD_5;
- ext5_1->ef = last_flag;
-
- ext5_1->mcScaleOffset = params->mc[0].mcScaleOffset;
- ext5_1->csf = params->mc[0].csf;
- ext5_1->mcScaleReMask = params->mc[0].mcScaleReMask;
- ext5_1->reserved = 0;
-
- ext5_1->extLen = 2;
-
- *(uint64_t *)ext5_1 = rte_cpu_to_be_64(*(uint64_t *)ext5_1);
- }
- }
- else if(params->num_sets == 2) {
- parm_size = sizeof(struct xran_cp_radioapp_section_ext5_2);
- ext5_2 = (struct xran_cp_radioapp_section_ext5_2 *)rte_pktmbuf_append(mbuf, parm_size);
- if(ext5_2 == NULL) {
- print_err("Fail to allocate the space for section extension 5-2");
- return (XRAN_STATUS_RESOURCE);
- }
- else {
- total_len += parm_size;
-
- ext5_2->extType = XRAN_CP_SECTIONEXTCMD_5;
- ext5_2->ef = last_flag;
-
- ext5_2->mcScaleOffset1 = params->mc[0].mcScaleOffset;
- ext5_2->csf1 = params->mc[0].csf;
- ext5_2->mcScaleReMask1 = params->mc[0].mcScaleReMask;
- ext5_2->mcScaleOffset2 = params->mc[1].mcScaleOffset;
- ext5_2->csf2 = params->mc[1].csf;
- ext5_2->mcScaleReMask2 = params->mc[1].mcScaleReMask;
-
- ext5_2->reserved0 = 0;
- ext5_2->reserved1 = 0;
-
- ext5_2->extLen = 3;
-
- *(uint64_t *)ext5_2 = rte_cpu_to_be_64(*(uint64_t *)ext5_2);
- data = (uint32_t *)((uint8_t *)ext5_2 + 8);
- *data = rte_cpu_to_be_32(*data);
- }
- }
- else {
- print_err("Invalid number of scalar values - %d", params->num_sets);
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- return (total_len);
-}
-
-/**
- * @brief add section extension to 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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM
- * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
- */
-int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
-{
- int i, ret;
- uint32_t totalen;
- int last_flag;
- int ext_size;
-
-
- if(unlikely(params->exDataSize >= XRAN_MAX_NUM_EXTENSIONS)) {
- print_err("Invalid total number of extensions - %d", params->exDataSize);
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- totalen = 0;
-
-
- ret = XRAN_STATUS_SUCCESS;
-
- for(i=0; i < params->exDataSize; i++) {
- if(params->exData[i].data == NULL) {
- print_err("Invalid parameter - extension data %d is NULL", i);
- ret = XRAN_STATUS_INVALID_PARAM;
- continue;
- }
-
-// params->exData[].len
- last_flag = ((params->exDataSize - i)==1)?0:1;
- switch(params->exData[i].type) {
- case XRAN_CP_SECTIONEXTCMD_1:
- ext_size = xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);
- break;
- case XRAN_CP_SECTIONEXTCMD_2:
- ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
- break;
- case XRAN_CP_SECTIONEXTCMD_4:
- ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
- break;
- case XRAN_CP_SECTIONEXTCMD_5:
- ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
- break;
-
- case XRAN_CP_SECTIONEXTCMD_0:
- case XRAN_CP_SECTIONEXTCMD_3:
- default:
- print_err("Extension Type %d is not supported!", params->exData[i].type);
- ret = XRAN_STATUS_INVALID_PARAM;
- ext_size = 0;
- }
-
- if(ext_size == XRAN_STATUS_RESOURCE) {
- break;
- }
-
- totalen += ext_size;
- }
-
- return (totalen);
-}
-
-
-/**
- * @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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
- */
-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_STATUS_INVALID_PARAM);
- }
-#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 = XRAN_CONVERT_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_STATUS_SUCCESS);
-}
-/**
- * @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
- * XRAN_STATUS_SUCCESS always
- */
-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_STATUS_SUCCESS);
-}
-
-/**
- * @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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
- */
-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_STATUS_INVALID_PARAM);
- }
-#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 = XRAN_CONVERT_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;
-
- section->hdr.u.s1.ef = params->info.ef;
-
- // for network byte order
- *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
-
- return (XRAN_STATUS_SUCCESS);
-}
-/**
- * @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
- * XRAN_STATUS_SUCCESS always
- */
-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_STATUS_SUCCESS);
-}
-
-/**
- * @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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
- */
-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_STATUS_INVALID_PARAM);
- }
-#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 = XRAN_CONVERT_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;
-
- section->hdr.u.s3.ef = params->info.ef;
-
- // for network byte order (header, 8 bytes)
- *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
-
- return (XRAN_STATUS_SUCCESS);
-}
-/**
- * @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
- * XRAN_STATUS_SUCCESS always
- */
-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_STATUS_SUCCESS);
-}
-
-/**
- * @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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
- * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
- */
-int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
-{
- int i, ret, ext_flag;
- 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_STATUS_INVALID_PARAM);
- }
-
- if(unlikely(xran_prepare_section_func == NULL)) {
- print_err("Section Type %d is not supported!", params->sectionType);
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- for(i=0; i<params->numSections; i++) {
- section = rte_pktmbuf_append(mbuf, section_size);
- if(section == NULL) {
- print_err("Fail to allocate the space for section[%d]!", i);
- return (XRAN_STATUS_RESOURCE);
- }
-
- ret = xran_prepare_section_func((void *)section,
- (void *)¶ms->sections[i]);
- if(ret < 0)
- return (ret);
- totalen += section_size;
-
- if(params->sections[i].info.ef) {
- ret = xran_append_section_extensions(mbuf, ¶ms->sections[i]);
- if(ret < 0)
- return (ret);
- totalen += ret;
- }
- }
-
- 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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
- */
-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_STATUS_INVALID_PARAM);
- }
- if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
- print_err("Invalid Slot ID!");
- return (XRAN_STATUS_INVALID_PARAM);
- }
- if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
- print_err("Invalid Symbol ID!");
- return (XRAN_STATUS_INVALID_PARAM);
- }
-#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_STATUS_SUCCESS);
-}
-
-/**
- * @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
- * The length of added section (>0) on success
- * XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
- * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
- */
-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_STATUS_INVALID_PARAM);
- }
-#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_STATUS_INVALID_PARAM);
- }
-
- 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_STATUS_RESOURCE);
- }
-
- ret = xran_prepare_radioapp_common_header(apphdr, params);
- if(unlikely(ret < 0)) {
- return (ret);
- }
-
- if(likely(xran_prepare_radioapp_section_hdr_func)) {
- totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
- }
- else {
- print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
- return (XRAN_STATUS_INVALID_PARAM);
- }
-
- 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
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
- * XRAN_STATUS_INVALID_PARM if section type is invalid
- */
-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;
-
-
- payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
-
- 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;
-
- /* set payload length */
- ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
-
- return (XRAN_STATUS_SUCCESS);
-}
-
-
-///////////////////////////////////////
-// for RU emulation
-/**
- * @brief Parse a C-Plane packet (for RU emulation)
- * Transport layer fragmentation is not supported.
- *
- * @ingroup xran_cp_pkt
- *
- * @param mbuf
- * The pointer of the packet buffer to be parsed
- * @param params
- * The pointer of structure to store the information of parsed packet
- * @param eaxc
- * The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
- * @return
- * XRAN_STATUS_SUCCESS on success
- * XRAN_STATUS_INVALID_PACKET if failed to parse the packet
- */
-int xran_parse_cp_pkt(struct rte_mbuf *mbuf,
- struct xran_cp_gen_params *result,
- struct xran_recv_packet_info *pkt_info)
-{
- struct xran_ecpri_hdr *ecpri_hdr;
- struct xran_cp_radioapp_common_header *apphdr;
- int i, ret;
- int extlen;
-
-
- ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
- if(ret < 0 && ecpri_hdr == NULL)
- return (XRAN_STATUS_INVALID_PACKET);
-
- /* 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_STATUS_INVALID_PACKET);
- }
-
- *((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_STATUS_INVALID_PACKET;
- }
-
- 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;
-
-#if 0
- printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
- pkt_info->payload_len,
- pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
- pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
- result->dir?"DL":"UL",
- pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
- result->sectionType, result->numSections,
- result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
- result->hdr.startSymId
- );
-#endif
-
- 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_STATUS_INVALID_PACKET);
- }
- for(i=0; i<result->numSections; 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_STATUS_INVALID_PACKET;
- 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_STATUS_INVALID_PACKET);
- }
-
- for(i=0; i<result->numSections; 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_STATUS_INVALID_PACKET;
- 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_STATUS_INVALID_PACKET);
- }
-
- for(i=0; i<result->numSections; 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_STATUS_INVALID_PACKET;
- }
-
- 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_STATUS_INVALID_PACKET;
- 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_STATUS_INVALID_PARAM;
- 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; i<result->numSections; i++) {
- printf(" >> %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d 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);
-}
-
+/******************************************************************************\r
+*\r
+* Copyright (c) 2019 Intel.\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+* http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*\r
+*******************************************************************************/\r
+\r
+/**\r
+ * @brief This file provides the API functions to build Control Plane Messages\r
+ * for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01.\r
+ *\r
+ * @file xran_cp_api.c\r
+ * @ingroup group_lte_source_xran\r
+ * @author Intel Corporation\r
+ *\r
+ **/\r
+\r
+#include <rte_branch_prediction.h>\r
+\r
+#include "xran_common.h"\r
+#include "xran_transport.h"\r
+#include "xran_cp_api.h"\r
+#include "xran_printf.h"\r
+#include "xran_compression.h"\r
+\r
+\r
+/**\r
+ * This structure to store the section information of C-Plane\r
+ * in order to generate and parse corresponding U-Plane */\r
+struct xran_sectioninfo_db {\r
+ uint32_t cur_index; /**< Current index to store for this eAXC */\r
+ struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /**< The array of section information */\r
+ };\r
+\r
+static struct xran_sectioninfo_db sectiondb[XRAN_MAX_SECTIONDB_CTX][XRAN_DIR_MAX][XRAN_COMPONENT_CARRIERS_MAX][XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR];\r
+\r
+static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };\r
+static const uint8_t bitmask[] = { 0x00, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };\r
+\r
+\r
+/**\r
+ * @brief Initialize section database.\r
+ * Allocate required memory space to store section information.\r
+ * Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.\r
+ * Total entry size : number of CC * number of antenna * max number of sections * 2(direction)\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area\r
+ */\r
+int xran_cp_init_sectiondb(void *pHandle)\r
+{\r
+ int ctx, dir, cc, ant;\r
+\r
+ for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)\r
+ for(dir=0; dir < XRAN_DIR_MAX; dir++)\r
+ for(cc=0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)\r
+ for(ant=0; ant < XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR; ant++)\r
+ sectiondb[ctx][dir][cc][ant].cur_index = 0;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief Release and free section database\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ */\r
+int xran_cp_free_sectiondb(void *pHandle)\r
+{\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+static inline struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,\r
+ uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)\r
+{\r
+ struct xran_sectioninfo_db *ptr;\r
+\r
+\r
+ if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {\r
+ print_err("Invalid Context id - %d", ctx_id);\r
+ return (NULL);\r
+ }\r
+\r
+ if(unlikely(dir >= XRAN_DIR_MAX)) {\r
+ print_err("Invalid direction - %d", dir);\r
+ return (NULL);\r
+ }\r
+\r
+ if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {\r
+ print_err("Invalid CC id - %d", cc_id);\r
+ return (NULL);\r
+ }\r
+\r
+ if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR)) {\r
+ print_err("Invalid eAxC id - %d", ruport_id);\r
+ return (NULL);\r
+ }\r
+\r
+ ptr = §iondb[ctx_id][dir][cc_id][ruport_id];\r
+\r
+ return(ptr);\r
+}\r
+\r
+static inline struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)\r
+{\r
+ if(unlikely(ptr == NULL))\r
+ return (NULL);\r
+\r
+ if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {\r
+ print_err("Index is out of range - %d", index);\r
+ return (NULL);\r
+ }\r
+\r
+ return(&(ptr->list[index]));\r
+}\r
+\r
+/**\r
+ * @brief Add a section information of C-Plane to dabase.\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @param dir\r
+ * Direction of C-Plane message for the section to store\r
+ * @param cc_id\r
+ * CC ID of C-Plane message for the section to store\r
+ * @param ruport_id\r
+ * RU port ID of C-Plane message for the section to store\r
+ * @param ctx_id\r
+ * Context index for the section database\r
+ * @param info\r
+ * The information of this section to store\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect\r
+ * XRAN_STATUS_RESOURCE, if no more space to add on database\r
+ */\r
+int xran_cp_add_section_info(void *pHandle,\r
+ uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,\r
+ struct xran_section_info *info)\r
+{\r
+ struct xran_sectioninfo_db *ptr;\r
+ struct xran_section_info *list;\r
+\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL)) {\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {\r
+ print_err("No more space to add section information!");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ list = xran_get_section_info(ptr, ptr->cur_index);\r
+\r
+ rte_memcpy(list, info, sizeof(struct xran_section_info));\r
+\r
+ ptr->cur_index++;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+int xran_cp_add_multisection_info(void *pHandle,\r
+ uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,\r
+ struct xran_cp_gen_params *gen_info)\r
+{\r
+ int i;\r
+ uint8_t dir, num_sections;\r
+ struct xran_sectioninfo_db *ptr;\r
+ struct xran_section_info *list;\r
+\r
+\r
+ dir = gen_info->dir;\r
+ num_sections = gen_info->numSections;\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL)) {\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {\r
+ print_err("No more space to add section information!");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ list = xran_get_section_info(ptr, ptr->cur_index);\r
+\r
+ for(i=0; i<num_sections; i++) {\r
+ rte_memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));\r
+ ptr->cur_index++;\r
+ }\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief Find a section information of C-Plane from dabase\r
+ * by given information\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @param dir\r
+ * The direction of the section to find\r
+ * @param cc_id\r
+ * The CC ID of the section to find\r
+ * @param ruport_id\r
+ * RU port ID of the section to find\r
+ * @param ctx_id\r
+ * Context index for the section database\r
+ * @param section_id\r
+ * The ID of section to find\r
+ * @return\r
+ * The pointer of section information if matched section is found\r
+ * NULL if failed to find matched section\r
+ */\r
+struct xran_section_info *xran_cp_find_section_info(void *pHandle,\r
+ uint8_t dir, uint8_t cc_id, uint8_t ruport_id,\r
+ uint8_t ctx_id, uint16_t section_id)\r
+{\r
+ int index, num_index;\r
+ struct xran_sectioninfo_db *ptr;\r
+\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL))\r
+ return (NULL);\r
+\r
+ if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)\r
+ num_index = XRAN_MAX_NUM_SECTIONS;\r
+ else\r
+ num_index = ptr->cur_index;\r
+\r
+ for(index=0; index < num_index; index++) {\r
+ if(ptr->list[index].id == section_id) {\r
+ return (xran_get_section_info(ptr, index));\r
+ }\r
+ }\r
+\r
+ print_dbg("No section ID in the list - %d", section_id);\r
+ return (NULL);\r
+}\r
+\r
+/**\r
+ * @brief Iterate each section information of C-Plane\r
+ * from the database of eAxC by given information\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @param dir\r
+ * The direction of the section to find\r
+ * @param cc_id\r
+ * The CC ID of the section to find\r
+ * @param ruport_id\r
+ * RU port ID of the section to find\r
+ * @param ctx_id\r
+ * Context index for the section database\r
+ * @param next\r
+ * The pointer to store the position of next entry\r
+ * @return\r
+ * The pointer of section information in the list\r
+ * NULL if reached at the end of the list\r
+ */\r
+struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,\r
+ uint8_t dir, uint8_t cc_id, uint8_t ruport_id,\r
+ uint8_t ctx_id, uint32_t *next)\r
+{\r
+ int index;\r
+ struct xran_sectioninfo_db *ptr;\r
+\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL))\r
+ return (NULL);\r
+\r
+ index = *next;\r
+ if(*next < ptr->cur_index) {\r
+ (*next)++;\r
+ return (xran_get_section_info(ptr, index));\r
+ }\r
+ else {\r
+ print_dbg("No more sections in the list");\r
+ return (NULL);\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Get the size of stored entries\r
+ * for the database of eAxC by given information\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @param dir\r
+ * The direction of the section to find\r
+ * @param cc_id\r
+ * The CC ID of the section to find\r
+ * @param ruport_id\r
+ * RU port ID of the section to find\r
+ * @param ctx_id\r
+ * Context index for the section database\r
+ * @return\r
+ * The size of stored entries\r
+ * -1 if failed to find matched database\r
+ */\r
+int32_t xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)\r
+{\r
+ int index;\r
+ struct xran_sectioninfo_db *ptr;\r
+\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL))\r
+ return (-1);\r
+\r
+ return (ptr->cur_index);\r
+}\r
+\r
+/**\r
+ * @brief Reset a database of eAxC by given information\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param pHandle\r
+ * handle for xRAN interface, currently not being used\r
+ * @param dir\r
+ * The direction of the section to find\r
+ * @param cc_id\r
+ * The CC ID of the section to find\r
+ * @param ruport_id\r
+ * RU port ID of the section to find\r
+ * @param ctx_id\r
+ * Context index for the section database\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if failed to find matched database\r
+ */\r
+int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)\r
+{\r
+ struct xran_sectioninfo_db *ptr;\r
+\r
+ ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);\r
+ if(unlikely(ptr == NULL)) {\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ ptr->cur_index = 0;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+\r
+int xran_dump_sectiondb(void)\r
+{\r
+ // TODO:\r
+ return (0);\r
+}\r
+\r
+int32_t xran_cp_populate_section_ext_1(int8_t *p_ext1_dst, /**< destination buffer */\r
+ uint16_t ext1_dst_len, /**< dest buffer size */\r
+ int16_t *p_bfw_iq_src, /**< source buffer of IQs */\r
+ uint16_t rbNum, /* number RBs to ext1 chain */\r
+ uint16_t bfwNumPerRb, /* number of bf weights per RB (i.e. antenna elements) */\r
+ uint8_t bfwiqWidth, /* bit size of IQs */\r
+ uint8_t bfwCompMeth) /* compression method */\r
+{\r
+ struct xran_cp_radioapp_section_ext1 *p_ext1;\r
+\r
+ uint8_t *p_bfw_content = NULL;\r
+ int32_t parm_size = 0;\r
+ int32_t bfw_iq_bits = 0;\r
+ int32_t total_len = 0;\r
+ int32_t comp_len = 0;\r
+ uint8_t ext_flag = XRAN_EF_F_ANOTHER_ONE;\r
+ int16_t idxRb = 0;\r
+ int16_t cur_ext_len = 0;\r
+ int8_t *p_ext1_dst_cur = NULL;\r
+\r
+ struct xranlib_compress_request bfp_com_req;\r
+ struct xranlib_compress_response bfp_com_rsp;\r
+\r
+ memset(&bfp_com_req, 0, sizeof(struct xranlib_compress_request));\r
+ memset(&bfp_com_rsp, 0, sizeof(struct xranlib_compress_response));\r
+\r
+ print_dbg("%s comp %d\n", __FUNCTION__, bfwCompMeth);\r
+ print_dbg("bfwNumPerRb %d bfwiqWidth %d\n", bfwNumPerRb, bfwiqWidth);\r
+\r
+ if(p_ext1_dst)\r
+ p_ext1_dst_cur = p_ext1_dst;\r
+ else\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+\r
+ /* create extType=1 section for each RB */\r
+ for (idxRb = 0; idxRb < rbNum; idxRb++) {\r
+ print_dbg("%s RB %d\n", __FUNCTION__, idxRb);\r
+\r
+ if(total_len >= ext1_dst_len){\r
+ print_err("p_ext1_dst overflow\n");\r
+ return -1;\r
+ }\r
+\r
+ cur_ext_len = 0; /** populate one extType=1 section with BFW for 1 RB */\r
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext1);\r
+ p_ext1 = (struct xran_cp_radioapp_section_ext1 *)p_ext1_dst_cur;\r
+ if(p_ext1 == NULL) {\r
+ print_err("p_ext1 is null!\n");\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ cur_ext_len += parm_size;\r
+\r
+ if(idxRb+1 == rbNum)\r
+ ext_flag = XRAN_EF_F_LAST;\r
+\r
+ p_ext1->extType = XRAN_CP_SECTIONEXTCMD_1;\r
+ p_ext1->ef = ext_flag;\r
+ p_ext1->bfwCompMeth = bfwCompMeth;\r
+ p_ext1->bfwIqWidth = XRAN_CONVERT_BFWIQWIDTH(bfwiqWidth);\r
+\r
+ switch(bfwCompMeth) {\r
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:\r
+ p_bfw_content = (uint8_t *)(p_ext1+1);\r
+ if(p_bfw_content == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ bfp_com_req.data_in = (int16_t*)p_bfw_iq_src;\r
+ bfp_com_req.len = bfwNumPerRb*4;\r
+ bfp_com_req.compMethod = p_ext1->bfwCompMeth;\r
+ bfp_com_req.iqWidth = p_ext1->bfwIqWidth;\r
+\r
+ print_dbg("req 0x%08p iqWidth %d\n",bfp_com_req.data_in, bfp_com_req.iqWidth);\r
+\r
+ parm_size = 1; /* exponent as part of bfwCompParam 1 octet */\r
+ break;\r
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:\r
+ rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_ULAW:\r
+ rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:\r
+ rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_NONE:\r
+ default:\r
+ p_bfw_content = (uint8_t *)(p_ext1+1);\r
+ /* bfwCompParam is absent for no compression case */\r
+ parm_size = 0;\r
+ }\r
+\r
+ if(p_bfw_content == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ bfw_iq_bits = bfwNumPerRb* bfwiqWidth * 2;\r
+\r
+ parm_size += bfw_iq_bits>>3;\r
+ if(bfw_iq_bits%8)\r
+ parm_size++;\r
+\r
+ print_dbg("copy BF W %p -> %p size %d \n", p_bfw_iq_src, p_bfw_content, parm_size);\r
+ if (p_ext1->bfwIqWidth == 0 || p_ext1->bfwIqWidth == 16){\r
+ rte_memcpy(p_bfw_content, p_bfw_iq_src, parm_size);\r
+ } else {\r
+ bfp_com_rsp.data_out = (int8_t*)p_bfw_content;\r
+ if(xranlib_compress_avx512_bfw(&bfp_com_req, &bfp_com_rsp) == 0){\r
+ comp_len = bfp_com_rsp.len;\r
+ print_dbg("comp_len %d\n", comp_len);\r
+ } else {\r
+ print_err("compression failed\n");\r
+ return (XRAN_STATUS_FAIL);\r
+ }\r
+ }\r
+\r
+ p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);\r
+\r
+ cur_ext_len += parm_size;\r
+ parm_size = cur_ext_len % XRAN_SECTIONEXT_ALIGN;\r
+ if(parm_size) {\r
+ parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;\r
+ p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);\r
+ rte_memcpy(p_bfw_content, zeropad, parm_size);\r
+ cur_ext_len += parm_size;\r
+ print_dbg("zeropad %d cur_ext_len %d\n", parm_size, cur_ext_len);\r
+ }\r
+\r
+ if(cur_ext_len % XRAN_SECTIONEXT_ALIGN)\r
+ rte_panic("ext1 should be aligned on 4-bytes boundary");\r
+\r
+ p_ext1->extLen = cur_ext_len / XRAN_SECTIONEXT_ALIGN;\r
+ print_dbg("p_ext1->extLen %d\n", p_ext1->extLen);\r
+\r
+ /* update for next RB */\r
+ p_ext1_dst_cur += cur_ext_len;\r
+ p_bfw_iq_src = p_bfw_iq_src + bfwNumPerRb*2;\r
+\r
+ total_len += cur_ext_len;\r
+ }\r
+\r
+ print_dbg("total_len %d\n", total_len);\r
+ return (total_len);\r
+}\r
+\r
+\r
+// Cyclic Prefix Length 5.4.4.14\r
+// CP_length = cpLength * Ts, Ts = 1/30.72MHz\r
+// i.e cpLength = CP_length / Ts ?\r
+#define CPLEN_TS (30720000)\r
+inline uint16_t xran_get_cplength(int CP_length)\r
+{\r
+ return (CP_length);\r
+}\r
+\r
+// Frequency offset 5.4.5.11\r
+// frequency_offset = freqOffset * SCS * 0.5\r
+// i.e freqOffset = (frequency_offset *2 )/ SCS ?\r
+inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)\r
+{\r
+ return (freqOffset);\r
+}\r
+\r
+static int xran_copy_sectionext_1(struct rte_mbuf *mbuf,\r
+ struct xran_sectionext1_info *params, int last_flag)\r
+{\r
+ int32_t total_len;\r
+ int8_t *p_dst = (int8_t *)rte_pktmbuf_append(mbuf, params->bfwIQ_sz);\r
+ if(p_dst == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", params->bfwIQ_sz);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ if(params->p_bfwIQ){\r
+ /* copy formated extType1 with all the headers */\r
+ rte_memcpy(p_dst, params->p_bfwIQ, params->bfwIQ_sz);\r
+ total_len = params->bfwIQ_sz;\r
+ }\r
+ else\r
+ total_len = 0;\r
+\r
+\r
+ return (total_len);\r
+}\r
+\r
+\r
+static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,\r
+ struct xran_sectionext1_info *params, int last_flag)\r
+{\r
+ struct xran_cp_radioapp_section_ext1 *ext1;\r
+ uint8_t *data;\r
+ int parm_size, iq_size;\r
+ int total_len;\r
+\r
+ total_len = 0;\r
+\r
+ print_dbg("%s %d\n", __FUNCTION__, last_flag);\r
+\r
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext1);\r
+ ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(ext1 == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ total_len += parm_size;\r
+\r
+ ext1->extType = XRAN_CP_SECTIONEXTCMD_1;\r
+ ext1->ef = last_flag;\r
+ ext1->bfwCompMeth = params->bfwCompMeth;\r
+ ext1->bfwIqWidth = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);\r
+\r
+ switch(params->bfwCompMeth) {\r
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:\r
+ parm_size = 1;\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ total_len += parm_size;\r
+ *data = (params->bfwCompParam.exponent & 0x0f);\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:\r
+ parm_size = 1;\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ total_len += parm_size;\r
+ *data = params->bfwCompParam.blockScaler;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_ULAW:\r
+ parm_size = 1;\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ total_len += parm_size;\r
+ *data = params->bfwCompParam.compBitWidthShift;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:\r
+ parm_size = params->bfwNumber>>3;\r
+ if(params->bfwNumber%8) parm_size++;\r
+ parm_size *= 8;\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);\r
+ total_len += parm_size;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_NONE:\r
+ default:\r
+ parm_size = 0;\r
+ }\r
+\r
+ print_dbg("params->bfwNumber %d params->bfwiqWidth %d\n", params->bfwNumber, params->bfwiqWidth);\r
+\r
+ iq_size = params->bfwNumber * params->bfwiqWidth * 2;\r
+\r
+ parm_size = iq_size>>3;\r
+ if(iq_size%8)\r
+ parm_size++;\r
+\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 BF W iq_size: [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ rte_memcpy(data, params->p_bfwIQ, parm_size);\r
+\r
+ total_len += parm_size;\r
+ parm_size = total_len % XRAN_SECTIONEXT_ALIGN;\r
+ if(parm_size) {\r
+ parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ rte_memcpy(data, zeropad, parm_size);\r
+ total_len += parm_size;\r
+ }\r
+\r
+ ext1->extLen = total_len / XRAN_SECTIONEXT_ALIGN;\r
+\r
+ return (total_len);\r
+}\r
+\r
+static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,\r
+ struct xran_sectionext2_info *params, int last_flag)\r
+{\r
+ struct xran_cp_radioapp_section_ext2 *ext2;\r
+ uint8_t *data;\r
+ int total_len;\r
+ int parm_size;\r
+ uint32_t val, shift_val;\r
+ int val_size, pad_size;\r
+\r
+\r
+ total_len = 0;\r
+\r
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext2);\r
+ ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(ext2 == NULL) {\r
+ print_err("Fail to allocate the space for section extension 2");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ total_len += parm_size;\r
+\r
+ ext2->extType = XRAN_CP_SECTIONEXTCMD_2;\r
+ ext2->ef = last_flag;\r
+ ext2->bfZe3ddWidth = params->bfZe3ddWidth;\r
+ ext2->bfAz3ddWidth = params->bfAz3ddWidth;\r
+ ext2->bfZePtWidth = params->bfZePtWidth;\r
+ ext2->bfAzPtWidth = params->bfAzPtWidth;\r
+ ext2->bfaCompResv0 = 0;\r
+ ext2->bfaCompResv1 = 0;\r
+\r
+ val = 0;\r
+ shift_val = 0;\r
+ if(params->bfAzPtWidth) {\r
+ val += params->bfAzPt & bitmask[params->bfAzPtWidth];\r
+ shift_val += 8 - (params->bfAzPtWidth+1);\r
+ }\r
+ else\r
+ shift_val += 8;\r
+\r
+ if(params->bfZePtWidth) {\r
+ val = val << (params->bfZePtWidth+1);\r
+ val += params->bfZePt & bitmask[params->bfZePtWidth];\r
+ shift_val += 8 - (params->bfZePtWidth+1);\r
+ }\r
+ else\r
+ shift_val += 8;\r
+\r
+ if(params->bfAz3ddWidth) {\r
+ val = val << (params->bfAz3ddWidth+1);\r
+ val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];\r
+ shift_val += 8 - (params->bfAz3ddWidth+1);\r
+ }\r
+ else\r
+ shift_val += 8;\r
+\r
+ if(params->bfZe3ddWidth) {\r
+ val = val << (params->bfZe3ddWidth+1);\r
+ val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];\r
+ shift_val += 8 - (params->bfZe3ddWidth+1);\r
+ }\r
+ else\r
+ shift_val += 8;\r
+\r
+ if(val) {\r
+ val = val << shift_val;\r
+ val = rte_cpu_to_be_32(val);\r
+ }\r
+\r
+ val_size = 4 - (shift_val/8); /* ceil(total bit/8) */\r
+ parm_size = val_size + 1; /* additional 1 byte for bfxxSI */\r
+\r
+ // alignment\r
+ total_len += parm_size;\r
+ pad_size = total_len % XRAN_SECTIONEXT_ALIGN;\r
+ if(pad_size) {\r
+ pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;\r
+ parm_size += pad_size;\r
+ total_len += pad_size;\r
+ }\r
+\r
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(data == NULL) {\r
+ print_err("Fail to allocate the space for section extension 2");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ rte_memcpy(data, &val, val_size);\r
+ data += val_size;\r
+ *data = ((params->bfAzSI) << 3) + (params->bfZeSI);\r
+ data++;\r
+ rte_memcpy(data, zeropad, pad_size);\r
+\r
+ ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;\r
+ *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);\r
+\r
+ return (total_len);\r
+}\r
+\r
+static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,\r
+ struct xran_sectionext4_info *params, int last_flag)\r
+{\r
+ struct xran_cp_radioapp_section_ext4 *ext4;\r
+ int parm_size;\r
+ int total_len;\r
+ int ret;\r
+\r
+\r
+ total_len = 0;\r
+\r
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext4);\r
+ ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);\r
+ if(ext4 == NULL) {\r
+ print_err("Fail to allocate the space for section extension 4");\r
+ return(XRAN_STATUS_RESOURCE);\r
+ }\r
+ else {\r
+ total_len += parm_size;\r
+\r
+ ext4->extType = XRAN_CP_SECTIONEXTCMD_4;\r
+ ext4->ef = last_flag;\r
+ ext4->modCompScaler = params->modCompScaler;\r
+ ext4->csf = params->csf?1:0;\r
+ ext4->extLen = total_len / XRAN_SECTIONEXT_ALIGN;\r
+\r
+ *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);\r
+ }\r
+\r
+ return (total_len);\r
+}\r
+\r
+static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,\r
+ struct xran_sectionext5_info *params, int last_flag)\r
+{\r
+ struct xran_cp_radioapp_section_ext_hdr *ext_hdr;\r
+ struct xran_cp_radioapp_section_ext5 ext5;\r
+ int padding;\r
+ int total_len;\r
+ uint8_t *data;\r
+ int i;\r
+\r
+\r
+ if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {\r
+ print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);\r
+ return (0);\r
+ }\r
+\r
+ total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)\r
+ + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2\r
+ - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust\r
+\r
+ /* for alignment */\r
+ padding = total_len % XRAN_SECTIONEXT_ALIGN;\r
+ if(padding) {\r
+ padding = XRAN_SECTIONEXT_ALIGN - padding;\r
+ total_len += padding;\r
+ }\r
+\r
+ ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);\r
+ if(ext_hdr == NULL) {\r
+ print_err("Fail to allocate the space for section extension 5");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ ext_hdr->extType = XRAN_CP_SECTIONEXTCMD_5;\r
+ ext_hdr->ef = last_flag;\r
+ ext_hdr->extLen = total_len / XRAN_SECTIONEXT_ALIGN;\r
+\r
+ *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));\r
+\r
+ data = (uint8_t *)(ext_hdr + 1);\r
+ i = 0;\r
+ while(i < params->num_sets) {\r
+ if(i%2) { // odd index\r
+ ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;\r
+ ext5.csf2 = params->mc[i].csf;\r
+ ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;\r
+ ext5.reserved0 = 0;\r
+ i++;\r
+\r
+ // adding two sets at once (due to the definition of structure)\r
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));\r
+ rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));\r
+ data += sizeof(struct xran_cp_radioapp_section_ext5);\r
+ }\r
+ else { // even index\r
+ ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;\r
+ ext5.csf1 = params->mc[i].csf;\r
+ ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;\r
+ ext5.mcScaleReMask2 = 0;\r
+ i++;\r
+\r
+ if(i == params->num_sets) { // adding last even index\r
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));\r
+ rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);\r
+ data += sizeof(struct xran_cp_radioapp_section_ext5)/2;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* zero padding */\r
+ if(padding)\r
+ rte_memcpy(data, zeropad, padding);\r
+\r
+ return (total_len);\r
+}\r
+\r
+/**\r
+ * @brief add section extension to C-Plane packet\r
+ *\r
+ * @param mbuf\r
+ * A pointer to the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM\r
+ * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer\r
+ */\r
+int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)\r
+{\r
+ int i, ret;\r
+ uint32_t totalen;\r
+ int last_flag;\r
+ int ext_size;\r
+\r
+ if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {\r
+ print_err("Invalid total number of extensions - %d", params->exDataSize);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ totalen = 0;\r
+\r
+ ret = XRAN_STATUS_SUCCESS;\r
+\r
+ print_dbg("params->exDataSize %d\n", params->exDataSize);\r
+ for(i=0; i < params->exDataSize; i++) {\r
+ if(params->exData[i].data == NULL) {\r
+ print_err("Invalid parameter - extension data %d is NULL", i);\r
+ ret = XRAN_STATUS_INVALID_PARAM;\r
+ continue;\r
+ }\r
+\r
+ last_flag = (params->exDataSize == (i+1))?0:1;\r
+\r
+ switch(params->exData[i].type) {\r
+ case XRAN_CP_SECTIONEXTCMD_1:\r
+ ext_size = xran_copy_sectionext_1(mbuf, params->exData[i].data, last_flag);\r
+ //xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_2:\r
+ ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_4:\r
+ ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_5:\r
+ ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_0:\r
+ case XRAN_CP_SECTIONEXTCMD_3:\r
+ default:\r
+ print_err("Extension Type %d is not supported!", params->exData[i].type);\r
+ ret = XRAN_STATUS_INVALID_PARAM;\r
+ ext_size = 0;\r
+ }\r
+\r
+ if(ext_size == XRAN_STATUS_RESOURCE) {\r
+ break;\r
+ }\r
+\r
+ totalen += ext_size;\r
+ }\r
+\r
+ return (totalen);\r
+}\r
+\r
+\r
+/**\r
+ * @brief Fill the section body of type 0 in C-Plane packet\r
+ *\r
+ * @param section\r
+ * A pointer to the section in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid\r
+ */\r
+static int xran_prepare_section0(\r
+ struct xran_cp_radioapp_section0 *section,\r
+ struct xran_section_gen_info *params)\r
+{\r
+#if (XRAN_STRICT_PARM_CHECK)\r
+ if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {\r
+ print_err("Invalid number of Symbols - %d", params->info.numSymbol);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+#endif\r
+\r
+ section->hdr.sectionId = params->info.id;\r
+ section->hdr.rb = params->info.rb;\r
+ section->hdr.symInc = params->info.symInc;\r
+ section->hdr.startPrbc = params->info.startPrbc;\r
+ section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);\r
+\r
+ section->hdr.u.s0.reMask = params->info.reMask;\r
+ section->hdr.u.s0.numSymbol = params->info.numSymbol;\r
+ section->hdr.u.s0.reserved = 0;\r
+\r
+ // for network byte order\r
+ *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+/**\r
+ * @brief Fill the section header of type 0 in C-Plane packet\r
+ *\r
+ * @param s0hdr\r
+ * A pointer to the section header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS always\r
+ */\r
+static int xran_prepare_section0_hdr(\r
+ struct xran_cp_radioapp_section0_header *s0hdr,\r
+ struct xran_cp_gen_params *params)\r
+\r
+{\r
+ s0hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset);\r
+ s0hdr->frameStructure.fftSize = params->hdr.fftSize;\r
+ s0hdr->frameStructure.uScs = params->hdr.scs;\r
+ s0hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength);\r
+ s0hdr->reserved = 0;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief Fill the section body of type 1 in C-Plane packet\r
+ * Extension is not supported.\r
+ *\r
+ * @param section\r
+ * A pointer to the section header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid\r
+ */\r
+static int xran_prepare_section1(\r
+ struct xran_cp_radioapp_section1 *section,\r
+ struct xran_section_gen_info *params)\r
+{\r
+#if (XRAN_STRICT_PARM_CHECK)\r
+ if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {\r
+ print_err("Invalid number of Symbols - %d", params->info.numSymbol);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+#endif\r
+\r
+ section->hdr.sectionId = params->info.id;\r
+ section->hdr.rb = params->info.rb;\r
+ section->hdr.symInc = params->info.symInc;\r
+ section->hdr.startPrbc = params->info.startPrbc;\r
+ section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);\r
+\r
+ section->hdr.u.s1.reMask = params->info.reMask;\r
+ section->hdr.u.s1.numSymbol = params->info.numSymbol;\r
+ section->hdr.u.s1.beamId = params->info.beamId;\r
+\r
+ section->hdr.u.s1.ef = params->info.ef;\r
+\r
+ // for network byte order\r
+ *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+/**\r
+ * @brief Fill the section header of type 1 in C-Plane packet\r
+ *\r
+ * @param s1hdr\r
+ * A pointer to the section header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS always\r
+ */\r
+static int xran_prepare_section1_hdr(\r
+ struct xran_cp_radioapp_section1_header *s1hdr,\r
+ struct xran_cp_gen_params *params)\r
+{\r
+ s1hdr->udComp.udIqWidth = params->hdr.iqWidth;\r
+ s1hdr->udComp.udCompMeth = params->hdr.compMeth;\r
+ s1hdr->reserved = 0;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief Fill the section body of type 3 in C-Plane packet\r
+ * Extension is not supported.\r
+ *\r
+ * @param section\r
+ * A pointer to the section header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid\r
+ */\r
+static int xran_prepare_section3(\r
+ struct xran_cp_radioapp_section3 *section,\r
+ struct xran_section_gen_info *params)\r
+{\r
+#if (XRAN_STRICT_PARM_CHECK)\r
+ if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {\r
+ print_err("Invalid number of Symbols - %d", params->info.numSymbol);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+#endif\r
+\r
+ section->hdr.sectionId = params->info.id;\r
+ section->hdr.rb = params->info.rb;\r
+ section->hdr.symInc = params->info.symInc;\r
+ section->hdr.startPrbc = params->info.startPrbc;\r
+ section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);\r
+\r
+ section->hdr.u.s3.reMask = params->info.reMask;\r
+ section->hdr.u.s3.numSymbol = params->info.numSymbol;\r
+ section->hdr.u.s3.beamId = params->info.beamId;\r
+\r
+ section->freqOffset = rte_cpu_to_be_32(params->info.freqOffset)>>8;\r
+ section->reserved = 0;\r
+\r
+ section->hdr.u.s3.ef = params->info.ef;\r
+\r
+ // for network byte order (header, 8 bytes)\r
+ *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+/**\r
+ * @brief Fill the section header of type 3 in C-Plane packet\r
+ *\r
+ * @param s3hdr\r
+ * A pointer to the section header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS always\r
+ */\r
+static int xran_prepare_section3_hdr(\r
+ struct xran_cp_radioapp_section3_header *s3hdr,\r
+ struct xran_cp_gen_params *params)\r
+\r
+{\r
+ s3hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset);\r
+ s3hdr->frameStructure.fftSize = params->hdr.fftSize;\r
+ s3hdr->frameStructure.uScs = params->hdr.scs;\r
+ s3hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength);\r
+ s3hdr->udComp.udIqWidth = params->hdr.iqWidth;\r
+ s3hdr->udComp.udCompMeth = params->hdr.compMeth;\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief add sections to C-Plane packet\r
+ * Section type 1 and 3 are supported.\r
+ *\r
+ * @param mbuf\r
+ * A pointer to the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL\r
+ * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer\r
+ */\r
+int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)\r
+{\r
+ int i, ret, ext_flag;\r
+ uint32_t totalen;\r
+ void *section;\r
+ int section_size;\r
+ int (*xran_prepare_section_func)(void *section, void *params);\r
+\r
+\r
+ totalen = 0;\r
+ switch(params->sectionType) {\r
+ case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */\r
+ section_size = sizeof(struct xran_cp_radioapp_section0);\r
+ xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section0;\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */\r
+ section_size = sizeof(struct xran_cp_radioapp_section1);\r
+ xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section1;\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */\r
+ section_size = sizeof(struct xran_cp_radioapp_section3);\r
+ xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section3;\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */\r
+ case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */\r
+ case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */\r
+ default:\r
+ section_size = 0;\r
+ xran_prepare_section_func = NULL;\r
+ print_err("Section Type %d is not supported!", params->sectionType);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ if(unlikely(xran_prepare_section_func == NULL)) {\r
+ print_err("Section Type %d is not supported!", params->sectionType);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ for(i=0; i < params->numSections; i++) {\r
+ section = rte_pktmbuf_append(mbuf, section_size);\r
+ if(section == NULL) {\r
+ print_err("Fail to allocate the space for section[%d]!", i);\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+ print_dbg("%s %d ef %d\n", __FUNCTION__, i, params->sections[i].info.ef);\r
+ ret = xran_prepare_section_func((void *)section,\r
+ (void *)¶ms->sections[i]);\r
+ if(ret < 0){\r
+ print_err("%s %d\n", __FUNCTION__, ret);\r
+ return (ret);\r
+ }\r
+ totalen += section_size;\r
+\r
+ if(params->sections[i].info.ef) {\r
+ print_dbg("sections[%d].info.ef %d exDataSize %d type %d\n", i, params->sections[i].info.ef,\r
+ params->sections[i].exDataSize, params->sections[i].exData[0].type);\r
+ ret = xran_append_section_extensions(mbuf, ¶ms->sections[i]);\r
+ if(ret < 0)\r
+ return (ret);\r
+ totalen += ret;\r
+ }\r
+ }\r
+\r
+ return (totalen);\r
+}\r
+\r
+/**\r
+ * @brief fill the information of a radio application header in a C-Plane packet\r
+ *\r
+ * @param apphdr\r
+ * A pointer to the application header in the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid\r
+ */\r
+static inline int xran_prepare_radioapp_common_header(\r
+ struct xran_cp_radioapp_common_header *apphdr,\r
+ struct xran_cp_gen_params *params)\r
+{\r
+\r
+#if (XRAN_STRICT_PARM_CHECK)\r
+ if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {\r
+ print_err("Invalid direction!");\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+ if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {\r
+ print_err("Invalid Slot ID!");\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+ if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {\r
+ print_err("Invalid Symbol ID!");\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+#endif\r
+\r
+ apphdr->dataDirection = params->dir;\r
+ apphdr->payloadVer = XRAN_PAYLOAD_VER;\r
+ apphdr->filterIndex = params->hdr.filterIdx;\r
+ apphdr->frameId = params->hdr.frameId;\r
+ apphdr->subframeId = params->hdr.subframeId;\r
+ apphdr->slotId = params->hdr.slotId;\r
+ apphdr->startSymbolId = params->hdr.startSymId;\r
+ apphdr->numOfSections = params->numSections;\r
+ apphdr->sectionType = params->sectionType;\r
+\r
+ /* radio app header has common parts of 4bytes for all section types */\r
+ *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+/**\r
+ * @brief add a radio application header in a C-Plane packet\r
+ *\r
+ * @param mbuf\r
+ * A pointer to the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @return\r
+ * The length of added section (>0) on success\r
+ * XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL\r
+ * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer\r
+ */\r
+int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)\r
+{\r
+ int ret;\r
+ uint32_t totalen;\r
+ struct xran_cp_radioapp_common_header *apphdr;\r
+ int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);\r
+\r
+\r
+#if (XRAN_STRICT_PARM_CHECK)\r
+ if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {\r
+ print_err("Invalid Section Type - %d", params->sectionType);\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+#endif\r
+\r
+ switch(params->sectionType) {\r
+ case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */\r
+ xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;\r
+ totalen = sizeof(struct xran_cp_radioapp_section0_header);\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */\r
+ xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;\r
+ totalen = sizeof(struct xran_cp_radioapp_section1_header);\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */\r
+ xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;\r
+ totalen = sizeof(struct xran_cp_radioapp_section3_header);\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */\r
+ case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */\r
+ case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */\r
+ default:\r
+ print_err("Section Type %d is not supported!", params->sectionType);\r
+ xran_prepare_radioapp_section_hdr_func = NULL;\r
+ totalen = 0;\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);\r
+ if(unlikely(apphdr == NULL)) {\r
+ print_err("Fail to reserve the space for radio application header!");\r
+ return (XRAN_STATUS_RESOURCE);\r
+ }\r
+\r
+ ret = xran_prepare_radioapp_common_header(apphdr, params);\r
+ if(unlikely(ret < 0)) {\r
+ return (ret);\r
+ }\r
+\r
+ if(likely(xran_prepare_radioapp_section_hdr_func)) {\r
+ totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);\r
+ }\r
+ else {\r
+ print_err("xran_prepare_radioapp_section_hdr_func is NULL!");\r
+ return (XRAN_STATUS_INVALID_PARAM);\r
+ }\r
+\r
+ return (totalen);\r
+}\r
+\r
+/**\r
+ * @brief Create a C-Plane packet\r
+ * Transport layer fragmentation is not supported.\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param mbuf\r
+ * A pointer to the packet buffer\r
+ * @param params\r
+ * A porinter to the information to generate a C-Plane packet\r
+ * @param CC_ID\r
+ * Component Carrier ID for this C-Plane message\r
+ * @param Ant_ID\r
+ * Antenna ID(RU Port ID) for this C-Plane message\r
+ * @param seq_id\r
+ * Sequence ID for this C-Plane message\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer\r
+ * XRAN_STATUS_INVALID_PARM if section type is invalid\r
+ */\r
+int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,\r
+ struct xran_cp_gen_params *params,\r
+ uint8_t CC_ID, uint8_t Ant_ID,\r
+ uint8_t seq_id)\r
+{\r
+ int ret;\r
+ uint32_t payloadlen;\r
+ struct xran_ecpri_hdr *ecpri_hdr;\r
+\r
+\r
+ payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);\r
+\r
+ ret = xran_append_radioapp_header(mbuf, params);\r
+ if(ret < 0) {\r
+ print_err("%s %d\n", __FUNCTION__, ret);\r
+ return (ret);\r
+ }\r
+ payloadlen += ret;\r
+\r
+ ret = xran_append_control_section(mbuf, params);\r
+ if(ret < 0) {\r
+ print_err("%s %d\n", __FUNCTION__, ret);\r
+ return (ret);\r
+ }\r
+ payloadlen += ret;\r
+\r
+ /* set payload length */\r
+ ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);\r
+\r
+ return (XRAN_STATUS_SUCCESS);\r
+}\r
+\r
+\r
+///////////////////////////////////////\r
+// for RU emulation\r
+int xran_parse_section_ext1(void *ext,\r
+ struct xran_sectionext1_info *extinfo)\r
+{\r
+ int len;\r
+ int total_len;\r
+ struct xran_cp_radioapp_section_ext1 *ext1;\r
+ uint8_t *data;\r
+ int parm_size, iq_size;\r
+ int N;\r
+ void *pHandle;\r
+\r
+ pHandle = NULL;\r
+ N = xran_get_conf_num_bfweights(pHandle);\r
+ extinfo->bfwNumber = N;\r
+\r
+ ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;\r
+ data = (uint8_t *)ext;\r
+\r
+ len = 0;\r
+ total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */\r
+\r
+ extinfo->bfwCompMeth = ext1->bfwCompMeth;\r
+ extinfo->bfwiqWidth = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;\r
+\r
+ len += sizeof(struct xran_cp_radioapp_section_ext1);\r
+ data += sizeof(struct xran_cp_radioapp_section_ext1);\r
+\r
+ switch(ext1->bfwCompMeth) {\r
+ case XRAN_BFWCOMPMETHOD_NONE:\r
+ parm_size = 0;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:\r
+ parm_size = 1;\r
+ extinfo->bfwCompParam.exponent = *data & 0x0f;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:\r
+ parm_size = 1;\r
+ extinfo->bfwCompParam.blockScaler = *data;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_ULAW:\r
+ parm_size = 1;\r
+ extinfo->bfwCompParam.compBitWidthShift = *data;\r
+ break;\r
+\r
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:\r
+ parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;\r
+ rte_memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);\r
+ break;\r
+\r
+ default:\r
+ print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);\r
+ parm_size = 0;\r
+ }\r
+\r
+ len += parm_size;\r
+ data += parm_size;\r
+\r
+ /* Get BF weights */\r
+ iq_size = N * extinfo->bfwiqWidth * 2; // total in bits\r
+ parm_size = iq_size>>3; // total in bytes (/8)\r
+ if(iq_size%8) parm_size++; // round up\r
+\r
+ //rte_memcpy(data, extinfo->p_bfwIQ, parm_size);\r
+ extinfo->p_bfwIQ = (int16_t*)data;\r
+\r
+ len += parm_size;\r
+\r
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;\r
+ if(parm_size)\r
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);\r
+\r
+ if(len != total_len) {\r
+ // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);\r
+ }\r
+\r
+ return (total_len);\r
+}\r
+\r
+int xran_parse_section_ext2(void *ext,\r
+ struct xran_sectionext2_info *extinfo)\r
+{\r
+ int len;\r
+ int total_len;\r
+ struct xran_cp_radioapp_section_ext2 *ext2;\r
+ uint8_t *data;\r
+ int parm_size;\r
+ uint32_t val;\r
+ int val_size;\r
+\r
+\r
+ ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;\r
+ data = (uint8_t *)ext;\r
+ *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);\r
+\r
+ len = 0;\r
+ total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */\r
+\r
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext2);\r
+\r
+ extinfo->bfAzPtWidth = ext2->bfAzPtWidth;\r
+ extinfo->bfZePtWidth = ext2->bfZePtWidth;\r
+ extinfo->bfAz3ddWidth = ext2->bfAz3ddWidth;\r
+ extinfo->bfZe3ddWidth = ext2->bfZe3ddWidth;\r
+\r
+ if(ext2->bfaCompResv0 || ext2->bfaCompResv1)\r
+ print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);\r
+\r
+ data += parm_size;\r
+ len += parm_size;\r
+\r
+ val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)\r
+ + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)\r
+ + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)\r
+ + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);\r
+ if(val_size) {\r
+ val = rte_cpu_to_be_32(*(uint32_t *)data);\r
+ val >>= (32 - val_size);\r
+\r
+ if(extinfo->bfZe3ddWidth) {\r
+ extinfo->bfZe3dd = val & bitmask[extinfo->bfZe3ddWidth];\r
+ val >>= (extinfo->bfZe3ddWidth + 1);\r
+ }\r
+ if(extinfo->bfAz3ddWidth) {\r
+ extinfo->bfAz3dd = val & bitmask[extinfo->bfAz3ddWidth];\r
+ val >>= (extinfo->bfAz3ddWidth + 1);\r
+ }\r
+ if(extinfo->bfZePtWidth) {\r
+ extinfo->bfZePt = val & bitmask[extinfo->bfZePtWidth];\r
+ val >>= (extinfo->bfZePtWidth + 1);\r
+ }\r
+ if(extinfo->bfAzPtWidth) {\r
+ extinfo->bfAzPt = val & bitmask[extinfo->bfAzPtWidth];\r
+ val >>= (extinfo->bfAzPtWidth + 1);\r
+ }\r
+ }\r
+\r
+ parm_size = val_size/8;\r
+ if(val_size%8) parm_size += 1;\r
+\r
+ data += parm_size;\r
+ len += parm_size;\r
+\r
+ extinfo->bfAzSI = (*data >> 3) & 0x07;\r
+ extinfo->bfZeSI = *data & 0x07;\r
+\r
+ data++;\r
+ len++;\r
+\r
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;\r
+ if(parm_size)\r
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);\r
+\r
+ if(len != total_len) {\r
+ print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);\r
+ }\r
+\r
+ return (total_len);\r
+\r
+}\r
+\r
+int xran_parse_section_ext4(void *ext,\r
+ struct xran_sectionext4_info *extinfo)\r
+{\r
+ int len;\r
+ struct xran_cp_radioapp_section_ext4 *ext4;\r
+ int total_len;\r
+\r
+\r
+ ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;\r
+\r
+ *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t *)ext4);\r
+\r
+ len = 0;\r
+ total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */\r
+\r
+ extinfo->modCompScaler = ext4->modCompScaler;\r
+ extinfo->csf = ext4->csf;\r
+// extinfo->pad0;\r
+\r
+ len += sizeof(struct xran_cp_radioapp_section_ext4);\r
+ if(len != total_len) {\r
+ print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);\r
+ }\r
+\r
+ return (total_len);\r
+}\r
+\r
+int xran_parse_section_ext5(void *ext,\r
+ struct xran_sectionext5_info *extinfo)\r
+{\r
+ int len;\r
+ struct xran_cp_radioapp_section_ext_hdr *ext_hdr;\r
+ struct xran_cp_radioapp_section_ext5 ext5;\r
+ int parm_size;\r
+ int total_len;\r
+ uint8_t *data;\r
+ uint16_t i;\r
+\r
+\r
+ ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;\r
+ *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*(uint16_t *)ext_hdr);\r
+\r
+ total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */\r
+\r
+ // one set has 3.5 bytes, so enforcing double to do integer calculation\r
+ parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;\r
+\r
+ if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {\r
+ print_err("Exceeds maximum number of parameters - %d", parm_size);\r
+ parm_size = XRAN_MAX_MODCOMP_ADDPARMS;\r
+ }\r
+\r
+ len = 0;\r
+ data = (uint8_t *)(ext_hdr + 1);\r
+\r
+ i = 0;\r
+ while(i < parm_size) {\r
+ // For odd number set, more data can be copied\r
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)data));\r
+\r
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset1;\r
+ extinfo->mc[i].csf = ext5.csf1;\r
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask1;\r
+ i++;\r
+\r
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset2;\r
+ extinfo->mc[i].csf = ext5.csf2;\r
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask2;\r
+ i++;\r
+\r
+ data += sizeof(struct xran_cp_radioapp_section_ext5);\r
+ }\r
+\r
+ // check the values of last set\r
+ // due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc\r
+ // don't check mcScaleOffset might not be zero (some part is out of zero-padding)\r
+ i--;\r
+ if(i < XRAN_MAX_MODCOMP_ADDPARMS) {\r
+ if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)\r
+ extinfo->num_sets = i;\r
+ else\r
+ extinfo->num_sets = i+1;\r
+ }else {\r
+ print_err("Maximum total number %d is not correct!", i);\r
+ }\r
+\r
+ return (total_len);\r
+}\r
+\r
+int xran_parse_section_extension(struct rte_mbuf *mbuf,\r
+ void *ext,\r
+ struct xran_section_gen_info *section)\r
+{\r
+ int total_len, len, numext;\r
+ uint8_t *ptr;\r
+ int flag_last;\r
+ int ext_type;\r
+ int i;\r
+\r
+ total_len = 0;\r
+ ptr = (uint8_t *)ext;\r
+\r
+ numext = 0;\r
+\r
+ flag_last = 1;\r
+ i = 0;\r
+ while(flag_last) {\r
+ /* check ef */\r
+ flag_last = (*ptr & 0x80);\r
+\r
+ ext_type = *ptr & 0x7f;\r
+ section->exData[numext].type = ext_type;\r
+ switch(ext_type) {\r
+ case XRAN_CP_SECTIONEXTCMD_1:\r
+ section->exData[numext].data = §ion->m_ext1[numext];\r
+ len = xran_parse_section_ext1(ptr, section->exData[numext].data);\r
+ section->exData[numext].len = len;\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_2:\r
+ section->exData[numext].data = §ion->m_ext2[numext];\r
+ len = xran_parse_section_ext2(ptr, section->exData[numext].data);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_4:\r
+ section->exData[numext].data = §ion->m_ext4[numext];\r
+ len = xran_parse_section_ext4(ptr, section->exData[numext].data);\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_5:\r
+ section->exData[numext].data = §ion->m_ext5[numext];\r
+ len = xran_parse_section_ext5(ptr, section->exData[numext].data);\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONEXTCMD_0:\r
+ case XRAN_CP_SECTIONEXTCMD_3:\r
+ default:\r
+ print_err("Extension %d is not supported!", ext_type);\r
+ len = 0;\r
+ }\r
+\r
+ section->exData[numext].len = len;\r
+ ptr += len; total_len += len;\r
+\r
+ i++;\r
+ if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;\r
+\r
+ /* exceeds maximum number of extensions */\r
+ break;\r
+ }\r
+\r
+ section->exDataSize = numext;\r
+\r
+ return (total_len);\r
+\r
+}\r
+\r
+/**\r
+ * @brief Parse a C-Plane packet (for RU emulation)\r
+ * Transport layer fragmentation is not supported.\r
+ *\r
+ * @ingroup xran_cp_pkt\r
+ *\r
+ * @param mbuf\r
+ * The pointer of the packet buffer to be parsed\r
+ * @param params\r
+ * The pointer of structure to store the information of parsed packet\r
+ * @param eaxc\r
+ * The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid\r
+ * @return\r
+ * XRAN_STATUS_SUCCESS on success\r
+ * XRAN_STATUS_INVALID_PACKET if failed to parse the packet\r
+ */\r
+int xran_parse_cp_pkt(struct rte_mbuf *mbuf,\r
+ struct xran_cp_gen_params *result,\r
+ struct xran_recv_packet_info *pkt_info)\r
+{\r
+ struct xran_ecpri_hdr *ecpri_hdr;\r
+ struct xran_cp_radioapp_common_header *apphdr;\r
+ int i, ret;\r
+ int extlen;\r
+\r
+\r
+ ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);\r
+ if(ret < 0 && ecpri_hdr == NULL)\r
+ return (XRAN_STATUS_INVALID_PACKET);\r
+\r
+ /* Process radio header. */\r
+ apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));\r
+ if(apphdr == NULL) {\r
+ print_err("Invalid packet - radio app hedaer!");\r
+ return (XRAN_STATUS_INVALID_PACKET);\r
+ }\r
+\r
+ *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));\r
+\r
+ if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {\r
+ print_err("Invalid Payload version - %d", apphdr->payloadVer);\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ }\r
+\r
+ result->dir = apphdr->dataDirection;\r
+ result->hdr.filterIdx = apphdr->filterIndex;\r
+ result->hdr.frameId = apphdr->frameId;\r
+ result->hdr.subframeId = apphdr->subframeId;\r
+ result->hdr.slotId = apphdr->slotId;\r
+ result->hdr.startSymId = apphdr->startSymbolId;\r
+ result->sectionType = apphdr->sectionType;\r
+ result->numSections = apphdr->numOfSections;\r
+\r
+#if 0\r
+ printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",\r
+ pkt_info->payload_len,\r
+ pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,\r
+ pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,\r
+ result->dir?"DL":"UL",\r
+ pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,\r
+ result->sectionType, result->numSections,\r
+ result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,\r
+ result->hdr.startSymId\r
+ );\r
+#endif\r
+\r
+ switch(apphdr->sectionType) {\r
+ case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted\r
+ {\r
+ struct xran_cp_radioapp_section0_header *hdr;\r
+ struct xran_cp_radioapp_section0 *section;\r
+\r
+ hdr = (struct xran_cp_radioapp_section0_header*)apphdr;\r
+\r
+ result->hdr.fftSize = rte_be_to_cpu_16(hdr->timeOffset);\r
+ result->hdr.scs = hdr->frameStructure.fftSize;\r
+ result->hdr.timeOffset = hdr->frameStructure.uScs;\r
+ result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength);\r
+ //hdr->reserved; /* should be zero */\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 0 - radio app hedaer!");\r
+ return (XRAN_STATUS_INVALID_PACKET);\r
+ }\r
+ for(i=0; i<result->numSections; i++) {\r
+ *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));\r
+\r
+ result->sections[i].info.type = apphdr->sectionType;\r
+ result->sections[i].info.id = section->hdr.sectionId;\r
+ result->sections[i].info.rb = section->hdr.rb;\r
+ result->sections[i].info.symInc = section->hdr.symInc;\r
+ result->sections[i].info.startPrbc = section->hdr.startPrbc;\r
+ result->sections[i].info.numPrbc = section->hdr.numPrbc,\r
+ result->sections[i].info.numSymbol = section->hdr.u.s0.numSymbol;\r
+ result->sections[i].info.reMask = section->hdr.u.s0.reMask;\r
+ //section->hdr.u.s0.reserved; /* should be zero */\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 0 - number of section [%d:%d]!",\r
+ result->numSections, i);\r
+ result->numSections = i;\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels\r
+ {\r
+ struct xran_cp_radioapp_section1_header *hdr;\r
+ struct xran_cp_radioapp_section1 *section;\r
+\r
+ hdr = (struct xran_cp_radioapp_section1_header*)apphdr;\r
+\r
+ result->hdr.iqWidth = hdr->udComp.udIqWidth;\r
+ result->hdr.compMeth = hdr->udComp.udCompMeth;\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 1 - radio app hedaer!");\r
+ return (XRAN_STATUS_INVALID_PACKET);\r
+ }\r
+\r
+ for(i=0; i<result->numSections; i++) {\r
+ *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));\r
+\r
+ result->sections[i].info.type = apphdr->sectionType;\r
+ result->sections[i].info.id = section->hdr.sectionId;\r
+ result->sections[i].info.rb = section->hdr.rb;\r
+ result->sections[i].info.symInc = section->hdr.symInc;\r
+ result->sections[i].info.startPrbc = section->hdr.startPrbc;\r
+ result->sections[i].info.numPrbc = section->hdr.numPrbc,\r
+ result->sections[i].info.numSymbol = section->hdr.u.s1.numSymbol;\r
+ result->sections[i].info.reMask = section->hdr.u.s1.reMask;\r
+ result->sections[i].info.beamId = section->hdr.u.s1.beamId;\r
+ result->sections[i].info.ef = section->hdr.u.s1.ef;\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf,\r
+ sizeof(struct xran_cp_radioapp_section1));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 1 - number of section [%d:%d]!",\r
+ result->numSections, i);\r
+ result->numSections = i;\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ break;\r
+ }\r
+\r
+ if(result->sections[i].info.ef) {\r
+ // parse section extension\r
+ extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);\r
+ if(extlen > 0) {\r
+ section = (void *)rte_pktmbuf_adj(mbuf, extlen);\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 1 - section extension [%d]!", i);\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else extlen = 0;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels\r
+ {\r
+ struct xran_cp_radioapp_section3_header *hdr;\r
+ struct xran_cp_radioapp_section3 *section;\r
+\r
+ hdr = (struct xran_cp_radioapp_section3_header*)apphdr;\r
+\r
+ result->hdr.timeOffset = rte_be_to_cpu_16(hdr->timeOffset);\r
+ result->hdr.scs = hdr->frameStructure.uScs;\r
+ result->hdr.fftSize = hdr->frameStructure.fftSize;\r
+ result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength);\r
+ result->hdr.iqWidth = hdr->udComp.udIqWidth;\r
+ result->hdr.compMeth = hdr->udComp.udCompMeth;\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 3 - radio app hedaer!");\r
+ return (XRAN_STATUS_INVALID_PACKET);\r
+ }\r
+\r
+ for(i=0; i<result->numSections; i++) {\r
+ *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));\r
+\r
+ result->sections[i].info.type = apphdr->sectionType;\r
+ result->sections[i].info.id = section->hdr.sectionId;\r
+ result->sections[i].info.rb = section->hdr.rb;\r
+ result->sections[i].info.symInc = section->hdr.symInc;\r
+ result->sections[i].info.startPrbc = section->hdr.startPrbc;\r
+ result->sections[i].info.numPrbc = section->hdr.numPrbc,\r
+ result->sections[i].info.numSymbol = section->hdr.u.s3.numSymbol;\r
+ result->sections[i].info.reMask = section->hdr.u.s3.reMask;\r
+ result->sections[i].info.beamId = section->hdr.u.s3.beamId;\r
+ result->sections[i].info.ef = section->hdr.u.s3.ef;\r
+ result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;\r
+\r
+ if(section->reserved) {\r
+ print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ }\r
+\r
+ section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3));\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 3 - number of section [%d:%d]!",\r
+ result->numSections, i);\r
+ result->numSections = i;\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ break;\r
+ }\r
+\r
+ if(result->sections[i].info.ef) {\r
+ // parse section extension\r
+ extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);\r
+ if(extlen > 0) {\r
+ section = (void *)rte_pktmbuf_adj(mbuf, extlen);\r
+ if(section == NULL) {\r
+ print_err("Invalid packet 3 - section extension [%d]!", i);\r
+ ret = XRAN_STATUS_INVALID_PACKET;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else extlen = 0;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported\r
+ case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported\r
+ case XRAN_CP_SECTIONTYPE_7: // LAA, not supported\r
+ default:\r
+ ret = XRAN_STATUS_INVALID_PARAM;\r
+ print_err("Non-supported Section Type - %d", apphdr->sectionType);\r
+ }\r
+\r
+#if 0\r
+ printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",\r
+ result->dir?"DL":"UL",\r
+ result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,\r
+ result->sectionType, result->numSections,\r
+ result->hdr.startSymId,\r
+ result->hdr.filterIdx,\r
+ result->hdr.iqWidth, result->hdr.compMeth);\r
+\r
+ for(i=0; i<result->numSections; i++) {\r
+ printf(" || %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",\r
+ i, result->sections[i].info.id,\r
+ result->sections[i].info.rb,\r
+ result->sections[i].info.symInc, result->sections[i].info.numSymbol,\r
+ result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,\r
+ result->sections[i].info.reMask,\r
+ result->sections[i].info.beamId,\r
+ result->sections[i].info.freqOffset,\r
+ result->sections[i].info.ef);\r
+\r
+ if(result->sections[i].info.ef) {\r
+ for(int j=0; j<result->sections[i].exDataSize; j++) {\r
+ printf(" || %2d : type=%d len=%d\n",\r
+ j, result->sections[i].exData[j].type, result->sections[i].exData[j].len);\r
+ switch(result->sections[i].exData[j].type) {\r
+ case XRAN_CP_SECTIONEXTCMD_1:\r
+ {\r
+ struct xran_sectionext1_info *ext1;\r
+ ext1 = result->sections[i].exData[j].data;\r
+ printf(" || bfwNumber=%d bfwiqWidth=%d bfwCompMeth=%d\n",\r
+ ext1->bfwNumber, ext1->bfwiqWidth, ext1->bfwCompMeth);\r
+ }\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_2:\r
+ {\r
+ struct xran_sectionext2_info *ext2;\r
+ ext2 = result->sections[i].exData[j].data;\r
+ printf(" || AzPt=%02x(%d) ZePt=%02x(%d) Az3dd=%02x(%d) Ze3dd=%02x(%d) AzSI=%02x ZeSI=%02x\n",\r
+ ext2->bfAzPt, ext2->bfAzPtWidth,\r
+ ext2->bfZePt, ext2->bfZePtWidth,\r
+ ext2->bfAz3dd, ext2->bfAz3ddWidth,\r
+ ext2->bfZe3dd, ext2->bfZe3ddWidth,\r
+ ext2->bfAzSI, ext2->bfZeSI);\r
+ }\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_4:\r
+ {\r
+ struct xran_sectionext4_info *ext4;\r
+ ext4 = result->sections[i].exData[j].data;\r
+ printf(" || csf=%d modCompScaler=%d\n",\r
+ ext4->csf, ext4->modCompScaler);\r
+ }\r
+ break;\r
+ case XRAN_CP_SECTIONEXTCMD_5:\r
+ {\r
+ struct xran_sectionext5_info *ext5;\r
+ ext5 = result->sections[i].exData[j].data;\r
+ printf(" || num_sets=%d\n", ext5->num_sets);\r
+ for(int k=0; k<ext5->num_sets; k++) {\r
+ printf(" || %d - csf=%d mcScaleReMask=%04x mcScaleOffset=%04x\n",\r
+ k, ext5->mc[k].csf,\r
+ ext5->mc[k].mcScaleReMask, ext5->mc[k].mcScaleOffset);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case XRAN_CP_SECTIONEXTCMD_0:\r
+ case XRAN_CP_SECTIONEXTCMD_3:\r
+ default:\r
+ printf("Invalid section extension type!\n");\r
+ }\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+ return(ret);\r
+}\r
+\r