1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
20 * @brief This file provides the API functions to build Control Plane Messages
21 * for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01.
24 * @ingroup group_lte_source_xran
25 * @author Intel Corporation
29 #include <rte_branch_prediction.h>
31 #include "xran_common.h"
32 #include "xran_transport.h"
33 #include "xran_cp_api.h"
34 #include "xran_printf.h"
35 #include "xran_compression.h"
39 * This structure to store the section information of C-Plane
40 * in order to generate and parse corresponding U-Plane */
41 struct xran_sectioninfo_db {
42 uint32_t cur_index; /**< Current index to store for this eAXC */
43 struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /**< The array of section information */
46 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];
48 static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };
49 static const uint8_t bitmask[] = { 0x00, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
53 * @brief Initialize section database.
54 * Allocate required memory space to store section information.
55 * Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.
56 * Total entry size : number of CC * number of antenna * max number of sections * 2(direction)
58 * @ingroup xran_cp_pkt
61 * handle for xRAN interface, currently not being used
63 * XRAN_STATUS_SUCCESS on success
64 * XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area
66 int xran_cp_init_sectiondb(void *pHandle)
68 int ctx, dir, cc, ant;
70 for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)
71 for(dir=0; dir < XRAN_DIR_MAX; dir++)
72 for(cc=0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)
73 for(ant=0; ant < XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR; ant++)
74 sectiondb[ctx][dir][cc][ant].cur_index = 0;
76 return (XRAN_STATUS_SUCCESS);
80 * @brief Release and free section database
82 * @ingroup xran_cp_pkt
85 * handle for xRAN interface, currently not being used
87 * XRAN_STATUS_SUCCESS on success
89 int xran_cp_free_sectiondb(void *pHandle)
91 return (XRAN_STATUS_SUCCESS);
94 static inline struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,
95 uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
97 struct xran_sectioninfo_db *ptr;
100 if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {
101 print_err("Invalid Context id - %d", ctx_id);
105 if(unlikely(dir >= XRAN_DIR_MAX)) {
106 print_err("Invalid direction - %d", dir);
110 if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {
111 print_err("Invalid CC id - %d", cc_id);
115 if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR)) {
116 print_err("Invalid eAxC id - %d", ruport_id);
120 ptr = §iondb[ctx_id][dir][cc_id][ruport_id];
125 static inline struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
127 if(unlikely(ptr == NULL))
130 if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {
131 print_err("Index is out of range - %d", index);
135 return(&(ptr->list[index]));
139 * @brief Add a section information of C-Plane to dabase.
141 * @ingroup xran_cp_pkt
144 * handle for xRAN interface, currently not being used
146 * Direction of C-Plane message for the section to store
148 * CC ID of C-Plane message for the section to store
150 * RU port ID of C-Plane message for the section to store
152 * Context index for the section database
154 * The information of this section to store
156 * XRAN_STATUS_SUCCESS on success
157 * XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect
158 * XRAN_STATUS_RESOURCE, if no more space to add on database
160 int xran_cp_add_section_info(void *pHandle,
161 uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
162 struct xran_section_info *info)
164 struct xran_sectioninfo_db *ptr;
165 struct xran_section_info *list;
168 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
169 if(unlikely(ptr == NULL)) {
170 return (XRAN_STATUS_INVALID_PARAM);
173 if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {
174 print_err("No more space to add section information!");
175 return (XRAN_STATUS_RESOURCE);
178 list = xran_get_section_info(ptr, ptr->cur_index);
180 rte_memcpy(list, info, sizeof(struct xran_section_info));
184 return (XRAN_STATUS_SUCCESS);
187 int xran_cp_add_multisection_info(void *pHandle,
188 uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
189 struct xran_cp_gen_params *gen_info)
192 uint8_t dir, num_sections;
193 struct xran_sectioninfo_db *ptr;
194 struct xran_section_info *list;
198 num_sections = gen_info->numSections;
200 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
201 if(unlikely(ptr == NULL)) {
202 return (XRAN_STATUS_INVALID_PARAM);
205 if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {
206 print_err("No more space to add section information!");
207 return (XRAN_STATUS_RESOURCE);
210 list = xran_get_section_info(ptr, ptr->cur_index);
212 for(i=0; i<num_sections; i++) {
213 rte_memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));
217 return (XRAN_STATUS_SUCCESS);
221 * @brief Find a section information of C-Plane from dabase
222 * by given information
224 * @ingroup xran_cp_pkt
227 * handle for xRAN interface, currently not being used
229 * The direction of the section to find
231 * The CC ID of the section to find
233 * RU port ID of the section to find
235 * Context index for the section database
237 * The ID of section to find
239 * The pointer of section information if matched section is found
240 * NULL if failed to find matched section
242 struct xran_section_info *xran_cp_find_section_info(void *pHandle,
243 uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
244 uint8_t ctx_id, uint16_t section_id)
246 int index, num_index;
247 struct xran_sectioninfo_db *ptr;
250 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
251 if(unlikely(ptr == NULL))
254 if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)
255 num_index = XRAN_MAX_NUM_SECTIONS;
257 num_index = ptr->cur_index;
259 for(index=0; index < num_index; index++) {
260 if(ptr->list[index].id == section_id) {
261 return (xran_get_section_info(ptr, index));
265 print_dbg("No section ID in the list - %d", section_id);
270 * @brief Iterate each section information of C-Plane
271 * from the database of eAxC by given information
273 * @ingroup xran_cp_pkt
276 * handle for xRAN interface, currently not being used
278 * The direction of the section to find
280 * The CC ID of the section to find
282 * RU port ID of the section to find
284 * Context index for the section database
286 * The pointer to store the position of next entry
288 * The pointer of section information in the list
289 * NULL if reached at the end of the list
291 struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,
292 uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
293 uint8_t ctx_id, uint32_t *next)
296 struct xran_sectioninfo_db *ptr;
299 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
300 if(unlikely(ptr == NULL))
304 if(*next < ptr->cur_index) {
306 return (xran_get_section_info(ptr, index));
309 print_dbg("No more sections in the list");
315 * @brief Get the size of stored entries
316 * for the database of eAxC by given information
318 * @ingroup xran_cp_pkt
321 * handle for xRAN interface, currently not being used
323 * The direction of the section to find
325 * The CC ID of the section to find
327 * RU port ID of the section to find
329 * Context index for the section database
331 * The size of stored entries
332 * -1 if failed to find matched database
334 int32_t xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
337 struct xran_sectioninfo_db *ptr;
340 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
341 if(unlikely(ptr == NULL))
344 return (ptr->cur_index);
348 * @brief Reset a database of eAxC by given information
350 * @ingroup xran_cp_pkt
353 * handle for xRAN interface, currently not being used
355 * The direction of the section to find
357 * The CC ID of the section to find
359 * RU port ID of the section to find
361 * Context index for the section database
363 * XRAN_STATUS_SUCCESS on success
364 * XRAN_STATUS_INVALID_PARM if failed to find matched database
366 int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
368 struct xran_sectioninfo_db *ptr;
370 ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
371 if(unlikely(ptr == NULL)) {
372 return (XRAN_STATUS_INVALID_PARAM);
377 return (XRAN_STATUS_SUCCESS);
381 int xran_dump_sectiondb(void)
387 int32_t xran_cp_populate_section_ext_1(int8_t *p_ext1_dst, /**< destination buffer */
388 uint16_t ext1_dst_len, /**< dest buffer size */
389 int16_t *p_bfw_iq_src, /**< source buffer of IQs */
390 uint16_t rbNum, /* number RBs to ext1 chain */
391 uint16_t bfwNumPerRb, /* number of bf weights per RB (i.e. antenna elements) */
392 uint8_t bfwiqWidth, /* bit size of IQs */
393 uint8_t bfwCompMeth) /* compression method */
395 struct xran_cp_radioapp_section_ext1 *p_ext1;
397 uint8_t *p_bfw_content = NULL;
398 int32_t parm_size = 0;
399 int32_t bfw_iq_bits = 0;
400 int32_t total_len = 0;
401 int32_t comp_len = 0;
402 uint8_t ext_flag = XRAN_EF_F_ANOTHER_ONE;
404 int16_t cur_ext_len = 0;
405 int8_t *p_ext1_dst_cur = NULL;
407 struct xranlib_compress_request bfp_com_req;
408 struct xranlib_compress_response bfp_com_rsp;
410 memset(&bfp_com_req, 0, sizeof(struct xranlib_compress_request));
411 memset(&bfp_com_rsp, 0, sizeof(struct xranlib_compress_response));
413 print_dbg("%s comp %d\n", __FUNCTION__, bfwCompMeth);
414 print_dbg("bfwNumPerRb %d bfwiqWidth %d\n", bfwNumPerRb, bfwiqWidth);
417 p_ext1_dst_cur = p_ext1_dst;
419 return (XRAN_STATUS_INVALID_PARAM);
421 /* create extType=1 section for each RB */
422 for (idxRb = 0; idxRb < rbNum; idxRb++) {
423 print_dbg("%s RB %d\n", __FUNCTION__, idxRb);
425 if(total_len >= ext1_dst_len){
426 print_err("p_ext1_dst overflow\n");
430 cur_ext_len = 0; /** populate one extType=1 section with BFW for 1 RB */
431 parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
432 p_ext1 = (struct xran_cp_radioapp_section_ext1 *)p_ext1_dst_cur;
434 print_err("p_ext1 is null!\n");
435 return (XRAN_STATUS_INVALID_PARAM);
438 cur_ext_len += parm_size;
441 ext_flag = XRAN_EF_F_LAST;
443 p_ext1->extType = XRAN_CP_SECTIONEXTCMD_1;
444 p_ext1->ef = ext_flag;
445 p_ext1->bfwCompMeth = bfwCompMeth;
446 p_ext1->bfwIqWidth = XRAN_CONVERT_BFWIQWIDTH(bfwiqWidth);
448 switch(bfwCompMeth) {
449 case XRAN_BFWCOMPMETHOD_BLKFLOAT:
450 p_bfw_content = (uint8_t *)(p_ext1+1);
451 if(p_bfw_content == NULL) {
452 print_err("Fail to allocate the space for section extension 1");
453 return (XRAN_STATUS_RESOURCE);
455 bfp_com_req.data_in = (int16_t*)p_bfw_iq_src;
456 bfp_com_req.len = bfwNumPerRb*4;
457 bfp_com_req.compMethod = p_ext1->bfwCompMeth;
458 bfp_com_req.iqWidth = p_ext1->bfwIqWidth;
460 print_dbg("req 0x%08p iqWidth %d\n",bfp_com_req.data_in, bfp_com_req.iqWidth);
462 parm_size = 1; /* exponent as part of bfwCompParam 1 octet */
464 case XRAN_BFWCOMPMETHOD_BLKSCALE:
465 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
468 case XRAN_BFWCOMPMETHOD_ULAW:
469 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
472 case XRAN_BFWCOMPMETHOD_BEAMSPACE:
473 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
476 case XRAN_BFWCOMPMETHOD_NONE:
478 p_bfw_content = (uint8_t *)(p_ext1+1);
479 /* bfwCompParam is absent for no compression case */
483 if(p_bfw_content == NULL) {
484 print_err("Fail to allocate the space for section extension 1");
485 return (XRAN_STATUS_RESOURCE);
488 bfw_iq_bits = bfwNumPerRb* bfwiqWidth * 2;
490 parm_size += bfw_iq_bits>>3;
494 print_dbg("copy BF W %p -> %p size %d \n", p_bfw_iq_src, p_bfw_content, parm_size);
495 if (p_ext1->bfwIqWidth == 0 || p_ext1->bfwIqWidth == 16){
496 rte_memcpy(p_bfw_content, p_bfw_iq_src, parm_size);
498 bfp_com_rsp.data_out = (int8_t*)p_bfw_content;
499 if(xranlib_compress_avx512_bfw(&bfp_com_req, &bfp_com_rsp) == 0){
500 comp_len = bfp_com_rsp.len;
501 print_dbg("comp_len %d\n", comp_len);
503 print_err("compression failed\n");
504 return (XRAN_STATUS_FAIL);
508 p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
510 cur_ext_len += parm_size;
511 parm_size = cur_ext_len % XRAN_SECTIONEXT_ALIGN;
513 parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
514 p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
515 rte_memcpy(p_bfw_content, zeropad, parm_size);
516 cur_ext_len += parm_size;
517 print_dbg("zeropad %d cur_ext_len %d\n", parm_size, cur_ext_len);
520 if(cur_ext_len % XRAN_SECTIONEXT_ALIGN)
521 rte_panic("ext1 should be aligned on 4-bytes boundary");
523 p_ext1->extLen = cur_ext_len / XRAN_SECTIONEXT_ALIGN;
524 print_dbg("p_ext1->extLen %d\n", p_ext1->extLen);
526 /* update for next RB */
527 p_ext1_dst_cur += cur_ext_len;
528 p_bfw_iq_src = p_bfw_iq_src + bfwNumPerRb*2;
530 total_len += cur_ext_len;
533 print_dbg("total_len %d\n", total_len);
538 // Cyclic Prefix Length 5.4.4.14
539 // CP_length = cpLength * Ts, Ts = 1/30.72MHz
540 // i.e cpLength = CP_length / Ts ?
541 #define CPLEN_TS (30720000)
542 inline uint16_t xran_get_cplength(int CP_length)
547 // Frequency offset 5.4.5.11
548 // frequency_offset = freqOffset * SCS * 0.5
549 // i.e freqOffset = (frequency_offset *2 )/ SCS ?
550 inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)
555 static int xran_copy_sectionext_1(struct rte_mbuf *mbuf,
556 struct xran_sectionext1_info *params, int last_flag)
559 int8_t *p_dst = (int8_t *)rte_pktmbuf_append(mbuf, params->bfwIQ_sz);
561 print_err("Fail to allocate the space for section extension 1 [%d]", params->bfwIQ_sz);
562 return (XRAN_STATUS_RESOURCE);
565 /* copy formated extType1 with all the headers */
566 rte_memcpy(p_dst, params->p_bfwIQ, params->bfwIQ_sz);
567 total_len = params->bfwIQ_sz;
577 static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,
578 struct xran_sectionext1_info *params, int last_flag)
580 struct xran_cp_radioapp_section_ext1 *ext1;
582 int parm_size, iq_size;
587 print_dbg("%s %d\n", __FUNCTION__, last_flag);
589 parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
590 ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);
592 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
593 return (XRAN_STATUS_RESOURCE);
596 total_len += parm_size;
598 ext1->extType = XRAN_CP_SECTIONEXTCMD_1;
599 ext1->ef = last_flag;
600 ext1->bfwCompMeth = params->bfwCompMeth;
601 ext1->bfwIqWidth = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);
603 switch(params->bfwCompMeth) {
604 case XRAN_BFWCOMPMETHOD_BLKFLOAT:
606 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
608 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
609 return (XRAN_STATUS_RESOURCE);
611 total_len += parm_size;
612 *data = (params->bfwCompParam.exponent & 0x0f);
615 case XRAN_BFWCOMPMETHOD_BLKSCALE:
617 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
619 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
620 return (XRAN_STATUS_RESOURCE);
622 total_len += parm_size;
623 *data = params->bfwCompParam.blockScaler;
626 case XRAN_BFWCOMPMETHOD_ULAW:
628 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
630 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
631 return (XRAN_STATUS_RESOURCE);
633 total_len += parm_size;
634 *data = params->bfwCompParam.compBitWidthShift;
637 case XRAN_BFWCOMPMETHOD_BEAMSPACE:
638 parm_size = params->bfwNumber>>3;
639 if(params->bfwNumber%8) parm_size++;
641 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
643 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
644 return (XRAN_STATUS_RESOURCE);
646 rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
647 total_len += parm_size;
650 case XRAN_BFWCOMPMETHOD_NONE:
655 print_dbg("params->bfwNumber %d params->bfwiqWidth %d\n", params->bfwNumber, params->bfwiqWidth);
657 iq_size = params->bfwNumber * params->bfwiqWidth * 2;
659 parm_size = iq_size>>3;
663 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
665 print_err("Fail to allocate the space for section extension 1 BF W iq_size: [%d]", parm_size);
666 return (XRAN_STATUS_RESOURCE);
668 rte_memcpy(data, params->p_bfwIQ, parm_size);
670 total_len += parm_size;
671 parm_size = total_len % XRAN_SECTIONEXT_ALIGN;
673 parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
674 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
676 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
677 return (XRAN_STATUS_RESOURCE);
679 rte_memcpy(data, zeropad, parm_size);
680 total_len += parm_size;
683 ext1->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
688 static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,
689 struct xran_sectionext2_info *params, int last_flag)
691 struct xran_cp_radioapp_section_ext2 *ext2;
695 uint32_t val, shift_val;
696 int val_size, pad_size;
701 parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
702 ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
704 print_err("Fail to allocate the space for section extension 2");
705 return (XRAN_STATUS_RESOURCE);
707 total_len += parm_size;
709 ext2->extType = XRAN_CP_SECTIONEXTCMD_2;
710 ext2->ef = last_flag;
711 ext2->bfZe3ddWidth = params->bfZe3ddWidth;
712 ext2->bfAz3ddWidth = params->bfAz3ddWidth;
713 ext2->bfZePtWidth = params->bfZePtWidth;
714 ext2->bfAzPtWidth = params->bfAzPtWidth;
715 ext2->bfaCompResv0 = 0;
716 ext2->bfaCompResv1 = 0;
720 if(params->bfAzPtWidth) {
721 val += params->bfAzPt & bitmask[params->bfAzPtWidth];
722 shift_val += 8 - (params->bfAzPtWidth+1);
727 if(params->bfZePtWidth) {
728 val = val << (params->bfZePtWidth+1);
729 val += params->bfZePt & bitmask[params->bfZePtWidth];
730 shift_val += 8 - (params->bfZePtWidth+1);
735 if(params->bfAz3ddWidth) {
736 val = val << (params->bfAz3ddWidth+1);
737 val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];
738 shift_val += 8 - (params->bfAz3ddWidth+1);
743 if(params->bfZe3ddWidth) {
744 val = val << (params->bfZe3ddWidth+1);
745 val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];
746 shift_val += 8 - (params->bfZe3ddWidth+1);
752 val = val << shift_val;
753 val = rte_cpu_to_be_32(val);
756 val_size = 4 - (shift_val/8); /* ceil(total bit/8) */
757 parm_size = val_size + 1; /* additional 1 byte for bfxxSI */
760 total_len += parm_size;
761 pad_size = total_len % XRAN_SECTIONEXT_ALIGN;
763 pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;
764 parm_size += pad_size;
765 total_len += pad_size;
768 data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
770 print_err("Fail to allocate the space for section extension 2");
771 return (XRAN_STATUS_RESOURCE);
774 rte_memcpy(data, &val, val_size);
776 *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
778 rte_memcpy(data, zeropad, pad_size);
780 ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
781 *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
786 static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
787 struct xran_sectionext4_info *params, int last_flag)
789 struct xran_cp_radioapp_section_ext4 *ext4;
797 parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
798 ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
800 print_err("Fail to allocate the space for section extension 4");
801 return(XRAN_STATUS_RESOURCE);
804 total_len += parm_size;
806 ext4->extType = XRAN_CP_SECTIONEXTCMD_4;
807 ext4->ef = last_flag;
808 ext4->modCompScaler = params->modCompScaler;
809 ext4->csf = params->csf?1:0;
810 ext4->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
812 *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
818 static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
819 struct xran_sectionext5_info *params, int last_flag)
821 struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
822 struct xran_cp_radioapp_section_ext5 ext5;
829 if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {
830 print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);
834 total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)
835 + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2
836 - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust
839 padding = total_len % XRAN_SECTIONEXT_ALIGN;
841 padding = XRAN_SECTIONEXT_ALIGN - padding;
842 total_len += padding;
845 ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);
846 if(ext_hdr == NULL) {
847 print_err("Fail to allocate the space for section extension 5");
848 return (XRAN_STATUS_RESOURCE);
851 ext_hdr->extType = XRAN_CP_SECTIONEXTCMD_5;
852 ext_hdr->ef = last_flag;
853 ext_hdr->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
855 *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));
857 data = (uint8_t *)(ext_hdr + 1);
859 while(i < params->num_sets) {
860 if(i%2) { // odd index
861 ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;
862 ext5.csf2 = params->mc[i].csf;
863 ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;
867 // adding two sets at once (due to the definition of structure)
868 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
869 rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));
870 data += sizeof(struct xran_cp_radioapp_section_ext5);
873 ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;
874 ext5.csf1 = params->mc[i].csf;
875 ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;
876 ext5.mcScaleReMask2 = 0;
879 if(i == params->num_sets) { // adding last even index
880 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
881 rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);
882 data += sizeof(struct xran_cp_radioapp_section_ext5)/2;
890 rte_memcpy(data, zeropad, padding);
896 * @brief add section extension to C-Plane packet
899 * A pointer to the packet buffer
901 * A porinter to the information to generate a C-Plane packet
903 * XRAN_STATUS_SUCCESS on success
904 * XRAN_STATUS_INVALID_PARM
905 * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
907 int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
914 if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {
915 print_err("Invalid total number of extensions - %d", params->exDataSize);
916 return (XRAN_STATUS_INVALID_PARAM);
921 ret = XRAN_STATUS_SUCCESS;
923 print_dbg("params->exDataSize %d\n", params->exDataSize);
924 for(i=0; i < params->exDataSize; i++) {
925 if(params->exData[i].data == NULL) {
926 print_err("Invalid parameter - extension data %d is NULL", i);
927 ret = XRAN_STATUS_INVALID_PARAM;
931 last_flag = (params->exDataSize == (i+1))?0:1;
933 switch(params->exData[i].type) {
934 case XRAN_CP_SECTIONEXTCMD_1:
935 ext_size = xran_copy_sectionext_1(mbuf, params->exData[i].data, last_flag);
936 //xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);
938 case XRAN_CP_SECTIONEXTCMD_2:
939 ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
941 case XRAN_CP_SECTIONEXTCMD_4:
942 ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
944 case XRAN_CP_SECTIONEXTCMD_5:
945 ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
947 case XRAN_CP_SECTIONEXTCMD_0:
948 case XRAN_CP_SECTIONEXTCMD_3:
950 print_err("Extension Type %d is not supported!", params->exData[i].type);
951 ret = XRAN_STATUS_INVALID_PARAM;
955 if(ext_size == XRAN_STATUS_RESOURCE) {
967 * @brief Fill the section body of type 0 in C-Plane packet
970 * A pointer to the section in the packet buffer
972 * A porinter to the information to generate a C-Plane packet
974 * XRAN_STATUS_SUCCESS on success
975 * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
977 static int xran_prepare_section0(
978 struct xran_cp_radioapp_section0 *section,
979 struct xran_section_gen_info *params)
981 #if (XRAN_STRICT_PARM_CHECK)
982 if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
983 print_err("Invalid number of Symbols - %d", params->info.numSymbol);
984 return (XRAN_STATUS_INVALID_PARAM);
988 section->hdr.sectionId = params->info.id;
989 section->hdr.rb = params->info.rb;
990 section->hdr.symInc = params->info.symInc;
991 section->hdr.startPrbc = params->info.startPrbc;
992 section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
994 section->hdr.u.s0.reMask = params->info.reMask;
995 section->hdr.u.s0.numSymbol = params->info.numSymbol;
996 section->hdr.u.s0.reserved = 0;
998 // for network byte order
999 *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1001 return (XRAN_STATUS_SUCCESS);
1004 * @brief Fill the section header of type 0 in C-Plane packet
1007 * A pointer to the section header in the packet buffer
1009 * A porinter to the information to generate a C-Plane packet
1011 * XRAN_STATUS_SUCCESS always
1013 static int xran_prepare_section0_hdr(
1014 struct xran_cp_radioapp_section0_header *s0hdr,
1015 struct xran_cp_gen_params *params)
1018 s0hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset);
1019 s0hdr->frameStructure.fftSize = params->hdr.fftSize;
1020 s0hdr->frameStructure.uScs = params->hdr.scs;
1021 s0hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength);
1022 s0hdr->reserved = 0;
1024 return (XRAN_STATUS_SUCCESS);
1028 * @brief Fill the section body of type 1 in C-Plane packet
1029 * Extension is not supported.
1032 * A pointer to the section header in the packet buffer
1034 * A porinter to the information to generate a C-Plane packet
1036 * XRAN_STATUS_SUCCESS on success
1037 * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1039 static int xran_prepare_section1(
1040 struct xran_cp_radioapp_section1 *section,
1041 struct xran_section_gen_info *params)
1043 #if (XRAN_STRICT_PARM_CHECK)
1044 if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1045 print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1046 return (XRAN_STATUS_INVALID_PARAM);
1050 section->hdr.sectionId = params->info.id;
1051 section->hdr.rb = params->info.rb;
1052 section->hdr.symInc = params->info.symInc;
1053 section->hdr.startPrbc = params->info.startPrbc;
1054 section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1056 section->hdr.u.s1.reMask = params->info.reMask;
1057 section->hdr.u.s1.numSymbol = params->info.numSymbol;
1058 section->hdr.u.s1.beamId = params->info.beamId;
1060 section->hdr.u.s1.ef = params->info.ef;
1062 // for network byte order
1063 *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1065 return (XRAN_STATUS_SUCCESS);
1068 * @brief Fill the section header of type 1 in C-Plane packet
1071 * A pointer to the section header in the packet buffer
1073 * A porinter to the information to generate a C-Plane packet
1075 * XRAN_STATUS_SUCCESS always
1077 static int xran_prepare_section1_hdr(
1078 struct xran_cp_radioapp_section1_header *s1hdr,
1079 struct xran_cp_gen_params *params)
1081 s1hdr->udComp.udIqWidth = params->hdr.iqWidth;
1082 s1hdr->udComp.udCompMeth = params->hdr.compMeth;
1083 s1hdr->reserved = 0;
1085 return (XRAN_STATUS_SUCCESS);
1089 * @brief Fill the section body of type 3 in C-Plane packet
1090 * Extension is not supported.
1093 * A pointer to the section header in the packet buffer
1095 * A porinter to the information to generate a C-Plane packet
1097 * XRAN_STATUS_SUCCESS on success
1098 * XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1100 static int xran_prepare_section3(
1101 struct xran_cp_radioapp_section3 *section,
1102 struct xran_section_gen_info *params)
1104 #if (XRAN_STRICT_PARM_CHECK)
1105 if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1106 print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1107 return (XRAN_STATUS_INVALID_PARAM);
1111 section->hdr.sectionId = params->info.id;
1112 section->hdr.rb = params->info.rb;
1113 section->hdr.symInc = params->info.symInc;
1114 section->hdr.startPrbc = params->info.startPrbc;
1115 section->hdr.numPrbc = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1117 section->hdr.u.s3.reMask = params->info.reMask;
1118 section->hdr.u.s3.numSymbol = params->info.numSymbol;
1119 section->hdr.u.s3.beamId = params->info.beamId;
1121 section->freqOffset = rte_cpu_to_be_32(params->info.freqOffset)>>8;
1122 section->reserved = 0;
1124 section->hdr.u.s3.ef = params->info.ef;
1126 // for network byte order (header, 8 bytes)
1127 *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1129 return (XRAN_STATUS_SUCCESS);
1132 * @brief Fill the section header of type 3 in C-Plane packet
1135 * A pointer to the section header in the packet buffer
1137 * A porinter to the information to generate a C-Plane packet
1139 * XRAN_STATUS_SUCCESS always
1141 static int xran_prepare_section3_hdr(
1142 struct xran_cp_radioapp_section3_header *s3hdr,
1143 struct xran_cp_gen_params *params)
1146 s3hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset);
1147 s3hdr->frameStructure.fftSize = params->hdr.fftSize;
1148 s3hdr->frameStructure.uScs = params->hdr.scs;
1149 s3hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength);
1150 s3hdr->udComp.udIqWidth = params->hdr.iqWidth;
1151 s3hdr->udComp.udCompMeth = params->hdr.compMeth;
1153 return (XRAN_STATUS_SUCCESS);
1157 * @brief add sections to C-Plane packet
1158 * Section type 1 and 3 are supported.
1161 * A pointer to the packet buffer
1163 * A porinter to the information to generate a C-Plane packet
1165 * XRAN_STATUS_SUCCESS on success
1166 * XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
1167 * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1169 int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1171 int i, ret, ext_flag;
1175 int (*xran_prepare_section_func)(void *section, void *params);
1179 switch(params->sectionType) {
1180 case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1181 section_size = sizeof(struct xran_cp_radioapp_section0);
1182 xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section0;
1185 case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1186 section_size = sizeof(struct xran_cp_radioapp_section1);
1187 xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section1;
1190 case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1191 section_size = sizeof(struct xran_cp_radioapp_section3);
1192 xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section3;
1195 case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1196 case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1197 case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1200 xran_prepare_section_func = NULL;
1201 print_err("Section Type %d is not supported!", params->sectionType);
1202 return (XRAN_STATUS_INVALID_PARAM);
1205 if(unlikely(xran_prepare_section_func == NULL)) {
1206 print_err("Section Type %d is not supported!", params->sectionType);
1207 return (XRAN_STATUS_INVALID_PARAM);
1210 for(i=0; i < params->numSections; i++) {
1211 section = rte_pktmbuf_append(mbuf, section_size);
1212 if(section == NULL) {
1213 print_err("Fail to allocate the space for section[%d]!", i);
1214 return (XRAN_STATUS_RESOURCE);
1216 print_dbg("%s %d ef %d\n", __FUNCTION__, i, params->sections[i].info.ef);
1217 ret = xran_prepare_section_func((void *)section,
1218 (void *)¶ms->sections[i]);
1220 print_err("%s %d\n", __FUNCTION__, ret);
1223 totalen += section_size;
1225 if(params->sections[i].info.ef) {
1226 print_dbg("sections[%d].info.ef %d exDataSize %d type %d\n", i, params->sections[i].info.ef,
1227 params->sections[i].exDataSize, params->sections[i].exData[0].type);
1228 ret = xran_append_section_extensions(mbuf, ¶ms->sections[i]);
1239 * @brief fill the information of a radio application header in a C-Plane packet
1242 * A pointer to the application header in the packet buffer
1244 * A porinter to the information to generate a C-Plane packet
1246 * XRAN_STATUS_SUCCESS on success
1247 * XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
1249 static inline int xran_prepare_radioapp_common_header(
1250 struct xran_cp_radioapp_common_header *apphdr,
1251 struct xran_cp_gen_params *params)
1254 #if (XRAN_STRICT_PARM_CHECK)
1255 if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
1256 print_err("Invalid direction!");
1257 return (XRAN_STATUS_INVALID_PARAM);
1259 if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
1260 print_err("Invalid Slot ID!");
1261 return (XRAN_STATUS_INVALID_PARAM);
1263 if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
1264 print_err("Invalid Symbol ID!");
1265 return (XRAN_STATUS_INVALID_PARAM);
1269 apphdr->dataDirection = params->dir;
1270 apphdr->payloadVer = XRAN_PAYLOAD_VER;
1271 apphdr->filterIndex = params->hdr.filterIdx;
1272 apphdr->frameId = params->hdr.frameId;
1273 apphdr->subframeId = params->hdr.subframeId;
1274 apphdr->slotId = params->hdr.slotId;
1275 apphdr->startSymbolId = params->hdr.startSymId;
1276 apphdr->numOfSections = params->numSections;
1277 apphdr->sectionType = params->sectionType;
1279 /* radio app header has common parts of 4bytes for all section types */
1280 *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1282 return (XRAN_STATUS_SUCCESS);
1286 * @brief add a radio application header in a C-Plane packet
1289 * A pointer to the packet buffer
1291 * A porinter to the information to generate a C-Plane packet
1293 * The length of added section (>0) on success
1294 * XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
1295 * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1297 int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1301 struct xran_cp_radioapp_common_header *apphdr;
1302 int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
1305 #if (XRAN_STRICT_PARM_CHECK)
1306 if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
1307 print_err("Invalid Section Type - %d", params->sectionType);
1308 return (XRAN_STATUS_INVALID_PARAM);
1312 switch(params->sectionType) {
1313 case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1314 xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;
1315 totalen = sizeof(struct xran_cp_radioapp_section0_header);
1318 case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1319 xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;
1320 totalen = sizeof(struct xran_cp_radioapp_section1_header);
1323 case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1324 xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;
1325 totalen = sizeof(struct xran_cp_radioapp_section3_header);
1328 case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1329 case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1330 case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1332 print_err("Section Type %d is not supported!", params->sectionType);
1333 xran_prepare_radioapp_section_hdr_func = NULL;
1335 return (XRAN_STATUS_INVALID_PARAM);
1338 apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
1339 if(unlikely(apphdr == NULL)) {
1340 print_err("Fail to reserve the space for radio application header!");
1341 return (XRAN_STATUS_RESOURCE);
1344 ret = xran_prepare_radioapp_common_header(apphdr, params);
1345 if(unlikely(ret < 0)) {
1349 if(likely(xran_prepare_radioapp_section_hdr_func)) {
1350 totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
1353 print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
1354 return (XRAN_STATUS_INVALID_PARAM);
1361 * @brief Create a C-Plane packet
1362 * Transport layer fragmentation is not supported.
1364 * @ingroup xran_cp_pkt
1367 * A pointer to the packet buffer
1369 * A porinter to the information to generate a C-Plane packet
1371 * Component Carrier ID for this C-Plane message
1373 * Antenna ID(RU Port ID) for this C-Plane message
1375 * Sequence ID for this C-Plane message
1377 * XRAN_STATUS_SUCCESS on success
1378 * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1379 * XRAN_STATUS_INVALID_PARM if section type is invalid
1381 int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
1382 struct xran_cp_gen_params *params,
1383 uint8_t CC_ID, uint8_t Ant_ID,
1387 uint32_t payloadlen;
1388 struct xran_ecpri_hdr *ecpri_hdr;
1391 payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
1393 ret = xran_append_radioapp_header(mbuf, params);
1395 print_err("%s %d\n", __FUNCTION__, ret);
1400 ret = xran_append_control_section(mbuf, params);
1402 print_err("%s %d\n", __FUNCTION__, ret);
1407 /* set payload length */
1408 ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
1410 return (XRAN_STATUS_SUCCESS);
1414 ///////////////////////////////////////
1416 int xran_parse_section_ext1(void *ext,
1417 struct xran_sectionext1_info *extinfo)
1421 struct xran_cp_radioapp_section_ext1 *ext1;
1423 int parm_size, iq_size;
1428 N = xran_get_conf_num_bfweights(pHandle);
1429 extinfo->bfwNumber = N;
1431 ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
1432 data = (uint8_t *)ext;
1435 total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
1437 extinfo->bfwCompMeth = ext1->bfwCompMeth;
1438 extinfo->bfwiqWidth = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
1440 len += sizeof(struct xran_cp_radioapp_section_ext1);
1441 data += sizeof(struct xran_cp_radioapp_section_ext1);
1443 switch(ext1->bfwCompMeth) {
1444 case XRAN_BFWCOMPMETHOD_NONE:
1448 case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1450 extinfo->bfwCompParam.exponent = *data & 0x0f;
1453 case XRAN_BFWCOMPMETHOD_BLKSCALE:
1455 extinfo->bfwCompParam.blockScaler = *data;
1458 case XRAN_BFWCOMPMETHOD_ULAW:
1460 extinfo->bfwCompParam.compBitWidthShift = *data;
1463 case XRAN_BFWCOMPMETHOD_BEAMSPACE:
1464 parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
1465 rte_memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
1469 print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
1476 /* Get BF weights */
1477 iq_size = N * extinfo->bfwiqWidth * 2; // total in bits
1478 parm_size = iq_size>>3; // total in bytes (/8)
1479 if(iq_size%8) parm_size++; // round up
1481 //rte_memcpy(data, extinfo->p_bfwIQ, parm_size);
1482 extinfo->p_bfwIQ = (int16_t*)data;
1486 parm_size = len % XRAN_SECTIONEXT_ALIGN;
1488 len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1490 if(len != total_len) {
1491 // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
1497 int xran_parse_section_ext2(void *ext,
1498 struct xran_sectionext2_info *extinfo)
1502 struct xran_cp_radioapp_section_ext2 *ext2;
1509 ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
1510 data = (uint8_t *)ext;
1511 *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
1514 total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
1516 parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
1518 extinfo->bfAzPtWidth = ext2->bfAzPtWidth;
1519 extinfo->bfZePtWidth = ext2->bfZePtWidth;
1520 extinfo->bfAz3ddWidth = ext2->bfAz3ddWidth;
1521 extinfo->bfZe3ddWidth = ext2->bfZe3ddWidth;
1523 if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
1524 print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
1529 val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
1530 + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
1531 + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
1532 + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
1534 val = rte_cpu_to_be_32(*(uint32_t *)data);
1535 val >>= (32 - val_size);
1537 if(extinfo->bfZe3ddWidth) {
1538 extinfo->bfZe3dd = val & bitmask[extinfo->bfZe3ddWidth];
1539 val >>= (extinfo->bfZe3ddWidth + 1);
1541 if(extinfo->bfAz3ddWidth) {
1542 extinfo->bfAz3dd = val & bitmask[extinfo->bfAz3ddWidth];
1543 val >>= (extinfo->bfAz3ddWidth + 1);
1545 if(extinfo->bfZePtWidth) {
1546 extinfo->bfZePt = val & bitmask[extinfo->bfZePtWidth];
1547 val >>= (extinfo->bfZePtWidth + 1);
1549 if(extinfo->bfAzPtWidth) {
1550 extinfo->bfAzPt = val & bitmask[extinfo->bfAzPtWidth];
1551 val >>= (extinfo->bfAzPtWidth + 1);
1555 parm_size = val_size/8;
1556 if(val_size%8) parm_size += 1;
1561 extinfo->bfAzSI = (*data >> 3) & 0x07;
1562 extinfo->bfZeSI = *data & 0x07;
1567 parm_size = len % XRAN_SECTIONEXT_ALIGN;
1569 len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1571 if(len != total_len) {
1572 print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
1579 int xran_parse_section_ext4(void *ext,
1580 struct xran_sectionext4_info *extinfo)
1583 struct xran_cp_radioapp_section_ext4 *ext4;
1587 ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
1589 *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t *)ext4);
1592 total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
1594 extinfo->modCompScaler = ext4->modCompScaler;
1595 extinfo->csf = ext4->csf;
1598 len += sizeof(struct xran_cp_radioapp_section_ext4);
1599 if(len != total_len) {
1600 print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
1606 int xran_parse_section_ext5(void *ext,
1607 struct xran_sectionext5_info *extinfo)
1610 struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
1611 struct xran_cp_radioapp_section_ext5 ext5;
1618 ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
1619 *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*(uint16_t *)ext_hdr);
1621 total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
1623 // one set has 3.5 bytes, so enforcing double to do integer calculation
1624 parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
1626 if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
1627 print_err("Exceeds maximum number of parameters - %d", parm_size);
1628 parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
1632 data = (uint8_t *)(ext_hdr + 1);
1635 while(i < parm_size) {
1636 // For odd number set, more data can be copied
1637 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)data));
1639 extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset1;
1640 extinfo->mc[i].csf = ext5.csf1;
1641 extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask1;
1644 extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset2;
1645 extinfo->mc[i].csf = ext5.csf2;
1646 extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask2;
1649 data += sizeof(struct xran_cp_radioapp_section_ext5);
1652 // check the values of last set
1653 // due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
1654 // don't check mcScaleOffset might not be zero (some part is out of zero-padding)
1656 if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
1657 if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
1658 extinfo->num_sets = i;
1660 extinfo->num_sets = i+1;
1662 print_err("Maximum total number %d is not correct!", i);
1668 int xran_parse_section_extension(struct rte_mbuf *mbuf,
1670 struct xran_section_gen_info *section)
1672 int total_len, len, numext;
1679 ptr = (uint8_t *)ext;
1687 flag_last = (*ptr & 0x80);
1689 ext_type = *ptr & 0x7f;
1690 section->exData[numext].type = ext_type;
1692 case XRAN_CP_SECTIONEXTCMD_1:
1693 section->exData[numext].data = §ion->m_ext1[numext];
1694 len = xran_parse_section_ext1(ptr, section->exData[numext].data);
1695 section->exData[numext].len = len;
1697 case XRAN_CP_SECTIONEXTCMD_2:
1698 section->exData[numext].data = §ion->m_ext2[numext];
1699 len = xran_parse_section_ext2(ptr, section->exData[numext].data);
1701 case XRAN_CP_SECTIONEXTCMD_4:
1702 section->exData[numext].data = §ion->m_ext4[numext];
1703 len = xran_parse_section_ext4(ptr, section->exData[numext].data);
1705 case XRAN_CP_SECTIONEXTCMD_5:
1706 section->exData[numext].data = §ion->m_ext5[numext];
1707 len = xran_parse_section_ext5(ptr, section->exData[numext].data);
1710 case XRAN_CP_SECTIONEXTCMD_0:
1711 case XRAN_CP_SECTIONEXTCMD_3:
1713 print_err("Extension %d is not supported!", ext_type);
1717 section->exData[numext].len = len;
1718 ptr += len; total_len += len;
1721 if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
1723 /* exceeds maximum number of extensions */
1727 section->exDataSize = numext;
1734 * @brief Parse a C-Plane packet (for RU emulation)
1735 * Transport layer fragmentation is not supported.
1737 * @ingroup xran_cp_pkt
1740 * The pointer of the packet buffer to be parsed
1742 * The pointer of structure to store the information of parsed packet
1744 * The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
1746 * XRAN_STATUS_SUCCESS on success
1747 * XRAN_STATUS_INVALID_PACKET if failed to parse the packet
1749 int xran_parse_cp_pkt(struct rte_mbuf *mbuf,
1750 struct xran_cp_gen_params *result,
1751 struct xran_recv_packet_info *pkt_info)
1753 struct xran_ecpri_hdr *ecpri_hdr;
1754 struct xran_cp_radioapp_common_header *apphdr;
1759 ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
1760 if(ret < 0 && ecpri_hdr == NULL)
1761 return (XRAN_STATUS_INVALID_PACKET);
1763 /* Process radio header. */
1764 apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
1765 if(apphdr == NULL) {
1766 print_err("Invalid packet - radio app hedaer!");
1767 return (XRAN_STATUS_INVALID_PACKET);
1770 *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1772 if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {
1773 print_err("Invalid Payload version - %d", apphdr->payloadVer);
1774 ret = XRAN_STATUS_INVALID_PACKET;
1777 result->dir = apphdr->dataDirection;
1778 result->hdr.filterIdx = apphdr->filterIndex;
1779 result->hdr.frameId = apphdr->frameId;
1780 result->hdr.subframeId = apphdr->subframeId;
1781 result->hdr.slotId = apphdr->slotId;
1782 result->hdr.startSymId = apphdr->startSymbolId;
1783 result->sectionType = apphdr->sectionType;
1784 result->numSections = apphdr->numOfSections;
1787 printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
1788 pkt_info->payload_len,
1789 pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
1790 pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
1791 result->dir?"DL":"UL",
1792 pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
1793 result->sectionType, result->numSections,
1794 result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1795 result->hdr.startSymId
1799 switch(apphdr->sectionType) {
1800 case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
1802 struct xran_cp_radioapp_section0_header *hdr;
1803 struct xran_cp_radioapp_section0 *section;
1805 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
1807 result->hdr.fftSize = rte_be_to_cpu_16(hdr->timeOffset);
1808 result->hdr.scs = hdr->frameStructure.fftSize;
1809 result->hdr.timeOffset = hdr->frameStructure.uScs;
1810 result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength);
1811 //hdr->reserved; /* should be zero */
1813 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
1814 if(section == NULL) {
1815 print_err("Invalid packet 0 - radio app hedaer!");
1816 return (XRAN_STATUS_INVALID_PACKET);
1818 for(i=0; i<result->numSections; i++) {
1819 *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1821 result->sections[i].info.type = apphdr->sectionType;
1822 result->sections[i].info.id = section->hdr.sectionId;
1823 result->sections[i].info.rb = section->hdr.rb;
1824 result->sections[i].info.symInc = section->hdr.symInc;
1825 result->sections[i].info.startPrbc = section->hdr.startPrbc;
1826 result->sections[i].info.numPrbc = section->hdr.numPrbc,
1827 result->sections[i].info.numSymbol = section->hdr.u.s0.numSymbol;
1828 result->sections[i].info.reMask = section->hdr.u.s0.reMask;
1829 //section->hdr.u.s0.reserved; /* should be zero */
1831 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
1832 if(section == NULL) {
1833 print_err("Invalid packet 0 - number of section [%d:%d]!",
1834 result->numSections, i);
1835 result->numSections = i;
1836 ret = XRAN_STATUS_INVALID_PACKET;
1843 case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
1845 struct xran_cp_radioapp_section1_header *hdr;
1846 struct xran_cp_radioapp_section1 *section;
1848 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
1850 result->hdr.iqWidth = hdr->udComp.udIqWidth;
1851 result->hdr.compMeth = hdr->udComp.udCompMeth;
1853 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
1854 if(section == NULL) {
1855 print_err("Invalid packet 1 - radio app hedaer!");
1856 return (XRAN_STATUS_INVALID_PACKET);
1859 for(i=0; i<result->numSections; i++) {
1860 *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1862 result->sections[i].info.type = apphdr->sectionType;
1863 result->sections[i].info.id = section->hdr.sectionId;
1864 result->sections[i].info.rb = section->hdr.rb;
1865 result->sections[i].info.symInc = section->hdr.symInc;
1866 result->sections[i].info.startPrbc = section->hdr.startPrbc;
1867 result->sections[i].info.numPrbc = section->hdr.numPrbc,
1868 result->sections[i].info.numSymbol = section->hdr.u.s1.numSymbol;
1869 result->sections[i].info.reMask = section->hdr.u.s1.reMask;
1870 result->sections[i].info.beamId = section->hdr.u.s1.beamId;
1871 result->sections[i].info.ef = section->hdr.u.s1.ef;
1873 section = (void *)rte_pktmbuf_adj(mbuf,
1874 sizeof(struct xran_cp_radioapp_section1));
1875 if(section == NULL) {
1876 print_err("Invalid packet 1 - number of section [%d:%d]!",
1877 result->numSections, i);
1878 result->numSections = i;
1879 ret = XRAN_STATUS_INVALID_PACKET;
1883 if(result->sections[i].info.ef) {
1884 // parse section extension
1885 extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
1887 section = (void *)rte_pktmbuf_adj(mbuf, extlen);
1888 if(section == NULL) {
1889 print_err("Invalid packet 1 - section extension [%d]!", i);
1890 ret = XRAN_STATUS_INVALID_PACKET;
1900 case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
1902 struct xran_cp_radioapp_section3_header *hdr;
1903 struct xran_cp_radioapp_section3 *section;
1905 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
1907 result->hdr.timeOffset = rte_be_to_cpu_16(hdr->timeOffset);
1908 result->hdr.scs = hdr->frameStructure.uScs;
1909 result->hdr.fftSize = hdr->frameStructure.fftSize;
1910 result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength);
1911 result->hdr.iqWidth = hdr->udComp.udIqWidth;
1912 result->hdr.compMeth = hdr->udComp.udCompMeth;
1914 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
1915 if(section == NULL) {
1916 print_err("Invalid packet 3 - radio app hedaer!");
1917 return (XRAN_STATUS_INVALID_PACKET);
1920 for(i=0; i<result->numSections; i++) {
1921 *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1923 result->sections[i].info.type = apphdr->sectionType;
1924 result->sections[i].info.id = section->hdr.sectionId;
1925 result->sections[i].info.rb = section->hdr.rb;
1926 result->sections[i].info.symInc = section->hdr.symInc;
1927 result->sections[i].info.startPrbc = section->hdr.startPrbc;
1928 result->sections[i].info.numPrbc = section->hdr.numPrbc,
1929 result->sections[i].info.numSymbol = section->hdr.u.s3.numSymbol;
1930 result->sections[i].info.reMask = section->hdr.u.s3.reMask;
1931 result->sections[i].info.beamId = section->hdr.u.s3.beamId;
1932 result->sections[i].info.ef = section->hdr.u.s3.ef;
1933 result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
1935 if(section->reserved) {
1936 print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);
1937 ret = XRAN_STATUS_INVALID_PACKET;
1940 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3));
1941 if(section == NULL) {
1942 print_err("Invalid packet 3 - number of section [%d:%d]!",
1943 result->numSections, i);
1944 result->numSections = i;
1945 ret = XRAN_STATUS_INVALID_PACKET;
1949 if(result->sections[i].info.ef) {
1950 // parse section extension
1951 extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
1953 section = (void *)rte_pktmbuf_adj(mbuf, extlen);
1954 if(section == NULL) {
1955 print_err("Invalid packet 3 - section extension [%d]!", i);
1956 ret = XRAN_STATUS_INVALID_PACKET;
1966 case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
1967 case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
1968 case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
1970 ret = XRAN_STATUS_INVALID_PARAM;
1971 print_err("Non-supported Section Type - %d", apphdr->sectionType);
1975 printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
1976 result->dir?"DL":"UL",
1977 result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1978 result->sectionType, result->numSections,
1979 result->hdr.startSymId,
1980 result->hdr.filterIdx,
1981 result->hdr.iqWidth, result->hdr.compMeth);
1983 for(i=0; i<result->numSections; i++) {
1984 printf(" || %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
1985 i, result->sections[i].info.id,
1986 result->sections[i].info.rb,
1987 result->sections[i].info.symInc, result->sections[i].info.numSymbol,
1988 result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
1989 result->sections[i].info.reMask,
1990 result->sections[i].info.beamId,
1991 result->sections[i].info.freqOffset,
1992 result->sections[i].info.ef);
1994 if(result->sections[i].info.ef) {
1995 for(int j=0; j<result->sections[i].exDataSize; j++) {
1996 printf(" || %2d : type=%d len=%d\n",
1997 j, result->sections[i].exData[j].type, result->sections[i].exData[j].len);
1998 switch(result->sections[i].exData[j].type) {
1999 case XRAN_CP_SECTIONEXTCMD_1:
2001 struct xran_sectionext1_info *ext1;
2002 ext1 = result->sections[i].exData[j].data;
2003 printf(" || bfwNumber=%d bfwiqWidth=%d bfwCompMeth=%d\n",
2004 ext1->bfwNumber, ext1->bfwiqWidth, ext1->bfwCompMeth);
2007 case XRAN_CP_SECTIONEXTCMD_2:
2009 struct xran_sectionext2_info *ext2;
2010 ext2 = result->sections[i].exData[j].data;
2011 printf(" || AzPt=%02x(%d) ZePt=%02x(%d) Az3dd=%02x(%d) Ze3dd=%02x(%d) AzSI=%02x ZeSI=%02x\n",
2012 ext2->bfAzPt, ext2->bfAzPtWidth,
2013 ext2->bfZePt, ext2->bfZePtWidth,
2014 ext2->bfAz3dd, ext2->bfAz3ddWidth,
2015 ext2->bfZe3dd, ext2->bfZe3ddWidth,
2016 ext2->bfAzSI, ext2->bfZeSI);
2019 case XRAN_CP_SECTIONEXTCMD_4:
2021 struct xran_sectionext4_info *ext4;
2022 ext4 = result->sections[i].exData[j].data;
2023 printf(" || csf=%d modCompScaler=%d\n",
2024 ext4->csf, ext4->modCompScaler);
2027 case XRAN_CP_SECTIONEXTCMD_5:
2029 struct xran_sectionext5_info *ext5;
2030 ext5 = result->sections[i].exData[j].data;
2031 printf(" || num_sets=%d\n", ext5->num_sets);
2032 for(int k=0; k<ext5->num_sets; k++) {
2033 printf(" || %d - csf=%d mcScaleReMask=%04x mcScaleOffset=%04x\n",
2035 ext5->mc[k].mcScaleReMask, ext5->mc[k].mcScaleOffset);
2040 case XRAN_CP_SECTIONEXTCMD_0:
2041 case XRAN_CP_SECTIONEXTCMD_3:
2043 printf("Invalid section extension type!\n");