O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fhi_lib / lib / src / xran_cp_api.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 Intel.
4 *
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
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 *******************************************************************************/
18
19 /**
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.
22  *
23  * @file xran_cp_api.c
24  * @ingroup group_lte_source_xran
25  * @author Intel Corporation
26  *
27  **/
28 #include <immintrin.h>
29 #include <rte_branch_prediction.h>
30 #include <rte_malloc.h>
31
32 #include "ethdi.h"
33 #include "xran_common.h"
34 #include "xran_transport.h"
35 #include "xran_cp_api.h"
36 #include "xran_printf.h"
37 #include "xran_compression.h"
38 #include "xran_dev.h"
39
40 PSECTION_DB_TYPE p_sectiondb[XRAN_PORTS_NUM] = {NULL, NULL, NULL, NULL};
41
42 static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };
43 static const uint8_t bitmask[] = { 0x00, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
44
45
46 /**
47  * @brief Initialize section database.
48  *   Allocate required memory space to store section information.
49  *   Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.
50  *   Total entry size : number of CC * number of antenna * max number of sections * 2(direction)
51  *
52  * @ingroup xran_cp_pkt
53  *
54  * @param pHandle
55  *  handle for xRAN interface, currently not being used
56  * @return
57  *  XRAN_STATUS_SUCCESS on success
58  *  XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area
59  */
60 int32_t
61 xran_cp_init_sectiondb(void *pHandle)
62 {
63     int32_t ctx, dir, cc, ant;
64     struct xran_device_ctx* p_dev = NULL;
65     uint8_t xran_port_id = 0;
66     PSECTION_DB_TYPE p_sec_db =  NULL;
67     struct xran_sectioninfo_db* p_sec_db_elm = NULL;
68
69     if(pHandle) {
70         p_dev = (struct xran_device_ctx* )pHandle;
71         xran_port_id = p_dev->xran_port_id;
72     } else {
73         print_err("Invalid pHandle - %p", pHandle);
74         return (XRAN_STATUS_FAIL);
75     }
76
77     if (p_sectiondb[xran_port_id] == NULL){
78         p_sec_db = rte_zmalloc(NULL,sizeof(SECTION_DB_TYPE), 0);
79         if(p_sec_db){
80             p_sectiondb[xran_port_id] = p_sec_db;
81             memset(p_sec_db, 0, sizeof(SECTION_DB_TYPE));
82             print_dbg("xran_port_id %d %p\n",xran_port_id,  p_sectiondb[xran_port_id]);
83             for (ctx = 0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++) {
84                 for (dir = 0; dir < XRAN_DIR_MAX; dir++) {
85                     for (cc = 0; cc < p_dev->fh_cfg.nCC && cc < XRAN_COMPONENT_CARRIERS_MAX; cc++) {
86                         for (ant = 0; ant < (p_dev->fh_cfg.neAxc*2 + p_dev->fh_cfg.nAntElmTRx) && ant < (XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR); ant++) {
87                             p_sec_db_elm = (struct xran_sectioninfo_db*)rte_zmalloc(NULL,sizeof(struct xran_sectioninfo_db), 0);
88                             if(p_sec_db_elm) {
89                                 memset(p_sec_db_elm, 0, sizeof(struct xran_sectioninfo_db));
90                                 p_sec_db->p_sectiondb_elm[ctx][dir][cc][ant] = p_sec_db_elm;
91                             } else {
92                                 print_err("Memory Allocation Failed [port %d sz %ld]\n", xran_port_id, sizeof(struct xran_sectioninfo_db));
93                                 return (XRAN_STATUS_RESOURCE);
94                             }
95                         }
96                     }
97                 }
98             }
99         } else {
100             print_err("Memory Allocation Failed [port %d sz %ld]\n", xran_port_id, sizeof(SECTION_DB_TYPE));
101             return (XRAN_STATUS_RESOURCE);
102         }
103     }else {
104         p_sec_db = p_sectiondb[xran_port_id];
105     }
106
107     for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)
108         for(dir=0; dir < XRAN_DIR_MAX; dir++)
109             for (cc = 0; cc < p_dev->fh_cfg.nCC && cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)
110                 for (ant = 0; ant < (p_dev->fh_cfg.neAxc*2 + p_dev->fh_cfg.nAntElmTRx) && ant < (XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR); ant++)
111                     if(p_sec_db->p_sectiondb_elm[ctx][dir][cc][ant])
112                         p_sec_db->p_sectiondb_elm[ctx][dir][cc][ant]->cur_index = 0;
113
114     return (XRAN_STATUS_SUCCESS);
115 }
116
117 /**
118  * @brief Release and free section database
119  *
120  * @ingroup xran_cp_pkt
121  *
122  * @param pHandle
123  *  handle for xRAN interface, currently not being used
124  * @return
125  *  XRAN_STATUS_SUCCESS on success
126  */
127 int32_t
128 xran_cp_free_sectiondb(void *pHandle)
129 {
130     int32_t ctx, dir, cc, ant;
131     struct xran_device_ctx* p_dev = NULL;
132     uint8_t xran_port_id = 0;
133     PSECTION_DB_TYPE p_sec_db =  NULL;
134
135     if(pHandle) {
136         p_dev = (struct xran_device_ctx* )pHandle;
137         xran_port_id = p_dev->xran_port_id;
138     } else {
139         print_err("Invalid pHandle - %p", pHandle);
140         return (XRAN_STATUS_FAIL);
141     }
142
143     if (p_sectiondb[xran_port_id] == NULL){
144         return (XRAN_STATUS_INVALID_PARAM);
145     } else {
146         p_sec_db = p_sectiondb[xran_port_id];
147         for (ctx = 0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++) {
148             for (dir = 0; dir < XRAN_DIR_MAX; dir++) {
149                 for (cc = 0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++) {
150                     for (ant = 0; ant < (XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR); ant++) {
151                         if(p_sec_db->p_sectiondb_elm[ctx][dir][cc][ant])
152                             rte_free(p_sec_db->p_sectiondb_elm[ctx][dir][cc][ant]);
153                     }
154                 }
155             }
156         }
157         rte_free(p_sec_db);
158         p_sectiondb[xran_port_id] = NULL;
159     }
160
161     return (XRAN_STATUS_SUCCESS);
162 }
163
164 static inline struct xran_sectioninfo_db *
165 xran_get_section_db(void *pHandle,
166         uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
167 {
168   struct xran_sectioninfo_db *ptr;
169     struct xran_device_ctx* p_dev = NULL;
170     uint8_t xran_port_id = 0;
171     PSECTION_DB_TYPE p_sec_db =  NULL;
172
173     if(pHandle) {
174         p_dev = (struct xran_device_ctx* )pHandle;
175         xran_port_id = p_dev->xran_port_id;
176     } else {
177         print_err("Invalid pHandle - %p", pHandle);
178         return (NULL);
179     }
180
181     if(unlikely(xran_port_id >= XRAN_PORTS_NUM)) {
182         print_err("Invalid Port id - %d", p_dev->xran_port_id);
183         return (NULL);
184     }
185
186     if (p_sectiondb[xran_port_id] == NULL){
187         print_err("p_sectiondb xran_port %d\n", xran_port_id);
188         return (NULL);
189     }else {
190         p_sec_db = p_sectiondb[xran_port_id];
191     }
192     if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {
193         print_err("Invalid Context id - %d", ctx_id);
194         return (NULL);
195         }
196
197     if(unlikely(dir >= XRAN_DIR_MAX)) {
198         print_err("Invalid direction - %d", dir);
199         return (NULL);
200         }
201
202     if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {
203         print_err("Invalid CC id - %d", cc_id);
204         return (NULL);
205         }
206
207     if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR)) {
208         print_err("Invalid eAxC id - %d", ruport_id);
209         return (NULL);
210         }
211
212     ptr = p_sec_db->p_sectiondb_elm[ctx_id][dir][cc_id][ruport_id];
213
214     return(ptr);
215 }
216
217 static inline struct xran_section_info *
218 xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
219 {
220     if(unlikely(ptr == NULL))
221         return (NULL);
222
223     if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {
224         print_err("Index is out of range - %d", index);
225         return (NULL);
226         }
227
228     return(&(ptr->list[index]));
229 }
230
231 /**
232  * @brief Add a section information of C-Plane to dabase.
233  *
234  * @ingroup xran_cp_pkt
235  *
236  * @param pHandle
237  *  handle for xRAN interface, currently not being used
238  * @param dir
239  *  Direction of C-Plane message for the section to store
240  * @param cc_id
241  *  CC ID of C-Plane message for the section to store
242  * @param ruport_id
243  *  RU port ID of C-Plane message for the section to store
244  * @param ctx_id
245  *  Context index for the section database
246  * @param info
247  *  The information of this section to store
248  * @return
249  *  XRAN_STATUS_SUCCESS on success
250  *  XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect
251  *  XRAN_STATUS_RESOURCE, if no more space to add on database
252  */
253 int32_t
254 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)
255 {
256   struct xran_sectioninfo_db *ptr;
257   struct xran_section_info *list;
258
259     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
260     if(unlikely(ptr == NULL)) {
261         return (XRAN_STATUS_INVALID_PARAM);
262         }
263
264     if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {
265         print_err("No more space to add section information!");
266         return (XRAN_STATUS_RESOURCE);
267         }
268
269     list = xran_get_section_info(ptr, ptr->cur_index);
270     if (list)
271         memcpy(list, info, sizeof(struct xran_section_info));
272     else
273     {
274         print_err("Null list in section db\n!");
275         return (XRAN_STATUS_INVALID_PARAM);
276     }
277
278     ptr->cur_index++;
279
280     return (XRAN_STATUS_SUCCESS);
281 }
282
283 int32_t
284 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)
285 {
286     int32_t i;
287   uint8_t dir, num_sections;
288   struct xran_sectioninfo_db *ptr;
289   struct xran_section_info *list;
290
291     dir             = gen_info->dir;
292     num_sections    = gen_info->numSections;
293
294     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
295     if(unlikely(ptr == NULL)) {
296         return (XRAN_STATUS_INVALID_PARAM);
297         }
298
299     if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {
300         print_err("No more space to add section information!");
301         return (XRAN_STATUS_RESOURCE);
302         }
303
304     list = xran_get_section_info(ptr, ptr->cur_index);
305     if (list)
306     {
307     for(i=0; i<num_sections; i++) {
308             memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));
309         ptr->cur_index++;
310         }
311     }
312     else
313     {
314         print_err("Null list in section db\n!");
315         return (XRAN_STATUS_INVALID_PARAM);
316     }
317
318     return (XRAN_STATUS_SUCCESS);
319 }
320
321 /**
322  * @brief Find a section information of C-Plane from database
323  *   by given information
324  *
325  * @ingroup xran_cp_pkt
326  *
327  * @param pHandle
328  *  handle for xRAN interface, currently not being used
329  * @param dir
330  *  The direction of the section to find
331  * @param cc_id
332  *  The CC ID of the section to find
333  * @param ruport_id
334  *  RU port ID of the section to find
335  * @param ctx_id
336  *  Context index for the section database
337  * @param section_id
338  *  The ID of section to find
339  * @return
340  *  The pointer of section information if matched section is found
341  *  NULL if failed to find matched section
342  */
343 struct xran_section_info *
344 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)
345 {
346     int32_t index, num_index;
347   struct xran_sectioninfo_db *ptr;
348
349     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
350     if(unlikely(ptr == NULL))
351         return (NULL);
352
353     if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)
354         num_index = XRAN_MAX_NUM_SECTIONS;
355     else
356         num_index = ptr->cur_index;
357
358     for(index=0; index < num_index; index++) {
359         if(ptr->list[index].id == section_id) {
360             return (xran_get_section_info(ptr, index));
361             }
362         }
363
364     print_dbg("No section ID in the list - %d", section_id);
365     return (NULL);
366 }
367
368 /**
369  * @brief Iterate each section information of C-Plane
370  *  from the database of eAxC by given information
371  *
372  * @ingroup xran_cp_pkt
373  *
374  * @param pHandle
375  *  handle for xRAN interface, currently not being used
376  * @param dir
377  *  The direction of the section to find
378  * @param cc_id
379  *  The CC ID of the section to find
380  * @param ruport_id
381  *  RU port ID of the section to find
382  * @param ctx_id
383  *  Context index for the section database
384  * @param next
385  *  The pointer to store the position of next entry
386  * @return
387  *  The pointer of section information in the list
388  *  NULL if reached at the end of the list
389  */
390 struct xran_section_info *
391 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)
392 {
393     int32_t index;
394   struct xran_sectioninfo_db *ptr;
395
396     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
397     if(unlikely(ptr == NULL))
398         return (NULL);
399
400     index = *next;
401     if(*next < ptr->cur_index) {
402         (*next)++;
403         return (xran_get_section_info(ptr, index));
404         }
405     else {
406         print_dbg("No more sections in the list");
407         return (NULL);
408         }
409 }
410
411 /**
412  * @brief Get the size of stored entries
413  *  for the database of eAxC by given information
414  *
415  * @ingroup xran_cp_pkt
416  *
417  * @param pHandle
418  *  handle for xRAN interface, currently not being used
419  * @param dir
420  *  The direction of the section to find
421  * @param cc_id
422  *  The CC ID of the section to find
423  * @param ruport_id
424  *  RU port ID of the section to find
425  * @param ctx_id
426  *  Context index for the section database
427  * @return
428  *  The size of stored entries
429  *  -1 if failed to find matched database
430  */
431 int32_t
432 xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
433 {
434     int32_t index;
435   struct xran_sectioninfo_db *ptr;
436
437     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
438     if(unlikely(ptr == NULL))
439         return (-1);
440
441     return (ptr->cur_index);
442 }
443
444 /**
445  * @brief Reset a database of eAxC by given information
446  *
447  * @ingroup xran_cp_pkt
448  *
449  * @param pHandle
450  *  handle for xRAN interface, currently not being used
451  * @param dir
452  *  The direction of the section to find
453  * @param cc_id
454  *  The CC ID of the section to find
455  * @param ruport_id
456  *  RU port ID of the section to find
457  * @param ctx_id
458  *  Context index for the section database
459  * @return
460  *  XRAN_STATUS_SUCCESS on success
461  *  XRAN_STATUS_INVALID_PARM if failed to find matched database
462  */
463 int32_t
464 xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
465 {
466   struct xran_sectioninfo_db *ptr;
467
468     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
469     if(unlikely(ptr == NULL)) {
470         return (XRAN_STATUS_INVALID_PARAM);
471         }
472
473     ptr->cur_index = 0;
474
475     return (XRAN_STATUS_SUCCESS);
476 }
477
478 int32_t xran_cp_populate_section_ext_1(int8_t  *p_ext1_dst,    /**< destination buffer */
479                                        uint16_t  ext1_dst_len, /**< dest buffer size */
480                                        int16_t  *p_bfw_iq_src, /**< source buffer of IQs */
481                                        uint16_t  rbNum,        /* number RBs to ext1 chain */
482                                        uint16_t  bfwNumPerRb,  /* number of bf weights per RB (i.e. antenna elements) */
483                                        uint8_t   bfwiqWidth,   /* bit size of IQs */
484                                        uint8_t   bfwCompMeth)  /* compression method */
485 {
486     struct xran_cp_radioapp_section_ext1 *p_ext1;
487
488     uint8_t *p_bfw_content = NULL;
489     int32_t parm_size   = 0;
490     int32_t bfw_iq_bits = 0;
491     int32_t total_len   = 0;
492     int32_t comp_len    = 0;
493     uint8_t ext_flag    = XRAN_EF_F_ANOTHER_ONE;
494     int16_t idxRb       = 0;
495     int16_t cur_ext_len = 0;
496     int8_t  *p_ext1_dst_cur = NULL;
497
498     struct xranlib_compress_request  bfp_com_req;
499     struct xranlib_compress_response bfp_com_rsp;
500
501     memset(&bfp_com_req, 0, sizeof(struct xranlib_compress_request));
502     memset(&bfp_com_rsp, 0, sizeof(struct xranlib_compress_response));
503
504     print_dbg("%s comp %d\n", __FUNCTION__, bfwCompMeth);
505     print_dbg("bfwNumPerRb %d bfwiqWidth %d\n", bfwNumPerRb, bfwiqWidth);
506
507     if(p_ext1_dst)
508         p_ext1_dst_cur = p_ext1_dst;
509     else
510         return (XRAN_STATUS_INVALID_PARAM);
511
512     /* create extType=1 section for each RB */
513     for (idxRb = 0; idxRb < rbNum; idxRb++) {
514         print_dbg("%s RB %d\n", __FUNCTION__, idxRb);
515
516         if(total_len >= ext1_dst_len){
517             print_err("p_ext1_dst overflow\n");
518             return -1;
519         }
520
521         cur_ext_len = 0; /** populate one extType=1 section with BFW for 1 RB */
522         parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
523         p_ext1 = (struct xran_cp_radioapp_section_ext1 *)p_ext1_dst_cur;
524         if(p_ext1 == NULL) {
525             print_err("p_ext1 is null!\n");
526             return (XRAN_STATUS_INVALID_PARAM);
527         }
528
529         cur_ext_len += parm_size;
530
531         if(idxRb+1 == rbNum)
532             ext_flag = XRAN_EF_F_LAST;
533
534         p_ext1->extType       = XRAN_CP_SECTIONEXTCMD_1;
535         p_ext1->ef            = ext_flag;
536         p_ext1->bfwCompMeth   = bfwCompMeth;
537         p_ext1->bfwIqWidth    = XRAN_CONVERT_BFWIQWIDTH(bfwiqWidth);
538
539         switch(bfwCompMeth) {
540             case XRAN_BFWCOMPMETHOD_BLKFLOAT:
541                 p_bfw_content = (uint8_t *)(p_ext1+1);
542                 if(p_bfw_content == NULL) {
543                     print_err("Fail to allocate the space for section extension 1");
544                     return (XRAN_STATUS_RESOURCE);
545                 }
546                 bfp_com_req.data_in         = (int16_t*)p_bfw_iq_src;
547                 bfp_com_req.numRBs          = 1;
548                 bfp_com_req.numDataElements = bfwNumPerRb*2;
549                 bfp_com_req.len             = bfwNumPerRb*4;
550                 bfp_com_req.compMethod      = p_ext1->bfwCompMeth;
551                 bfp_com_req.iqWidth         = p_ext1->bfwIqWidth;
552
553                 print_dbg("req 0x%08p iqWidth %d\n",bfp_com_req.data_in, bfp_com_req.iqWidth);
554
555                 parm_size = 1; /* exponent as part of bfwCompParam 1 octet */
556                 break;
557             case XRAN_BFWCOMPMETHOD_BLKSCALE:
558                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
559                 break;
560
561             case XRAN_BFWCOMPMETHOD_ULAW:
562                 rte_panic("XRAN_BFWCOMPMETHOD_ULAW");
563                 break;
564
565             case XRAN_BFWCOMPMETHOD_BEAMSPACE:
566                 rte_panic("XRAN_BFWCOMPMETHOD_BEAMSPACE");
567                 break;
568
569             case XRAN_BFWCOMPMETHOD_NONE:
570             default:
571                 p_bfw_content = (uint8_t *)(p_ext1+1);
572                 /* bfwCompParam is absent for no compression case */
573                 parm_size = 0;
574         }
575
576         if(p_bfw_content == NULL) {
577             print_err("Fail to allocate the space for section extension 1");
578             return (XRAN_STATUS_RESOURCE);
579             }
580
581         bfw_iq_bits = bfwNumPerRb* bfwiqWidth * 2;
582
583         parm_size += bfw_iq_bits>>3;
584         if(bfw_iq_bits%8)
585             parm_size++;
586
587         print_dbg("copy BF W %p -> %p size %d \n", p_bfw_iq_src, p_bfw_content, parm_size);
588         if (p_ext1->bfwIqWidth == 0 || p_ext1->bfwIqWidth == 16){
589             memcpy(p_bfw_content, p_bfw_iq_src, parm_size);
590         } else {
591             bfp_com_rsp.data_out = (int8_t*)p_bfw_content;
592             if(xranlib_compress_bfw(&bfp_com_req, &bfp_com_rsp) == 0){
593                 comp_len = bfp_com_rsp.len;
594                 print_dbg("comp_len %d parm_size %d\n", comp_len, parm_size);
595             } else {
596                 print_err("compression failed\n");
597                 return (XRAN_STATUS_FAIL);
598             }
599         }
600
601         p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
602
603         cur_ext_len += parm_size;
604         parm_size = cur_ext_len % XRAN_SECTIONEXT_ALIGN;
605         if(parm_size) {
606             parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
607             p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
608             memcpy(p_bfw_content, zeropad, RTE_MIN(parm_size, sizeof(zeropad)));
609             cur_ext_len += parm_size;
610             print_dbg("zeropad %d cur_ext_len %d\n", parm_size, cur_ext_len);
611         }
612
613         if(cur_ext_len % XRAN_SECTIONEXT_ALIGN)
614             rte_panic("ext1 should be aligned on 4-bytes boundary");
615
616         p_ext1->extLen = cur_ext_len / XRAN_SECTIONEXT_ALIGN;
617         print_dbg("[%d] %p iq %p p_ext1->extLen %d\n",idxRb, p_ext1, p_ext1+1,  p_ext1->extLen);
618
619         /* update for next RB */
620         p_ext1_dst_cur += cur_ext_len;
621         p_bfw_iq_src   = p_bfw_iq_src + bfwNumPerRb*2;
622
623         total_len += cur_ext_len;
624     }
625
626     print_dbg("total_len %d\n", total_len);
627     return (total_len);
628 }
629
630 // TODO: Need to decide to add calculation or not
631 // Frequency offset 5.4.5.11
632 //   frequency_offset = freqOffset * SCS * 0.5
633 //    i.e freqOffset = (frequency_offset *2 )/ SCS ?
634 inline int32_t
635 xran_get_freqoffset(int32_t freqOffset, int32_t scs)
636 {
637     return (freqOffset);
638 }
639
640 static int32_t
641 xran_append_sectionext_1(struct rte_mbuf *mbuf, struct xran_sectionext1_info *params, int32_t last_flag)
642 {
643     int32_t total_len = 0;
644
645     if(params->bfwIQ_sz) {
646         int8_t *p_dst = (int8_t *)rte_pktmbuf_append(mbuf, params->bfwIQ_sz);
647
648         if(p_dst == NULL) {
649             print_err("Fail to allocate the space for section extension 1 [%d]", params->bfwIQ_sz);
650             return (XRAN_STATUS_RESOURCE);
651         }
652
653         /* extType1 with all the headers created by xran_cp_populate_section_ext_1() earlier */
654         total_len = params->bfwIQ_sz;
655     }
656
657     return (total_len);
658 }
659
660 static int32_t
661 xran_prepare_sectionext_2(struct rte_mbuf *mbuf, struct xran_sectionext2_info *params, int32_t last_flag)
662 {
663   struct xran_cp_radioapp_section_ext2 *ext2;
664   uint8_t *data;
665     int32_t total_len;
666     int32_t parm_size;
667   uint32_t val, shift_val;
668     int32_t val_size, pad_size;
669
670     total_len = 0;
671
672     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
673     ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
674     if(ext2 == NULL) {
675         print_err("Fail to allocate the space for section extension 2");
676         return (XRAN_STATUS_RESOURCE);
677         }
678     total_len += parm_size;
679
680     ext2->extType           = XRAN_CP_SECTIONEXTCMD_2;
681     ext2->ef                = last_flag;
682     ext2->bfZe3ddWidth      = params->bfZe3ddWidth;
683     ext2->bfAz3ddWidth      = params->bfAz3ddWidth;
684     ext2->bfZePtWidth       = params->bfZePtWidth;
685     ext2->bfAzPtWidth       = params->bfAzPtWidth;
686     ext2->bfaCompResv0      = 0;
687     ext2->bfaCompResv1      = 0;
688
689     val = 0;
690     shift_val = 0;
691     if(params->bfAzPtWidth) {
692         val += params->bfAzPt & bitmask[params->bfAzPtWidth];
693         shift_val += 8 - (params->bfAzPtWidth+1);
694     } else
695         shift_val += 8;
696
697     if(params->bfZePtWidth) {
698         val = val << (params->bfZePtWidth+1);
699         val += params->bfZePt & bitmask[params->bfZePtWidth];
700         shift_val += 8 - (params->bfZePtWidth+1);
701     } else
702         shift_val += 8;
703
704     if(params->bfAz3ddWidth) {
705         val = val << (params->bfAz3ddWidth+1);
706         val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];
707         shift_val += 8 - (params->bfAz3ddWidth+1);
708     } else
709         shift_val += 8;
710
711     if(params->bfZe3ddWidth) {
712         val = val << (params->bfZe3ddWidth+1);
713         val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];
714         shift_val += 8 - (params->bfZe3ddWidth+1);
715     } else
716         shift_val += 8;
717
718     if(val) {
719         val = val << shift_val;
720         val = rte_cpu_to_be_32(val);
721         }
722
723     val_size = 4 - (shift_val/8);   /* ceil(total bit/8) */
724     parm_size = val_size + 1;       /* additional 1 byte for bfxxSI */
725
726     // alignment
727     total_len += parm_size;
728     pad_size = total_len % XRAN_SECTIONEXT_ALIGN;
729     if(pad_size) {
730         pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;
731         parm_size += pad_size;
732         total_len += pad_size;
733         }
734
735     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
736     if(data == NULL) {
737         print_err("Fail to allocate the space for section extension 2");
738         return (XRAN_STATUS_RESOURCE);
739         }
740
741     memcpy(data, &val, val_size);
742     data += val_size;
743     *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
744     data++;
745     memcpy(data, zeropad, pad_size);
746
747     ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
748     *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
749
750     return (total_len);
751 }
752
753 static int32_t
754 xran_prepare_sectionext_3(struct rte_mbuf *mbuf, struct xran_sectionext3_info *params, int32_t last_flag)
755 {
756     int32_t total_len;
757     int32_t adj;
758     int32_t data_first_byte, data_second_byte;
759     int32_t data_third_byte, data_fourth_byte;
760     int32_t extLen;
761
762     if(params->layerId == XRAN_LAYERID_0
763         || params->layerId == XRAN_LAYERID_TXD) {   /* first data layer */
764
765         union xran_cp_radioapp_section_ext3_first *ext3_f;
766         uint64_t *tmp;
767
768         total_len = sizeof(union xran_cp_radioapp_section_ext3_first);
769         ext3_f = (union xran_cp_radioapp_section_ext3_first *)rte_pktmbuf_append(mbuf, total_len);
770         if(ext3_f == NULL) {
771             print_err("Fail to allocate the space for section extension 3");
772             return (XRAN_STATUS_RESOURCE);
773             }
774
775         /*ext3_f->data_field.data_field1 = _mm_setzero_si128();
776
777         ext3_f->all_bits.layerId         = params->layerId;
778         ext3_f->all_bits.ef              = last_flag;
779         ext3_f->all_bits.extType         = XRAN_CP_SECTIONEXTCMD_3;
780         ext3_f->all_bits.crsSymNum       = params->crsSymNum;
781         ext3_f->all_bits.crsShift        = params->crsShift;
782         ext3_f->all_bits.crsReMask       = params->crsReMask;
783         ext3_f->all_bits.txScheme        = params->txScheme;
784         ext3_f->all_bits.numLayers       = params->numLayers;
785         ext3_f->all_bits.codebookIndex   = params->codebookIdx;
786
787         if(params->numAntPort == 2) {
788             ext3_f->all_bits.beamIdAP3   = params->beamIdAP1;
789             ext3_f->all_bits.extLen      = 3;
790             adj = 4;
791             total_len -= adj;
792             }
793         else {
794             ext3_f->all_bits.beamIdAP3   = params->beamIdAP1;
795             ext3_f->all_bits.beamIdAP2   = params->beamIdAP2;
796             ext3_f->all_bits.beamIdAP1   = params->beamIdAP3;
797             ext3_f->all_bits.extLen      = 4;
798             adj = 0;
799             }*/
800
801         if(params->numAntPort == 2) {
802             data_third_byte = 0;
803             extLen = 3;
804             adj = 4;
805             total_len -= adj;
806         }else
807         {
808             data_third_byte = (params->beamIdAP2 << 16) | params->beamIdAP3;
809             extLen = 4;
810             adj = 0;
811             }
812
813         data_first_byte  = (params->txScheme << xran_cp_radioapp_sec_ext3_TxScheme)
814                          | (params->crsReMask << xran_cp_radioapp_sec_ext3_CrcReMask)
815                          | (params->crsShift << xran_cp_radioapp_sec_ext3_CrcShift)
816                          | (params->crsSymNum << xran_cp_radioapp_sec_ext3_CrcSymNum);
817         data_second_byte = (last_flag << xran_cp_radioapp_sec_ext3_EF)
818                          | (XRAN_CP_SECTIONEXTCMD_3 << xran_cp_radioapp_sec_ext3_ExtType)
819                          | (extLen << xran_cp_radioapp_sec_ext3_ExtLen)
820                          | (params->codebookIdx << xran_cp_radioapp_sec_ext3_CodebookIdx)
821                          | (params->layerId << xran_cp_radioapp_sec_ext3_LayerId)
822                          | (params->numLayers << xran_cp_radioapp_sec_ext3_NumLayers);
823         data_fourth_byte  = params->beamIdAP1;
824         ext3_f->data_field.data_field1 = _mm_set_epi32(data_fourth_byte, data_third_byte, data_second_byte, data_first_byte);
825
826         /* convert byte order */
827         tmp = (uint64_t *)ext3_f;
828         *tmp = rte_cpu_to_be_64(*tmp); tmp++;
829         *tmp = rte_cpu_to_be_64(*tmp);
830
831         if(adj)
832             rte_pktmbuf_trim(mbuf, adj);
833         }
834     else {  /* non-first data layer */
835         union xran_cp_radioapp_section_ext3_non_first *ext3_nf;
836
837         total_len = sizeof(union xran_cp_radioapp_section_ext3_non_first);
838         ext3_nf = (union xran_cp_radioapp_section_ext3_non_first *)rte_pktmbuf_append(mbuf, total_len);
839         if(ext3_nf == NULL) {
840             print_err("Fail to allocate the space for section extension 3");
841             return (XRAN_STATUS_RESOURCE);
842             }
843
844         /*ext3_nf->all_bits.layerId        = params->layerId;
845         ext3_nf->all_bits.ef             = last_flag;
846         ext3_nf->all_bits.extType        = XRAN_CP_SECTIONEXTCMD_3;
847         ext3_nf->all_bits.numLayers      = params->numLayers;
848         ext3_nf->all_bits.codebookIndex  = params->codebookIdx;
849
850         ext3_nf->all_bits.extLen         = sizeof(union xran_cp_radioapp_section_ext3_non_first)/XRAN_SECTIONEXT_ALIGN;*/
851
852         ext3_nf->data_field = (last_flag << xran_cp_radioapp_sec_ext3_EF)
853                             | (XRAN_CP_SECTIONEXTCMD_3 << xran_cp_radioapp_sec_ext3_ExtType)
854                             | ((sizeof(union xran_cp_radioapp_section_ext3_non_first)/XRAN_SECTIONEXT_ALIGN) << xran_cp_radioapp_sec_ext3_ExtLen)
855                             | (params->codebookIdx << xran_cp_radioapp_sec_ext3_CodebookIdx)
856                             | (params->layerId << xran_cp_radioapp_sec_ext3_LayerId)
857                             | (params->numLayers << xran_cp_radioapp_sec_ext3_NumLayers);
858
859         *(uint32_t *)ext3_nf = rte_cpu_to_be_32(*(uint32_t *)ext3_nf);
860         }
861
862     return (total_len);
863 }
864
865 static int32_t
866 xran_prepare_sectionext_4(struct rte_mbuf *mbuf, struct xran_sectionext4_info *params, int32_t last_flag)
867 {
868   struct xran_cp_radioapp_section_ext4 *ext4;
869     int32_t parm_size;
870
871     parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
872     ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
873     if(ext4 == NULL) {
874         print_err("Fail to allocate the space for section extension 4");
875         return(XRAN_STATUS_RESOURCE);
876         }
877
878         ext4->extType       = XRAN_CP_SECTIONEXTCMD_4;
879         ext4->ef            = last_flag;
880         ext4->modCompScaler = params->modCompScaler;
881         ext4->csf           = params->csf?1:0;
882     ext4->extLen        = parm_size / XRAN_SECTIONEXT_ALIGN;
883
884         *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
885
886     return (parm_size);
887 }
888
889 static int32_t
890 xran_prepare_sectionext_5(struct rte_mbuf *mbuf, struct xran_sectionext5_info *params, int32_t last_flag)
891 {
892   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
893   struct xran_cp_radioapp_section_ext5 ext5;
894     int32_t padding;
895     int32_t total_len;
896   uint8_t *data;
897     int32_t i;
898
899     if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {
900         print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);
901         return (0);
902         }
903
904     total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)
905                 + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2
906                 - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust
907
908     /* for alignment */
909     padding = total_len % XRAN_SECTIONEXT_ALIGN;
910     if(padding) {
911         padding = XRAN_SECTIONEXT_ALIGN - padding;
912         total_len += padding;
913         }
914
915     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);
916     if(ext_hdr == NULL) {
917         print_err("Fail to allocate the space for section extension 5");
918         return (XRAN_STATUS_RESOURCE);
919         }
920
921     ext_hdr->extType    = XRAN_CP_SECTIONEXTCMD_5;
922     ext_hdr->ef         = last_flag;
923     ext_hdr->extLen     = total_len / XRAN_SECTIONEXT_ALIGN;
924
925     *(uint16_t *)ext_hdr    = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));
926
927     data = (uint8_t *)(ext_hdr + 1);
928     i = 0;
929     while(i < params->num_sets) {
930         if(i%2) { // odd index
931             ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;
932             ext5.csf2           = params->mc[i].csf;
933             ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;
934             ext5.reserved0      = 0;
935             i++;
936
937             // adding two sets at once (due to the definition of structure)
938             *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
939             memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));
940             data += sizeof(struct xran_cp_radioapp_section_ext5);
941             }
942         else { // even index
943             ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;
944             ext5.csf1           = params->mc[i].csf;
945             ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;
946             ext5.mcScaleReMask2 = 0;
947             i++;
948
949             if(i == params->num_sets) { // adding last even index
950                 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
951                 memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);
952                 data += sizeof(struct xran_cp_radioapp_section_ext5)/2;
953                 break;
954                 }
955             }
956         }
957
958     /* zero padding */
959     if(padding)
960         memcpy(data, zeropad, padding);
961
962     return (total_len);
963 }
964
965 static int32_t
966 xran_prepare_sectionext_6(struct rte_mbuf *mbuf,
967                 struct xran_sectionext6_info *params, int32_t last_flag)
968 {
969     union xran_cp_radioapp_section_ext6 *ext6;
970     int32_t parm_size;
971
972     parm_size = sizeof(union xran_cp_radioapp_section_ext6);
973     ext6 = (union xran_cp_radioapp_section_ext6 *)rte_pktmbuf_append(mbuf, parm_size);
974     if(ext6 == NULL) {
975         print_err("Fail to allocate the space for section extension 6");
976         return(XRAN_STATUS_RESOURCE);
977         }
978
979     ext6->data_field.data_field1 = 0x0LL;
980     ext6->all_bits.extType       = XRAN_CP_SECTIONEXTCMD_6;
981     ext6->all_bits.ef            = last_flag;
982     ext6->all_bits.rbgSize       = params->rbgSize;
983     ext6->all_bits.rbgMask       = params->rbgMask;
984     ext6->all_bits.symbolMask    = params->symbolMask;
985     ext6->all_bits.extLen        = parm_size / XRAN_SECTIONEXT_ALIGN;
986     //ext6->reserved0     = 0;
987     //ext6->reserved1     = 0;
988
989     *(uint64_t *)ext6 = rte_cpu_to_be_64(*(uint64_t*)ext6);
990
991     return (parm_size);
992 }
993
994 static int32_t
995 xran_prepare_sectionext_10(struct rte_mbuf *mbuf,
996                 struct xran_sectionext10_info *params, int32_t last_flag)
997 {
998   union xran_cp_radioapp_section_ext10 *ext10;
999   int32_t parm_size;
1000   int32_t total_len;
1001   int32_t padding;
1002   int32_t i;
1003   uint16_t *id_ptr;
1004
1005
1006 #if (XRAN_STRICT_PARM_CHECK)
1007     if(params->beamGrpType != XRAN_BEAMGT_COMMON
1008         && params->beamGrpType != XRAN_BEAMGT_MATRIXIND
1009         && params->beamGrpType != XRAN_BEAMGT_VECTORLIST) {
1010         print_err("Invalid beam group Type - %d\n", params->beamGrpType);
1011         return (XRAN_STATUS_INVALID_PARAM);
1012         }
1013 #endif
1014     /* should be checked since it will be used for the index of array */
1015     if(params->numPortc > XRAN_MAX_NUMPORTC_EXT10) {
1016         print_err("Invalid Number of eAxC in extension 10 - %d\n", params->numPortc);
1017         return (XRAN_STATUS_INVALID_PARAM);
1018         }
1019
1020     parm_size = sizeof(union xran_cp_radioapp_section_ext10);
1021     ext10 = (union xran_cp_radioapp_section_ext10 *)rte_pktmbuf_append(mbuf, parm_size);
1022     if(ext10 == NULL) {
1023         print_err("Fail to allocate the space for section extension 10");
1024         return(XRAN_STATUS_RESOURCE);
1025         }
1026
1027     ext10->all_bits.extType          = XRAN_CP_SECTIONEXTCMD_10;
1028     ext10->all_bits.ef               = last_flag;
1029     ext10->all_bits.numPortc         = params->numPortc;
1030     ext10->all_bits.beamGroupType    = params->beamGrpType;
1031     ext10->all_bits.reserved         = 0;
1032
1033     total_len = parm_size;
1034
1035     if(params->beamGrpType == XRAN_BEAMGT_VECTORLIST) {
1036         /* Calculate required size, it needs to be reduced by one byte
1037          * since beam ID starts from reserved field(fourth octet). */
1038         parm_size = params->numPortc * 2 - 1;
1039
1040         /* for alignment */
1041         padding = (parm_size + total_len) % XRAN_SECTIONEXT_ALIGN;
1042         if(padding) {
1043             padding = XRAN_SECTIONEXT_ALIGN - padding;
1044             parm_size += padding;
1045             }
1046
1047         id_ptr = (uint16_t *)rte_pktmbuf_append(mbuf, parm_size);
1048         if(id_ptr == NULL) {
1049             print_err("Fail to allocate the space for beam IDs in section extension 10");
1050             return(XRAN_STATUS_RESOURCE);
1051             }
1052
1053         /* Need to advance pointer by one-byte since beam IDs start from fourth octet */
1054         id_ptr = (uint16_t *)(((uint8_t *)id_ptr) - 1);
1055
1056         /* this might not be optimal since the alignment is broken */
1057         for(i = 0; i < params->numPortc; i++)
1058             id_ptr[i] = rte_cpu_to_be_16(params->beamID[i]);
1059
1060         /* zero padding */
1061         if(padding)
1062             memcpy((uint8_t *)&id_ptr[params->numPortc], zeropad, padding);
1063         }
1064
1065     total_len += parm_size;
1066     ext10->all_bits.extLen = total_len / XRAN_SECTIONEXT_ALIGN;
1067
1068     ext10->data_field = 0;
1069     ext10->data_field = (XRAN_CP_SECTIONEXTCMD_10 << xran_cp_radioapp_sec_ext10_ExtType)
1070                       | (last_flag << xran_cp_radioapp_sec_ext10_EF)
1071                       | ((total_len / XRAN_SECTIONEXT_ALIGN) << xran_cp_radioapp_sec_ext10_ExtLen)
1072                       | (params->numPortc << xran_cp_radioapp_sec_ext10_NumPortc)
1073                       | (params->beamGrpType << xran_cp_radioapp_sec_ext10_BeamGroupType);
1074
1075
1076     return (total_len);
1077 }
1078
1079 /**
1080  * @brief Estimates how many BFW sets can be fit to given MTU size
1081  *
1082  * @ingroup xran_cp_pkt
1083  *
1084  * @param numBFW        the number of BFW I/Qs
1085  * @param iqWidth       the bitwidth of BFW
1086  * @param compMeth      Compression method for BFW
1087  * @param mtu           MTU size
1088  *
1089  * @return
1090  *  the number of maximum set of BFWs on success
1091  *  XRAN_STATUS_INVALID_PARAM, if compression method is not supported.
1092  */
1093 int32_t
1094 xran_cp_estimate_max_set_bfws(uint8_t numBFWs, uint8_t iqWidth, uint8_t compMeth, uint16_t mtu)
1095 {
1096     int32_t avail_len;
1097     int32_t bfw_bitsize;
1098     int32_t bundle_size;
1099
1100     /* Exclude headers can be present */
1101     avail_len = mtu - ( RTE_PKTMBUF_HEADROOM \
1102                         + sizeof(struct xran_ecpri_hdr)                    \
1103                         + sizeof(struct xran_cp_radioapp_common_header)    \
1104                         + sizeof(struct xran_cp_radioapp_section1)         \
1105                         + sizeof(union xran_cp_radioapp_section_ext6)     \
1106                         + sizeof(union xran_cp_radioapp_section_ext10) );
1107
1108     /* Calculate the size of BFWs I/Q in bytes */
1109     bfw_bitsize = numBFWs * iqWidth * 2;
1110     bundle_size = bfw_bitsize>>3;
1111     if(bfw_bitsize%8) bundle_size++;
1112
1113     bundle_size += 2;           /* two bytes for Beam ID */
1114     switch(compMeth) {
1115         case XRAN_BFWCOMPMETHOD_NONE:
1116             break;
1117
1118         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1119             bundle_size += 1;   /* for bfwCompParam */
1120             break;
1121
1122         default:
1123             print_err("Compression method %d is not supported!", compMeth);
1124             return (XRAN_STATUS_INVALID_PARAM);
1125         }
1126
1127     return (avail_len / bundle_size);
1128 }
1129
1130 inline static uint32_t
1131 xran_cp_get_hdroffset_section1(uint32_t exthdr_size)
1132 {
1133   uint32_t hdr_len;
1134
1135     hdr_len = ( RTE_PKTMBUF_HEADROOM                                \
1136                 + sizeof(struct xran_ecpri_hdr)                     \
1137                 + sizeof(struct xran_cp_radioapp_common_header)     \
1138                 + sizeof(struct xran_cp_radioapp_section1)          \
1139                 + exthdr_size );
1140     return (hdr_len);
1141 }
1142
1143 /**
1144  * @brief Prepare Beam Forming Weights(BFWs) for Section Extension 11
1145  *   Copy sets of BFWs to buffer after compression if required.
1146  *
1147  * @ingroup xran_cp_pkt
1148  *
1149  * @param numSetBFW     the number of set of BFWs
1150  * @param numBFW        the number of BFWs in a set
1151  * @param iqWidth       the bitwidth of BFW
1152  * @param compMeth      Compression method for BFW
1153  * @param bfwIQ         the array of BFW I/Q source
1154  * @param dst           the pointer of destination buffer (external buffer)
1155  * @param dst_maxlen    the maximum length of destination buffer
1156  *                      need to exclude headroom from MTU
1157  * @param bfwInfo       Extension 11 PRB bundle information array.
1158  *                      BFW size, offset and pointer will be set.
1159  *
1160  * @return
1161  *  XRAN_STATUS_SUCCESS on success
1162  *  XRAN_STATUS_RESOURCE, if destination memory is not enough to store all BFWs
1163  */
1164 int32_t xran_cp_prepare_ext11_bfws(uint8_t numSetBFW, uint8_t numBFW,
1165                         uint8_t iqWidth, uint8_t compMeth,
1166                         uint8_t *dst, int16_t dst_maxlen,
1167                         struct xran_ext11_bfw_info bfwInfo[])
1168 {
1169     int32_t   i;
1170     int32_t   iq_bitsize, iq_size;
1171     int32_t   parm_size;
1172     int32_t   total_len;
1173     uint32_t  hdr_offset;
1174     uint8_t   *ptr;
1175
1176     struct xranlib_compress_request  bfpComp_req;
1177     struct xranlib_compress_response bfpComp_rsp;
1178
1179     if(dst == NULL) {
1180         print_err("Invalid destination pointer!");
1181         return (XRAN_STATUS_INVALID_PARAM);
1182     }
1183
1184     /* Calculate the size of BFWs I/Q in bytes */
1185     iq_bitsize = numBFW * iqWidth * 2;
1186     iq_size = iq_bitsize>>3;
1187     if(iq_bitsize%8)
1188         iq_size++;
1189
1190     /* Check maximum size */
1191     parm_size = ((compMeth == XRAN_BFWCOMPMETHOD_NONE)?0:1) + 2; /* bfwCompParam + beamID(2) */
1192     total_len = numSetBFW * (parm_size + iq_size);
1193
1194     if(total_len >= dst_maxlen) {
1195         print_err("Exceed maximum length to fit the set of BFWs - (%d/%d)",
1196                     total_len, dst_maxlen);
1197         return (XRAN_STATUS_RESOURCE);
1198     }
1199
1200     hdr_offset = xran_cp_get_hdroffset_section1(sizeof(union xran_cp_radioapp_section_ext11));
1201
1202     /* Copy BFWs to destination buffer */
1203     ptr = dst + hdr_offset + 2;
1204     switch(compMeth) {
1205         /* No compression */
1206         case XRAN_BFWCOMPMETHOD_NONE:
1207             for(i = 0; i < numSetBFW; i++) {
1208                 *((uint16_t *)ptr) = rte_cpu_to_be_16((bfwInfo[i].beamId & 0x7fff));
1209                 memcpy((ptr + 2), bfwInfo[i].pBFWs, iq_size);
1210                 ptr += iq_size + 2; /* beam ID + IQ size */
1211             }
1212             break;
1213
1214         /* currently only supports BFP compression */
1215         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1216             memset(&bfpComp_req, 0, sizeof(struct xranlib_compress_request));
1217             memset(&bfpComp_rsp, 0, sizeof(struct xranlib_compress_response));
1218
1219             for(i = 0; i < numSetBFW; i++) {
1220                 bfpComp_req.numRBs          = 1;
1221                 bfpComp_req.numDataElements = numBFW*2;
1222                 bfpComp_req.len             = numBFW*2*2;
1223                 bfpComp_req.compMethod      = compMeth;
1224                 bfpComp_req.iqWidth         = iqWidth;
1225                 bfpComp_req.data_in         = (int16_t *)bfwInfo[i].pBFWs;
1226                 bfpComp_rsp.data_out        = (int8_t*)(ptr + 2);   /* exponent will be stored at first byte */
1227
1228                 if(xranlib_compress_bfw(&bfpComp_req, &bfpComp_rsp) == 0) {
1229                     print_dbg("comp_len %d iq_size %d\n", bfpComp_rsp.len, iq_size);
1230                 } else {
1231                     print_err("compression failed\n");
1232                     return (XRAN_STATUS_FAIL);
1233                     }
1234                 /* move exponent, it is stored at first byte of output */
1235                 *ptr = *(ptr + 2);
1236
1237                 /* beamId */
1238                 *((uint16_t *)(ptr+1)) = rte_cpu_to_be_16((bfwInfo[i].beamId & 0x7fff));
1239                 ptr += iq_size + 3;
1240             }
1241             break;
1242
1243         default:
1244             print_err("Compression method %d is not supported!", compMeth);
1245             return (XRAN_STATUS_INVALID_PARAM);
1246     }
1247
1248     /* Update the length of extension with padding */
1249     parm_size = (total_len + sizeof(union xran_cp_radioapp_section_ext11))
1250                     % XRAN_SECTIONEXT_ALIGN;
1251     if(parm_size) {
1252         /* Add padding */
1253         parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
1254         memcpy(ptr, zeropad, parm_size);
1255         total_len += parm_size;
1256         }
1257
1258     return (total_len);
1259 }
1260
1261
1262 static void free_ext_buf(void *addr, void *opaque)
1263 {
1264     /* free is not required for external buffers */
1265 }
1266
1267 /*
1268  * extbuf_start : the pointer of the external buffer,
1269  *          It can be the start address of whole external buffer.
1270  * extbuf_len : total length of the external buffer (available space to access)
1271  *          To use the length of the data, offset2data should be zero.
1272  * */
1273 int32_t xran_cp_attach_ext_buf(struct rte_mbuf *mbuf,
1274                 uint8_t *extbuf_start, uint16_t extbuf_len,
1275                 struct rte_mbuf_ext_shared_info *shinfo)
1276 {
1277     rte_iova_t extbuf_iova;
1278
1279
1280     if(unlikely(mbuf == NULL)) {
1281         print_err("Invalid mbuf to attach!\n");
1282         return (XRAN_STATUS_INVALID_PARAM);
1283         }
1284
1285     /* Update shared information */
1286     shinfo->free_cb = free_ext_buf;
1287     rte_mbuf_ext_refcnt_update(shinfo, 1);
1288
1289     extbuf_iova = rte_malloc_virt2iova(extbuf_start);
1290     if(unlikely(extbuf_iova == RTE_BAD_IOVA)) {
1291         print_err("Failed rte_mem_virt2iova RTE_BAD_IOVA \n");
1292         return (XRAN_STATUS_INVALID_PARAM);
1293         }
1294
1295     rte_pktmbuf_attach_extbuf(mbuf, extbuf_start, extbuf_iova, extbuf_len, shinfo);
1296
1297     rte_pktmbuf_reset_headroom(mbuf);
1298
1299     return (XRAN_STATUS_SUCCESS);
1300 }
1301
1302
1303 static int32_t
1304 xran_prepare_sectionext_11(struct rte_mbuf *mbuf,
1305                 struct xran_sectionext11_info *params, int32_t last_flag)
1306 {
1307     union xran_cp_radioapp_section_ext11 *ext11;
1308     int32_t total_len;
1309
1310
1311 #if (XRAN_STRICT_PARM_CHECK)
1312     if(unlikely((params->numSetBFWs == 0)
1313             || (params->numSetBFWs > XRAN_MAX_SET_BFWS))) {
1314         print_err("Invalid number of the set of PRB bundle [%d]", params->numSetBFWs);
1315         return (XRAN_STATUS_INVALID_PARAM);
1316         }
1317 #endif
1318
1319     /* BFWs are already present in the external buffer, just update the length */
1320     total_len = sizeof(union xran_cp_radioapp_section_ext11) + params->totalBfwIQLen;
1321
1322     ext11 = (union xran_cp_radioapp_section_ext11 *)rte_pktmbuf_append(mbuf, total_len);
1323     if(ext11 == NULL) {
1324         print_err("Fail to allocate the space for section extension 11 [%d]", total_len);
1325         return (XRAN_STATUS_RESOURCE);
1326         }
1327
1328     /*ext11->all_bits.extType      = XRAN_CP_SECTIONEXTCMD_11;
1329     ext11->all_bits.ef           = last_flag;
1330     ext11->all_bits.reserved     = 0;
1331     ext11->all_bits.RAD          = params->RAD;
1332     ext11->all_bits.disableBFWs  = params->disableBFWs;
1333     ext11->all_bits.numBundPrb   = params->numBundPrb;
1334     ext11->all_bits.bfwCompMeth  = params->bfwCompMeth;
1335     ext11->all_bits.bfwIqWidth   = XRAN_CONVERT_BFWIQWIDTH(params->bfwIqWidth);
1336
1337     ext11->all_bits.extLen        = total_len / XRAN_SECTIONEXT_ALIGN;*/
1338
1339     ext11->data_field.data_field1 = (last_flag << xran_cp_radioapp_sec_ext11_bitfield_Ef)
1340                                   | (XRAN_CP_SECTIONEXTCMD_11 << xran_cp_radioapp_sec_ext11_bitfield_ExtType)
1341                                   | ((total_len / XRAN_SECTIONEXT_ALIGN) << xran_cp_radioapp_sec_ext11_bitfield_ExtLen)
1342                                   | (params->disableBFWs << xran_cp_radioapp_sec_ext11_bitfield_DisBFWs)
1343                                   | (params->RAD << xran_cp_radioapp_sec_ext11_bitfield_RAD);
1344     ext11->data_field.data_field2 = ((XRAN_CONVERT_BFWIQWIDTH(params->bfwIqWidth)) << xran_cp_radioapp_sec_ext11_bitfield_BFWIQWidth)
1345                                   | (params->bfwCompMeth << xran_cp_radioapp_sec_ext11_bitfield_BFWCompMeth)
1346                                   | params->numBundPrb;
1347
1348     *(uint32_t *)ext11 = rte_cpu_to_be_32(*(uint32_t*)ext11);
1349
1350     return (total_len);
1351 }
1352
1353 /**
1354  * @brief add section extension to C-Plane packet
1355  *
1356  * @param mbuf
1357  *  A pointer to the packet buffer
1358  * @param params
1359  *  A porinter to the information to generate a C-Plane packet
1360  * @return
1361  *  XRAN_STATUS_SUCCESS on success
1362  *  XRAN_STATUS_INVALID_PARM
1363  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1364  */
1365 int32_t xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
1366 {
1367     int32_t i, ret;
1368     uint32_t totalen;
1369     int32_t last_flag;
1370     int32_t ext_size;
1371
1372     if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {
1373         print_err("Invalid total number of extensions - %d", params->exDataSize);
1374         return (XRAN_STATUS_INVALID_PARAM);
1375     }
1376
1377     totalen = 0;
1378
1379     ret = XRAN_STATUS_SUCCESS;
1380
1381     print_dbg("params->exDataSize %d\n", params->exDataSize);
1382     for(i=0; i < params->exDataSize; i++) {
1383         if(params->exData[i].data == NULL) {
1384             print_err("Invalid parameter - extension data %d is NULL", i);
1385             ret = XRAN_STATUS_INVALID_PARAM;
1386             continue;
1387         }
1388
1389         last_flag = (params->exDataSize == (i+1))?0:1;
1390
1391         switch(params->exData[i].type) {
1392             case XRAN_CP_SECTIONEXTCMD_1:
1393                 ext_size = xran_append_sectionext_1(mbuf, params->exData[i].data, last_flag);
1394                 break;
1395             case XRAN_CP_SECTIONEXTCMD_2:
1396                 ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
1397                 break;
1398             case XRAN_CP_SECTIONEXTCMD_3:
1399                 ext_size = xran_prepare_sectionext_3(mbuf, params->exData[i].data, last_flag);
1400                 break;
1401             case XRAN_CP_SECTIONEXTCMD_4:
1402                 ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
1403                 break;
1404             case XRAN_CP_SECTIONEXTCMD_5:
1405                 ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
1406                 break;
1407             case XRAN_CP_SECTIONEXTCMD_6:
1408                 ext_size = xran_prepare_sectionext_6(mbuf, params->exData[i].data, last_flag);
1409                 break;
1410             case XRAN_CP_SECTIONEXTCMD_10:
1411                 ext_size = xran_prepare_sectionext_10(mbuf, params->exData[i].data, last_flag);
1412                 break;
1413             case XRAN_CP_SECTIONEXTCMD_11:
1414                 ext_size = xran_prepare_sectionext_11(mbuf, params->exData[i].data, last_flag);
1415                 break;
1416             default:
1417                 print_err("Extension Type %d is not supported!", params->exData[i].type);
1418                 ret = XRAN_STATUS_INVALID_PARAM;
1419                 ext_size = 0;
1420             }
1421
1422         if(ext_size == XRAN_STATUS_RESOURCE) {
1423             break;
1424         }
1425
1426         totalen += ext_size;
1427     }
1428
1429     return (totalen);
1430 }
1431
1432
1433 /**
1434  * @brief Fill the section body of type 0 in C-Plane packet
1435  *
1436  * @param section
1437  *  A pointer to the section in the packet buffer
1438  * @param params
1439  *  A porinter to the information to generate a C-Plane packet
1440  * @return
1441  *  XRAN_STATUS_SUCCESS on success
1442  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1443  */
1444 static int32_t
1445 xran_prepare_section0(struct xran_cp_radioapp_section0 *section, struct xran_section_gen_info *params)
1446 {
1447 #if (XRAN_STRICT_PARM_CHECK)
1448     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1449         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1450         return (XRAN_STATUS_INVALID_PARAM);
1451         }
1452 #endif
1453
1454     section->hdr.u1.common.sectionId      = params->info.id;
1455     section->hdr.u1.common.rb             = params->info.rb;
1456     section->hdr.u1.common.symInc         = params->info.symInc;
1457     section->hdr.u1.common.startPrbc      = params->info.startPrbc;
1458     section->hdr.u1.common.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1459
1460     section->hdr.u.s0.reMask    = params->info.reMask;
1461     section->hdr.u.s0.numSymbol = params->info.numSymbol;
1462     section->hdr.u.s0.reserved  = 0;
1463
1464     // for network byte order
1465     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1466
1467     return (XRAN_STATUS_SUCCESS);
1468 }
1469
1470 /**
1471  * @brief Fill the section header of type 0 in C-Plane packet
1472  *
1473  * @param s0hdr
1474  *  A pointer to the section header in the packet buffer
1475  * @param params
1476  *  A porinter to the information to generate a C-Plane packet
1477  * @return
1478  *  XRAN_STATUS_SUCCESS always
1479  */
1480 static int32_t
1481 xran_prepare_section0_hdr( struct xran_cp_radioapp_section0_header *s0hdr,
1482                 struct xran_cp_gen_params *params)
1483 {
1484     s0hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1485     s0hdr->frameStructure.fftSize   = params->hdr.fftSize;
1486     s0hdr->frameStructure.uScs      = params->hdr.scs;
1487     s0hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1488     s0hdr->reserved                 = 0;
1489
1490     return (XRAN_STATUS_SUCCESS);
1491 }
1492
1493 /**
1494  * @brief Fill the section body of type 1 in C-Plane packet
1495  *  Extension is not supported.
1496  *
1497  * @param section
1498  *  A pointer to the section header in the packet buffer
1499  * @param params
1500  *  A porinter to the information to generate a C-Plane packet
1501  * @return
1502  *  XRAN_STATUS_SUCCESS on success
1503  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1504  */
1505 static int32_t
1506 xran_prepare_section1(struct xran_cp_radioapp_section1 *section,
1507                 struct xran_section_gen_info *params)
1508 {
1509 #if (XRAN_STRICT_PARM_CHECK)
1510     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1511         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1512         return (XRAN_STATUS_INVALID_PARAM);
1513         }
1514 #endif
1515
1516     /*section->hdr.u1.common.sectionId      = params->info.id;
1517     section->hdr.u1.common.rb             = params->info.rb;
1518     section->hdr.u1.common.symInc         = params->info.symInc;
1519     section->hdr.u1.common.startPrbc      = params->info.startPrbc;
1520     section->hdr.u1.common.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1521
1522     section->hdr.u.s1.reMask    = params->info.reMask;
1523     section->hdr.u.s1.numSymbol = params->info.numSymbol;
1524     section->hdr.u.s1.beamId    = params->info.beamId;
1525     section->hdr.u.s1.ef        = params->info.ef;*/
1526
1527     section->hdr.u.first_4byte   = (params->info.reMask << xran_cp_radioapp_sec_hdr_sc_ReMask)
1528                                  | (params->info.numSymbol << xran_cp_radioapp_sec_hdr_sc_NumSym)
1529                                  | (params->info.ef << xran_cp_radioapp_sec_hdr_sc_Ef)
1530                                  | (params->info.beamId << xran_cp_radioapp_sec_hdr_sc_BeamID);
1531     section->hdr.u1.second_4byte = (params->info.id << xran_cp_radioapp_sec_hdr_c_SecId)
1532                                  | (params->info.rb << xran_cp_radioapp_sec_hdr_c_RB)
1533                                  | (params->info.symInc << xran_cp_radioapp_sec_hdr_c_SymInc)
1534                                  | (params->info.startPrbc << xran_cp_radioapp_sec_hdr_c_StartPrbc)
1535                                  | ((XRAN_CONVERT_NUMPRBC(params->info.numPrbc)) << xran_cp_radioapp_sec_hdr_c_NumPrbc);
1536
1537     // for network byte order
1538     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1539
1540     return (XRAN_STATUS_SUCCESS);
1541 }
1542
1543 /**
1544  * @brief Fill the section header of type 1 in C-Plane packet
1545  *
1546  * @param s1hdr
1547  *  A pointer to the section header in the packet buffer
1548  * @param params
1549  *  A porinter to the information to generate a C-Plane packet
1550  * @return
1551  *  XRAN_STATUS_SUCCESS always
1552  */
1553 static int32_t
1554 xran_prepare_section1_hdr(struct xran_cp_radioapp_section1_header *s1hdr,
1555                 struct xran_cp_gen_params *params)
1556 {
1557     s1hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1558     s1hdr->udComp.udCompMeth        = params->hdr.compMeth;
1559     s1hdr->reserved                 = 0;
1560
1561     return (XRAN_STATUS_SUCCESS);
1562 }
1563
1564 /**
1565  * @brief Fill the section body of type 3 in C-Plane packet
1566  *  Extension is not supported.
1567  *
1568  * @param section
1569  *  A pointer to the section header in the packet buffer
1570  * @param params
1571  *  A porinter to the information to generate a C-Plane packet
1572  * @return
1573  *  XRAN_STATUS_SUCCESS on success
1574  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1575  */
1576 static int32_t
1577 xran_prepare_section3(struct xran_cp_radioapp_section3 *section,
1578                 struct xran_section_gen_info *params)
1579 {
1580 #if (XRAN_STRICT_PARM_CHECK)
1581     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1582         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1583         return (XRAN_STATUS_INVALID_PARAM);
1584         }
1585 #endif
1586
1587     /*section->hdr.u1.common.sectionId      = params->info.id;
1588     section->hdr.u1.common.rb             = params->info.rb;
1589     section->hdr.u1.common.symInc         = params->info.symInc;
1590     section->hdr.u1.common.startPrbc      = params->info.startPrbc;
1591     section->hdr.u1.common.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1592
1593     section->hdr.u.s3.reMask    = params->info.reMask;
1594     section->hdr.u.s3.numSymbol = params->info.numSymbol;
1595     section->hdr.u.s3.beamId    = params->info.beamId;
1596     section->hdr.u.s3.ef        = params->info.ef;*/
1597
1598     section->hdr.u.first_4byte   = (params->info.reMask << xran_cp_radioapp_sec_hdr_sc_ReMask)
1599                                  | (params->info.numSymbol << xran_cp_radioapp_sec_hdr_sc_NumSym)
1600                                  | (params->info.ef << xran_cp_radioapp_sec_hdr_sc_Ef)
1601                                  | (params->info.beamId << xran_cp_radioapp_sec_hdr_sc_BeamID);
1602     section->hdr.u1.second_4byte = (params->info.id << xran_cp_radioapp_sec_hdr_c_SecId)
1603                                  | (params->info.rb << xran_cp_radioapp_sec_hdr_c_RB)
1604                                  | (params->info.symInc << xran_cp_radioapp_sec_hdr_c_SymInc)
1605                                  | (params->info.startPrbc << xran_cp_radioapp_sec_hdr_c_StartPrbc)
1606                                  | ((XRAN_CONVERT_NUMPRBC(params->info.numPrbc)) << xran_cp_radioapp_sec_hdr_c_NumPrbc);
1607
1608     section->freqOffset         = rte_cpu_to_be_32(params->info.freqOffset)>>8;
1609     section->reserved           = 0;
1610
1611     /* for network byte order (header, 8 bytes) */
1612     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1613
1614     return (XRAN_STATUS_SUCCESS);
1615 }
1616
1617 /**
1618  * @brief Fill the section header of type 3 in C-Plane packet
1619  *
1620  * @param s3hdr
1621  *  A pointer to the section header in the packet buffer
1622  * @param params
1623  *  A porinter to the information to generate a C-Plane packet
1624  * @return
1625  *  XRAN_STATUS_SUCCESS always
1626  */
1627 static int32_t
1628 xran_prepare_section3_hdr(struct xran_cp_radioapp_section3_header *s3hdr,
1629                 struct xran_cp_gen_params *params)
1630 {
1631     s3hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1632     s3hdr->frameStructure.fftSize   = params->hdr.fftSize;
1633     s3hdr->frameStructure.uScs      = params->hdr.scs;
1634     s3hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1635     s3hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1636     s3hdr->udComp.udCompMeth        = params->hdr.compMeth;
1637
1638     return (XRAN_STATUS_SUCCESS);
1639 }
1640
1641 /**
1642  * @brief add sections to C-Plane packet
1643  *  Section type 1 and 3 are supported.
1644  *
1645  * @param mbuf
1646  *  A pointer to the packet buffer
1647  * @param params
1648  *  A porinter to the information to generate a C-Plane packet
1649  * @return
1650  *  XRAN_STATUS_SUCCESS on success
1651  *  XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
1652  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1653  */
1654 int32_t
1655 xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1656 {
1657     int32_t i, ret, ext_flag;
1658   uint32_t totalen;
1659   void *section;
1660     int32_t section_size;
1661     int32_t (*xran_prepare_section_func)(void *section, void *params);
1662
1663     totalen = 0;
1664     switch(params->sectionType) {
1665         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1666             section_size                = sizeof(struct xran_cp_radioapp_section0);
1667             xran_prepare_section_func   = (int32_t (*)(void *, void *))xran_prepare_section0;
1668             break;
1669
1670         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1671             section_size                = sizeof(struct xran_cp_radioapp_section1);
1672             xran_prepare_section_func   = (int32_t (*)(void *, void *))xran_prepare_section1;
1673             break;
1674
1675         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1676             section_size                = sizeof(struct xran_cp_radioapp_section3);
1677             xran_prepare_section_func   = (int32_t (*)(void *, void *))xran_prepare_section3;
1678             break;
1679
1680         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1681         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1682         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1683         default:
1684             section_size                = 0;
1685             xran_prepare_section_func   = NULL;
1686             print_err("Section Type %d is not supported!", params->sectionType);
1687             return (XRAN_STATUS_INVALID_PARAM);
1688         }
1689
1690     if(unlikely(xran_prepare_section_func == NULL)) {
1691        print_err("Section Type %d is not supported!", params->sectionType);
1692        return (XRAN_STATUS_INVALID_PARAM);
1693     }
1694
1695     for(i=0; i < params->numSections; i++) {
1696         section = rte_pktmbuf_append(mbuf, section_size);
1697         if(section == NULL) {
1698             print_err("Fail to allocate the space for section[%d]!", i);
1699             return (XRAN_STATUS_RESOURCE);
1700         }
1701         print_dbg("%s %d ef %d\n", __FUNCTION__, i, params->sections[i].info.ef);
1702         ret = xran_prepare_section_func((void *)section,
1703                             (void *)&params->sections[i]);
1704         if(ret < 0){
1705             print_err("%s %d\n", __FUNCTION__, ret);
1706             return (ret);
1707         }
1708         totalen += section_size;
1709
1710         if(params->sections[i].info.ef) {
1711             print_dbg("sections[%d].info.ef %d exDataSize %d  type %d\n", i, params->sections[i].info.ef,
1712                 params->sections[i].exDataSize, params->sections[i].exData[0].type);
1713             ret = xran_append_section_extensions(mbuf, &params->sections[i]);
1714             if(ret < 0)
1715                 return (ret);
1716             totalen += ret;
1717        }
1718     }
1719
1720     return (totalen);
1721 }
1722
1723 /**
1724  * @brief fill the information of a radio application header in a C-Plane packet
1725  *
1726  * @param apphdr
1727  *  A pointer to the application header in the packet buffer
1728  * @param params
1729  *  A porinter to the information to generate a C-Plane packet
1730  * @return
1731  *  XRAN_STATUS_SUCCESS on success
1732  *  XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
1733  */
1734 static inline int32_t
1735 xran_prepare_radioapp_common_header(struct xran_cp_radioapp_common_header *apphdr,
1736                 struct xran_cp_gen_params *params)
1737 {
1738
1739 #if (XRAN_STRICT_PARM_CHECK)
1740     if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
1741         print_err("Invalid direction!");
1742         return (XRAN_STATUS_INVALID_PARAM);
1743         }
1744     if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
1745         print_err("Invalid Slot ID!");
1746         return (XRAN_STATUS_INVALID_PARAM);
1747         }
1748     if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
1749         print_err("Invalid Symbol ID!");
1750         return (XRAN_STATUS_INVALID_PARAM);
1751         }
1752 #endif
1753
1754     /*apphdr->field.all_bits = XRAN_PAYLOAD_VER << 28;
1755     apphdr->field.dataDirection   = params->dir;
1756     //apphdr->field.payloadVer      = XRAN_PAYLOAD_VER;
1757     apphdr->field.filterIndex     = params->hdr.filterIdx;
1758     apphdr->field.frameId         = params->hdr.frameId;
1759     apphdr->field.subframeId      = params->hdr.subframeId;
1760     apphdr->field.slotId          = xran_slotid_convert(params->hdr.slotId, 0);
1761     apphdr->field.startSymbolId   = params->hdr.startSymId;*/
1762
1763     apphdr->field.all_bits   = (params->dir << xran_cp_radioapp_cmn_hdr_bitwidth_DataDir)
1764                              | (XRAN_PAYLOAD_VER << xran_cp_radioapp_cmn_hdr_bitwidth_PayLoadVer)
1765                              | (params->hdr.filterIdx << xran_cp_radioapp_cmn_hdr_bitwidth_FilterIdex)
1766                              | (params->hdr.frameId << xran_cp_radioapp_cmn_hdr_bitwidth_FrameId)
1767                              | (params->hdr.subframeId << xran_cp_radioapp_cmn_hdr_bitwidth_SubFrameId)
1768                              | (xran_slotid_convert(params->hdr.slotId, 0) << xran_cp_radioapp_cmn_hdr_bitwidth_SlotId)
1769                              | (params->hdr.startSymId << xran_cp_radioapp_cmn_hdr_bitwidth_StartSymId);
1770
1771     apphdr->numOfSections   = params->numSections;
1772     apphdr->sectionType     = params->sectionType;
1773
1774     /* radio app header has common parts of 4bytes for all section types */
1775     //*((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1776     *((uint32_t *)apphdr) = rte_cpu_to_be_32(apphdr->field.all_bits);
1777     return (XRAN_STATUS_SUCCESS);
1778 }
1779
1780 /**
1781  * @brief add a radio application header in a C-Plane packet
1782  *
1783  * @param mbuf
1784  *  A pointer to the packet buffer
1785  * @param params
1786  *  A porinter to the information to generate a C-Plane packet
1787  * @return
1788  *  The length of added section (>0) on success
1789  *  XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
1790  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1791  */
1792 int32_t
1793 xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1794 {
1795   int32_t ret;
1796   uint32_t totalen;
1797   struct xran_cp_radioapp_common_header *apphdr;
1798   int32_t (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
1799
1800
1801 #if (XRAN_STRICT_PARM_CHECK)
1802     if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
1803         print_err("Invalid Section Type - %d", params->sectionType);
1804         return (XRAN_STATUS_INVALID_PARAM);
1805         }
1806 #endif
1807
1808     switch(params->sectionType) {
1809         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1810             xran_prepare_radioapp_section_hdr_func = (int32_t (*)(void *, void*))xran_prepare_section0_hdr;
1811             totalen = sizeof(struct xran_cp_radioapp_section0_header);
1812             break;
1813
1814         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1815             xran_prepare_radioapp_section_hdr_func = (int32_t (*)(void *, void*))xran_prepare_section1_hdr;
1816             totalen = sizeof(struct xran_cp_radioapp_section1_header);
1817             break;
1818
1819         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1820             xran_prepare_radioapp_section_hdr_func = (int32_t (*)(void *, void*))xran_prepare_section3_hdr;
1821             totalen = sizeof(struct xran_cp_radioapp_section3_header);
1822             break;
1823
1824         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1825         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1826         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1827         default:
1828             print_err("Section Type %d is not supported!", params->sectionType);
1829             xran_prepare_radioapp_section_hdr_func = NULL;
1830             totalen = 0;
1831             return (XRAN_STATUS_INVALID_PARAM);
1832         }
1833
1834     apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
1835     if(unlikely(apphdr == NULL)) {
1836         print_err("Fail to reserve the space for radio application header!");
1837         return (XRAN_STATUS_RESOURCE);
1838         }
1839
1840     ret = xran_prepare_radioapp_common_header(apphdr, params);
1841     if(unlikely(ret < 0)) {
1842         return (ret);
1843         }
1844
1845     if(likely(xran_prepare_radioapp_section_hdr_func)) {
1846         totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
1847         }
1848     else {
1849         print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
1850         return (XRAN_STATUS_INVALID_PARAM);
1851         }
1852
1853     return (totalen);
1854 }
1855
1856 /**
1857  * @brief Create a C-Plane packet
1858  *  Transport layer fragmentation is not supported.
1859  *
1860  * @ingroup xran_cp_pkt
1861  *
1862  * @param mbuf
1863  *  A pointer to the packet buffer
1864  * @param params
1865  *  A porinter to the information to generate a C-Plane packet
1866  * @param CC_ID
1867  *  Component Carrier ID for this C-Plane message
1868  * @param Ant_ID
1869  *  Antenna ID(RU Port ID) for this C-Plane message
1870  * @param seq_id
1871  *  Sequence ID for this C-Plane message
1872  * @return
1873  *  XRAN_STATUS_SUCCESS on success
1874  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1875  *  XRAN_STATUS_INVALID_PARM if section type is invalid
1876  */
1877 int32_t
1878 xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
1879                         struct xran_cp_gen_params *params,
1880                         uint8_t CC_ID, uint8_t Ant_ID,
1881                         uint8_t seq_id)
1882 {
1883     int32_t ret;
1884   uint32_t payloadlen;
1885   struct xran_ecpri_hdr *ecpri_hdr;
1886
1887     payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
1888
1889     ret = xran_append_radioapp_header(mbuf, params);
1890     if(ret < 0) {
1891         print_err("%s %d\n", __FUNCTION__, ret);
1892         return (ret);
1893     }
1894     payloadlen += ret;
1895
1896     ret = xran_append_control_section(mbuf, params);
1897     if(ret < 0) {
1898         print_err("%s %d\n", __FUNCTION__, ret);
1899         return (ret);
1900     }
1901     payloadlen += ret;
1902
1903     /* set payload length */
1904     ecpri_hdr->cmnhdr.bits.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
1905
1906     return (XRAN_STATUS_SUCCESS);
1907 }
1908
1909 ///////////////////////////////////////
1910 // for RU emulation
1911 int32_t
1912 xran_parse_section_ext1(void *ext, struct xran_sectionext1_info *extinfo)
1913 {
1914     int32_t len;
1915     int32_t total_len;
1916   struct xran_cp_radioapp_section_ext1 *ext1;
1917   uint8_t *data;
1918     int32_t parm_size, iq_size;
1919     int32_t N;
1920   void *pHandle;
1921
1922     pHandle = NULL;
1923     N = xran_get_conf_num_bfweights(pHandle);
1924     extinfo->bfwNumber = N;
1925
1926     ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
1927     data = (uint8_t *)ext;
1928
1929     len = 0;
1930     total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1931
1932     extinfo->bfwCompMeth    = ext1->bfwCompMeth;
1933     extinfo->bfwIqWidth     = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
1934
1935     len     += sizeof(struct xran_cp_radioapp_section_ext1);
1936     data    += sizeof(struct xran_cp_radioapp_section_ext1);
1937
1938     switch(ext1->bfwCompMeth) {
1939         case XRAN_BFWCOMPMETHOD_NONE:
1940             parm_size = 0;
1941             break;
1942
1943         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1944             parm_size = 1;
1945             extinfo->bfwCompParam.exponent = *data & 0x0f;
1946             break;
1947
1948         case XRAN_BFWCOMPMETHOD_BLKSCALE:
1949             parm_size = 1;
1950             extinfo->bfwCompParam.blockScaler = *data;
1951             break;
1952
1953         case XRAN_BFWCOMPMETHOD_ULAW:
1954             parm_size = 1;
1955             extinfo->bfwCompParam.compBitWidthShift = *data;
1956             break;
1957
1958         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
1959             parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
1960             memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
1961             break;
1962
1963         default:
1964             print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
1965             parm_size = 0;
1966         }
1967
1968     len     += parm_size;
1969     data    += parm_size;
1970
1971     /* Get BF weights */
1972     iq_size = N * extinfo->bfwIqWidth * 2;  // total in bits
1973     parm_size = iq_size>>3;                 // total in bytes (/8)
1974     if(iq_size%8) parm_size++;              // round up
1975
1976     //memcpy(data, extinfo->p_bfwIQ, parm_size);
1977     extinfo->p_bfwIQ =  (int16_t*)data;
1978
1979     len += parm_size;
1980
1981     parm_size = len % XRAN_SECTIONEXT_ALIGN;
1982     if(parm_size)
1983         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1984
1985     if(len != total_len) {
1986         // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
1987     }
1988
1989     return (total_len);
1990 }
1991
1992 int32_t
1993 xran_parse_section_ext2(void *ext, struct xran_sectionext2_info *extinfo)
1994 {
1995     int32_t len;
1996     int32_t total_len;
1997   struct xran_cp_radioapp_section_ext2 *ext2;
1998   uint8_t *data;
1999     int32_t parm_size;
2000   uint32_t val;
2001     int32_t val_size;
2002
2003     ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
2004     data = (uint8_t *)ext;
2005     *(uint32_t *)ext2 = rte_be_to_cpu_32(*(uint32_t *)ext2);
2006
2007     len = 0;
2008     total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2009
2010     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
2011
2012     extinfo->bfAzPtWidth    = ext2->bfAzPtWidth;
2013     extinfo->bfZePtWidth    = ext2->bfZePtWidth;
2014     extinfo->bfAz3ddWidth   = ext2->bfAz3ddWidth;
2015     extinfo->bfZe3ddWidth   = ext2->bfZe3ddWidth;
2016
2017     if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
2018         print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
2019
2020     data    += parm_size;
2021     len     += parm_size;
2022
2023     val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
2024                 + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
2025                 + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
2026                 + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
2027     if(val_size) {
2028         val = rte_be_to_cpu_32(*(uint32_t *)data);
2029         val >>= (32 - val_size);
2030
2031         if(extinfo->bfZe3ddWidth) {
2032             extinfo->bfZe3dd    = val & bitmask[extinfo->bfZe3ddWidth];
2033             val >>= (extinfo->bfZe3ddWidth + 1);
2034             }
2035         if(extinfo->bfAz3ddWidth) {
2036             extinfo->bfAz3dd    = val & bitmask[extinfo->bfAz3ddWidth];
2037             val >>= (extinfo->bfAz3ddWidth + 1);
2038             }
2039         if(extinfo->bfZePtWidth) {
2040             extinfo->bfZePt     = val & bitmask[extinfo->bfZePtWidth];
2041             val >>= (extinfo->bfZePtWidth + 1);
2042             }
2043         if(extinfo->bfAzPtWidth) {
2044             extinfo->bfAzPt     = val & bitmask[extinfo->bfAzPtWidth];
2045             val >>= (extinfo->bfAzPtWidth + 1);
2046             }
2047         }
2048
2049     parm_size = val_size/8;
2050     if(val_size%8) parm_size += 1;
2051
2052     data    += parm_size;
2053     len     += parm_size;
2054
2055     extinfo->bfAzSI = (*data >> 3) & 0x07;
2056     extinfo->bfZeSI = *data & 0x07;
2057
2058     data++;
2059     len++;
2060
2061     parm_size = len % XRAN_SECTIONEXT_ALIGN;
2062     if(parm_size)
2063         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
2064
2065     if(len != total_len) {
2066         print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
2067         }
2068
2069     return (total_len);
2070
2071 }
2072
2073 int32_t
2074 xran_parse_section_ext3(void *ext, struct xran_sectionext3_info *extinfo)
2075 {
2076     int32_t len;
2077     int32_t total_len;
2078
2079     total_len = 0;
2080     len = *((uint8_t *)ext + 1);
2081
2082     switch(len) {
2083         case 1:     /* non-first data layer */
2084             {
2085             union xran_cp_radioapp_section_ext3_non_first *ext3_nf;
2086
2087             ext3_nf = (union xran_cp_radioapp_section_ext3_non_first *)ext;
2088             *(uint32_t *)ext3_nf = rte_be_to_cpu_32(*(uint32_t *)ext3_nf);
2089
2090             total_len = ext3_nf->all_bits.extLen * XRAN_SECTIONEXT_ALIGN;    /* from word to byte */
2091
2092             extinfo->codebookIdx= ext3_nf->all_bits.codebookIndex;
2093             extinfo->layerId    = ext3_nf->all_bits.layerId;
2094             extinfo->numLayers  = ext3_nf->all_bits.numLayers;
2095             }
2096             break;
2097
2098         case 3:     /* first data layer with two antenna */
2099         case 4:     /* first data layer with four antenna */
2100             {
2101             union xran_cp_radioapp_section_ext3_first *ext3_f;
2102             uint16_t *beamid;
2103
2104             ext3_f = (union xran_cp_radioapp_section_ext3_first *)ext;
2105             *(uint64_t *)ext3_f = rte_be_to_cpu_64(*(uint64_t *)ext3_f);
2106
2107             total_len = ext3_f->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
2108
2109             extinfo->codebookIdx= ext3_f->all_bits.codebookIndex;
2110             extinfo->layerId    = ext3_f->all_bits.layerId;
2111             extinfo->numLayers  = ext3_f->all_bits.numLayers;
2112             extinfo->txScheme   = ext3_f->all_bits.txScheme;
2113             extinfo->crsReMask  = ext3_f->all_bits.crsReMask;
2114             extinfo->crsShift   = ext3_f->all_bits.crsShift;
2115             extinfo->crsSymNum  = ext3_f->all_bits.crsSymNum;
2116
2117             /* beam IDs are stored from 10th octet */
2118             beamid = (uint16_t *)((uint8_t *)ext + 10);
2119
2120             extinfo->beamIdAP1  = rte_be_to_cpu_16(*beamid++);
2121             if(len == 4) {
2122                 extinfo->beamIdAP2  = rte_be_to_cpu_16(*beamid++);
2123                 extinfo->beamIdAP3  = rte_be_to_cpu_16(*beamid);
2124                 extinfo->numAntPort = 4;
2125                 }
2126             else {
2127                 extinfo->numAntPort = 2;
2128                 }
2129             }
2130             break;
2131
2132         default:
2133             print_err("Invalid length of extension 3 - %d", len);
2134         }
2135
2136     return (total_len);
2137 }
2138
2139 int32_t
2140 xran_parse_section_ext4(void *ext, struct xran_sectionext4_info *extinfo)
2141 {
2142     int32_t len;
2143   struct xran_cp_radioapp_section_ext4 *ext4;
2144     int32_t total_len;
2145
2146     ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
2147
2148     *(uint32_t *)ext4 = rte_be_to_cpu_32(*(uint32_t *)ext4);
2149
2150     len = 0;
2151     total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2152
2153     extinfo->modCompScaler  = ext4->modCompScaler;
2154     extinfo->csf            = ext4->csf;
2155
2156     len += sizeof(struct xran_cp_radioapp_section_ext4);
2157     if(len != total_len) {
2158         print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
2159         }
2160
2161     return (total_len);
2162 }
2163
2164 int32_t
2165 xran_parse_section_ext5(void *ext,
2166                 struct xran_sectionext5_info *extinfo)
2167 {
2168     int32_t len;
2169   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
2170   struct xran_cp_radioapp_section_ext5 ext5;
2171     int32_t parm_size;
2172     int32_t total_len;
2173   uint8_t *data;
2174   uint16_t i;
2175
2176     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
2177     *(uint16_t *)ext_hdr = rte_be_to_cpu_16(*(uint16_t *)ext_hdr);
2178
2179     total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2180
2181     /* one set has 3.5 bytes, so enforcing double to do integer calculation */
2182     parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
2183
2184     if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
2185         print_err("Exceeds maximum number of parameters - %d", parm_size);
2186         parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
2187     }
2188
2189     len = 0;
2190     data = (uint8_t *)(ext_hdr + 1);
2191
2192     i = 0;
2193     while(i < parm_size) {
2194         // For odd number set, more data can be copied
2195         *((uint64_t *)&ext5) = rte_be_to_cpu_64(*((uint64_t *)data));
2196
2197         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset1;
2198         extinfo->mc[i].csf              = ext5.csf1;
2199         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask1;
2200         i++;
2201
2202         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset2;
2203         extinfo->mc[i].csf              = ext5.csf2;
2204         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask2;
2205         i++;
2206
2207         data += sizeof(struct xran_cp_radioapp_section_ext5);
2208         }
2209
2210     /* check the values of last set
2211      * due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
2212      * don't check mcScaleOffset might not be zero (some part is out of zero-padding) */
2213     i--;
2214     if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
2215         if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
2216             extinfo->num_sets = i;
2217         else
2218             extinfo->num_sets = i+1;
2219     }else {
2220         print_err("Maximum total number %d is not correct!", i);
2221     }
2222
2223     return (total_len);
2224 }
2225
2226 int32_t
2227 xran_parse_section_ext6(void *ext,
2228                 struct xran_sectionext6_info *extinfo)
2229 {
2230     int32_t len;
2231     union xran_cp_radioapp_section_ext6 *ext6;
2232     int32_t total_len;
2233
2234     ext6 = (union xran_cp_radioapp_section_ext6 *)ext;
2235     *(uint64_t *)ext6 = rte_be_to_cpu_64(*(uint64_t *)ext6);
2236
2237     total_len = ext6->all_bits.extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2238
2239     extinfo->rbgSize    = ext6->all_bits.rbgSize;
2240     extinfo->rbgMask    = ext6->all_bits.rbgMask;
2241     extinfo->symbolMask = ext6->all_bits.symbolMask;
2242
2243     len = sizeof(union xran_cp_radioapp_section_ext6);
2244     if(len != total_len) {
2245         print_err("The size of extension 6 is not correct! [%d:%d]", len, total_len);
2246         }
2247
2248     return (total_len);
2249 }
2250
2251 int32_t
2252 xran_parse_section_ext10(void *ext,
2253                 struct xran_sectionext10_info *extinfo)
2254 {
2255     int32_t len, padding;
2256     int32_t i;
2257     union xran_cp_radioapp_section_ext10 *ext10;
2258     int32_t total_len;
2259     uint16_t *ptr;
2260
2261     ext10 = (union xran_cp_radioapp_section_ext10 *)ext;
2262
2263     total_len = ext10->all_bits.extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2264
2265     extinfo->numPortc   = ext10->all_bits.numPortc;
2266     extinfo->beamGrpType= ext10->all_bits.beamGroupType;
2267
2268     len = sizeof(union xran_cp_radioapp_section_ext10);
2269     if(ext10->all_bits.beamGroupType == XRAN_BEAMGT_VECTORLIST) {
2270         len += extinfo->numPortc * 2 - 1;
2271         padding = len % XRAN_SECTIONEXT_ALIGN;
2272         if(padding) {
2273             padding = XRAN_SECTIONEXT_ALIGN - padding;
2274             len += padding;
2275             }
2276
2277         ptr = (uint16_t *)&ext10->all_bits.reserved;
2278         for(i=0; i < extinfo->numPortc; i++)
2279             extinfo->beamID[i] = rte_be_to_cpu_16(ptr[i]);
2280         }
2281
2282     if(len != total_len) {
2283         print_err("The size of extension 10 is not correct! [%d:%d]", len, total_len);
2284         }
2285
2286     return (total_len);
2287 }
2288
2289 int32_t
2290 xran_parse_section_ext11(void *ext,
2291                          struct xran_sectionext11_recv_info *extinfo)
2292 {
2293     int32_t len;
2294     int32_t total_len;
2295     union xran_cp_radioapp_section_ext11 *ext11;
2296     uint8_t *data;
2297     int32_t parm_size, iq_size;
2298     int32_t N;
2299     void *pHandle;
2300
2301     pHandle = NULL;
2302     N = xran_get_conf_num_bfweights(pHandle);
2303
2304     ext11 = (union xran_cp_radioapp_section_ext11 *)ext;
2305     data = (uint8_t *)ext;
2306
2307     *(uint32_t *)ext11 = rte_cpu_to_be_32(*(uint32_t*)ext11);
2308     total_len = ext11->all_bits.extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
2309
2310     extinfo->RAD            = ext11->all_bits.RAD;
2311     extinfo->disableBFWs    = ext11->all_bits.disableBFWs;
2312     extinfo->numBundPrb     = ext11->all_bits.numBundPrb;
2313     extinfo->bfwCompMeth    = ext11->all_bits.bfwCompMeth;
2314     extinfo->bfwIqWidth     = (ext11->all_bits.bfwIqWidth==0)?16:ext11->all_bits.bfwIqWidth;
2315
2316     len     = sizeof(union xran_cp_radioapp_section_ext11);
2317     data    += sizeof(union xran_cp_radioapp_section_ext11);
2318
2319     extinfo->numSetBFWs = 0;
2320     while((len+4) < total_len) {    /* adding 4 is to consider zero pads */
2321         /* Get bfwCompParam */
2322         switch(ext11->all_bits.bfwCompMeth) {
2323             case XRAN_BFWCOMPMETHOD_NONE:
2324                 parm_size = 0;
2325                 break;
2326
2327             case XRAN_BFWCOMPMETHOD_BLKFLOAT:
2328                 parm_size = 1;
2329                 extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.exponent = *data & 0x0f;
2330                 break;
2331 #if 0   /* Not supported */
2332             case XRAN_BFWCOMPMETHOD_BLKSCALE:
2333                 parm_size = 1;
2334                 extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.blockScaler = *data;
2335                 break;
2336
2337             case XRAN_BFWCOMPMETHOD_ULAW:
2338                 parm_size = 1;
2339                 extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.compBitWidthShift = *data;
2340                 break;
2341
2342             case XRAN_BFWCOMPMETHOD_BEAMSPACE:
2343                 parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
2344                 memcpy(data, extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.activeBeamspaceCoeffMask, parm_size);
2345                 break;
2346 #endif
2347             default:
2348                 print_err("Invalid BfComp method - %d", ext11->all_bits.bfwCompMeth);
2349                 parm_size = 0;
2350             }
2351         len     += parm_size;
2352         data    += parm_size;
2353
2354         /* Get beam ID */
2355         extinfo->bundInfo[extinfo->numSetBFWs].beamId = rte_be_to_cpu_16(*((int16_t *)data));
2356         len     += sizeof(int16_t);
2357         data    += sizeof(int16_t);
2358
2359         /* Get BF weights */
2360         iq_size = N * extinfo->bfwIqWidth * 2;  // total in bits
2361         parm_size = iq_size>>3;                 // total in bytes (/8)
2362         if(iq_size%8) parm_size++;              // round up
2363
2364         if(extinfo->bundInfo[extinfo->numSetBFWs].pBFWs) {
2365             memcpy(extinfo->bundInfo[extinfo->numSetBFWs].pBFWs, data, parm_size);
2366             }
2367         extinfo->bundInfo[extinfo->numSetBFWs].BFWSize  = parm_size;
2368
2369         len     += parm_size;
2370         data    += parm_size;
2371         extinfo->numSetBFWs++;
2372         }
2373
2374     parm_size = len % XRAN_SECTIONEXT_ALIGN;
2375     if(parm_size)
2376         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
2377
2378     if(len != total_len) {
2379         print_err("The size of extension 11 is not correct! [%d:%d]", len, total_len);
2380         }
2381
2382     return (total_len);
2383 }
2384
2385 int32_t
2386 xran_parse_section_extension(struct rte_mbuf *mbuf,
2387                     void *ext,
2388                              struct xran_section_recv_info *section)
2389 {
2390     int32_t total_len, len, numext;
2391   uint8_t *ptr;
2392     int32_t flag_last;
2393     int32_t ext_type;
2394     int32_t i;
2395
2396     total_len = 0;
2397     ptr = (uint8_t *)ext;
2398
2399     numext = 0;
2400
2401     flag_last = 1;
2402     i = 0;
2403     while(flag_last) {
2404         /* check ef */
2405         flag_last = (*ptr & 0x80);
2406
2407         ext_type = *ptr & 0x7f;
2408         section->exts[numext].type = ext_type;
2409         switch(ext_type) {
2410             case XRAN_CP_SECTIONEXTCMD_1:
2411                 len = xran_parse_section_ext1(ptr, &section->exts[numext].u.ext1);
2412                 break;
2413             case XRAN_CP_SECTIONEXTCMD_2:
2414                 len = xran_parse_section_ext2(ptr, &section->exts[numext].u.ext2);
2415                 break;
2416             case XRAN_CP_SECTIONEXTCMD_3:
2417                 len = xran_parse_section_ext3(ptr, &section->exts[numext].u.ext3);
2418                 break;
2419             case XRAN_CP_SECTIONEXTCMD_4:
2420                 len = xran_parse_section_ext4(ptr, &section->exts[numext].u.ext4);
2421                 break;
2422             case XRAN_CP_SECTIONEXTCMD_5:
2423                 len = xran_parse_section_ext5(ptr, &section->exts[numext].u.ext5);
2424                 break;
2425             case XRAN_CP_SECTIONEXTCMD_6:
2426                 len = xran_parse_section_ext6(ptr, &section->exts[numext].u.ext6);
2427                 break;
2428             case XRAN_CP_SECTIONEXTCMD_10:
2429                 len = xran_parse_section_ext10(ptr, &section->exts[numext].u.ext10);
2430                 break;
2431             case XRAN_CP_SECTIONEXTCMD_11:
2432                 len = xran_parse_section_ext11(ptr, &section->exts[numext].u.ext11);
2433                 break;
2434
2435             default:
2436                 print_err("Extension %d is not supported!", ext_type);
2437                 len = 0;
2438             }
2439
2440         section->exts[numext].size = len;
2441         ptr += len; total_len += len;
2442
2443         i++;
2444         if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
2445
2446         /* exceeds maximum number of extensions */
2447         break;
2448         }
2449
2450     section->numExts = numext;
2451
2452     return (total_len);
2453 }
2454
2455 /**
2456  * @brief Parse a C-Plane packet (for RU emulation)
2457  *  Transport layer fragmentation is not supported.
2458  *
2459  * @ingroup xran_cp_pkt
2460  *
2461  * @param mbuf
2462  *  The pointer of the packet buffer to be parsed
2463  * @param params
2464  *  The pointer of structure to store the information of parsed packet
2465  * @param eaxc
2466  *  The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
2467  * @return
2468  *  XRAN_STATUS_SUCCESS on success
2469  *  XRAN_STATUS_INVALID_PACKET if failed to parse the packet
2470  */
2471 int32_t
2472 xran_parse_cp_pkt(struct rte_mbuf *mbuf,
2473                     struct xran_cp_recv_params *result,
2474                     struct xran_recv_packet_info *pkt_info)
2475 {
2476   struct xran_ecpri_hdr *ecpri_hdr;
2477   struct xran_cp_radioapp_common_header *apphdr;
2478     int32_t i, ret;
2479     int32_t extlen;
2480
2481     ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
2482     if(ret < 0 && ecpri_hdr == NULL)
2483         return (XRAN_STATUS_INVALID_PACKET);
2484
2485     /* Process radio header. */
2486     apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
2487     if(apphdr == NULL) {
2488         print_err("Invalid packet - radio app hedaer!");
2489         return (XRAN_STATUS_INVALID_PACKET);
2490         }
2491
2492     *((uint32_t *)apphdr) = rte_be_to_cpu_32(*((uint32_t *)apphdr));
2493
2494     if(apphdr->field.payloadVer != XRAN_PAYLOAD_VER) {
2495         print_err("Invalid Payload version - %d", apphdr->field.payloadVer);
2496         ret = XRAN_STATUS_INVALID_PACKET;
2497         }
2498
2499     result->dir             = apphdr->field.dataDirection;
2500     result->hdr.filterIdx   = apphdr->field.filterIndex;
2501     result->hdr.frameId     = apphdr->field.frameId;
2502     result->hdr.subframeId  = apphdr->field.subframeId;
2503     result->hdr.slotId      = apphdr->field.slotId;
2504     result->hdr.startSymId  = apphdr->field.startSymbolId;
2505     result->sectionType     = apphdr->sectionType;
2506     result->numSections     = apphdr->numOfSections;
2507
2508 #if 0
2509     printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
2510         pkt_info->payload_len,
2511         pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
2512         pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
2513         result->dir?"DL":"UL",
2514         pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
2515         result->sectionType, result->numSections,
2516         result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
2517         result->hdr.startSymId
2518         );
2519 #endif
2520
2521     switch(apphdr->sectionType) {
2522         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
2523             {
2524             struct xran_cp_radioapp_section0_header *hdr;
2525             struct xran_cp_radioapp_section0 *section;
2526
2527                 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
2528
2529                 result->hdr.fftSize     = rte_be_to_cpu_16(hdr->timeOffset);
2530                 result->hdr.scs         = hdr->frameStructure.fftSize;
2531                 result->hdr.timeOffset  = hdr->frameStructure.uScs;
2532                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
2533                 //hdr->reserved;    /* should be zero */
2534
2535                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
2536                 if(section == NULL) {
2537                     print_err("Invalid packet: section type0 - radio app hedaer!");
2538                     return (XRAN_STATUS_INVALID_PACKET);
2539                     }
2540                 for(i=0; i<result->numSections; i++) {
2541                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
2542
2543                     result->sections[i].info.type       = apphdr->sectionType;
2544                     result->sections[i].info.id         = section->hdr.u1.common.sectionId;
2545                     result->sections[i].info.rb         = section->hdr.u1.common.rb;
2546                     result->sections[i].info.symInc     = section->hdr.u1.common.symInc;
2547                     result->sections[i].info.startPrbc  = section->hdr.u1.common.startPrbc;
2548                     result->sections[i].info.numPrbc    = section->hdr.u1.common.numPrbc,
2549                     result->sections[i].info.numSymbol  = section->hdr.u.s0.numSymbol;
2550                     result->sections[i].info.reMask     = section->hdr.u.s0.reMask;
2551                     //section->hdr.u.s0.reserved;   /* should be zero */
2552
2553                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
2554                     if(section == NULL) {
2555                         print_err("Invalid packet: section type0 - number of section [%d:%d]!",
2556                                     result->numSections, i);
2557                         result->numSections = i;
2558                         ret = XRAN_STATUS_INVALID_PACKET;
2559                         break;
2560                         }
2561                     }
2562             }
2563             break;
2564
2565         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
2566             {
2567             struct xran_cp_radioapp_section1_header *hdr;
2568             struct xran_cp_radioapp_section1 *section;
2569
2570                 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
2571
2572                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
2573                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
2574
2575                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
2576                 if(section == NULL) {
2577                     print_err("Invalid packet: section type1 - radio app hedaer!");
2578                     return (XRAN_STATUS_INVALID_PACKET);
2579                     }
2580
2581                 for(i=0; i<result->numSections; i++) {
2582                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
2583
2584                     result->sections[i].info.type       = apphdr->sectionType;
2585                     result->sections[i].info.id         = section->hdr.u1.common.sectionId;
2586                     result->sections[i].info.rb         = section->hdr.u1.common.rb;
2587                     result->sections[i].info.symInc     = section->hdr.u1.common.symInc;
2588                     result->sections[i].info.startPrbc  = section->hdr.u1.common.startPrbc;
2589                     result->sections[i].info.numPrbc    = section->hdr.u1.common.numPrbc,
2590                     result->sections[i].info.numSymbol  = section->hdr.u.s1.numSymbol;
2591                     result->sections[i].info.reMask     = section->hdr.u.s1.reMask;
2592                     result->sections[i].info.beamId     = section->hdr.u.s1.beamId;
2593                     result->sections[i].info.ef         = section->hdr.u.s1.ef;
2594
2595                     section = (void *)rte_pktmbuf_adj(mbuf,
2596                                     sizeof(struct xran_cp_radioapp_section1));
2597                     if(section == NULL) {
2598                         print_err("Invalid packet: section type1 - number of section [%d:%d]!",
2599                                     result->numSections, i);
2600                         result->numSections = i;
2601                         ret = XRAN_STATUS_INVALID_PACKET;
2602                         break;
2603                         }
2604
2605                     if(result->sections[i].info.ef) {
2606                         // parse section extension
2607                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
2608                         if(extlen > 0) {
2609                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
2610                             if(section == NULL) {
2611                                 print_err("Invalid packet: section type1 - section extension [%d]!", i);
2612                                 ret = XRAN_STATUS_INVALID_PACKET;
2613                                 break;
2614                                 }
2615                             }
2616                         }
2617                     else extlen = 0;
2618                     }
2619             }
2620             break;
2621
2622         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
2623             {
2624             struct xran_cp_radioapp_section3_header *hdr;
2625             struct xran_cp_radioapp_section3 *section;
2626
2627                 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
2628
2629                 result->hdr.timeOffset  = rte_be_to_cpu_16(hdr->timeOffset);
2630                 result->hdr.scs         = hdr->frameStructure.uScs;
2631                 result->hdr.fftSize     = hdr->frameStructure.fftSize;
2632                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
2633                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
2634                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
2635
2636                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
2637                 if(section == NULL) {
2638                     print_err("Invalid packet: section type3 - radio app hedaer!");
2639                     return (XRAN_STATUS_INVALID_PACKET);
2640                     }
2641
2642                 for(i=0; i<result->numSections; i++) {
2643                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
2644
2645                     result->sections[i].info.type       = apphdr->sectionType;
2646                     result->sections[i].info.id         = section->hdr.u1.common.sectionId;
2647                     result->sections[i].info.rb         = section->hdr.u1.common.rb;
2648                     result->sections[i].info.symInc     = section->hdr.u1.common.symInc;
2649                     result->sections[i].info.startPrbc  = section->hdr.u1.common.startPrbc;
2650                     result->sections[i].info.numPrbc    = section->hdr.u1.common.numPrbc,
2651                     result->sections[i].info.numSymbol  = section->hdr.u.s3.numSymbol;
2652                     result->sections[i].info.reMask     = section->hdr.u.s3.reMask;
2653                     result->sections[i].info.beamId     = section->hdr.u.s3.beamId;
2654                     result->sections[i].info.ef         = section->hdr.u.s3.ef;
2655                     result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
2656
2657                     if(section->reserved) {
2658                         print_err("Invalid packet: section type3 - section[%d] reserved[%d]", i, section->reserved);
2659                         ret = XRAN_STATUS_INVALID_PACKET;
2660                         }
2661
2662                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3));
2663                     if(section == NULL) {
2664                         print_err("Invalid packet: section type3 - number of section [%d:%d]!",
2665                                     result->numSections, i);
2666                         result->numSections = i;
2667                         ret = XRAN_STATUS_INVALID_PACKET;
2668                         break;
2669                         }
2670
2671                     if(result->sections[i].info.ef) {
2672                         // parse section extension
2673                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
2674                         if(extlen > 0) {
2675                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
2676                             if(section == NULL) {
2677                                 print_err("Invalid packet: section type3 - section extension [%d]!", i);
2678                                 ret = XRAN_STATUS_INVALID_PACKET;
2679                                 break;
2680                                 }
2681                             }
2682                         }
2683                     else extlen = 0;
2684                     }
2685             }
2686             break;
2687
2688         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
2689         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
2690         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
2691         default:
2692             ret = XRAN_STATUS_INVALID_PARAM;
2693             print_err("Non-supported Section Type - %d", apphdr->sectionType);
2694         }
2695
2696 #if 0
2697     printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
2698             result->dir?"DL":"UL",
2699             result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
2700             result->sectionType, result->numSections,
2701             result->hdr.startSymId,
2702             result->hdr.filterIdx,
2703             result->hdr.iqWidth, result->hdr.compMeth);
2704
2705     for(i=0; i<result->numSections; i++) {
2706         printf("  || %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
2707             i, result->sections[i].info.id,
2708             result->sections[i].info.rb,
2709             result->sections[i].info.symInc, result->sections[i].info.numSymbol,
2710             result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
2711             result->sections[i].info.reMask,
2712             result->sections[i].info.beamId,
2713             result->sections[i].info.freqOffset,
2714             result->sections[i].info.ef);
2715
2716         if(result->sections[i].info.ef) {
2717             for(int32_t j=0; j<result->sections[i].exDataSize; j++) {
2718                 printf("      || %2d : type=%d len=%d\n",
2719                         j, result->sections[i].exData[j].type, result->sections[i].exData[j].len);
2720                 switch(result->sections[i].exData[j].type) {
2721                     case XRAN_CP_SECTIONEXTCMD_1:
2722                         {
2723                         struct xran_sectionext1_info *ext1;
2724                         ext1 = result->sections[i].exData[j].data;
2725                         printf("      ||    bfwNumber=%d bfwIqWidth=%d bfwCompMeth=%d\n",
2726                                 ext1->bfwNumber, ext1->bfwIqWidth, ext1->bfwCompMeth);
2727                         }
2728                         break;
2729                     case XRAN_CP_SECTIONEXTCMD_2:
2730                         {
2731                         struct xran_sectionext2_info *ext2;
2732                         ext2 = result->sections[i].exData[j].data;
2733                         printf("      ||    AzPt=%02x(%d) ZePt=%02x(%d) Az3dd=%02x(%d) Ze3dd=%02x(%d) AzSI=%02x ZeSI=%02x\n",
2734                                 ext2->bfAzPt, ext2->bfAzPtWidth,
2735                                 ext2->bfZePt, ext2->bfZePtWidth,
2736                                 ext2->bfAz3dd, ext2->bfAz3ddWidth,
2737                                 ext2->bfZe3dd, ext2->bfZe3ddWidth,
2738                                 ext2->bfAzSI, ext2->bfZeSI);
2739                         }
2740                         break;
2741                     case XRAN_CP_SECTIONEXTCMD_4:
2742                         {
2743                         struct xran_sectionext4_info *ext4;
2744                         ext4 = result->sections[i].exData[j].data;
2745                         printf("      ||    csf=%d modCompScaler=%d\n",
2746                                 ext4->csf, ext4->modCompScaler);
2747                         }
2748                         break;
2749                     case XRAN_CP_SECTIONEXTCMD_5:
2750                         {
2751                         struct xran_sectionext5_info *ext5;
2752                         ext5 = result->sections[i].exData[j].data;
2753                         printf("      ||    num_sets=%d\n", ext5->num_sets);
2754                         for(int32_t k=0; k<ext5->num_sets; k++) {
2755                             printf("          || %d - csf=%d mcScaleReMask=%04x mcScaleOffset=%04x\n",
2756                                 k, ext5->mc[k].csf,
2757                                 ext5->mc[k].mcScaleReMask, ext5->mc[k].mcScaleOffset);
2758                             }
2759                         }
2760                         break;
2761
2762                     case XRAN_CP_SECTIONEXTCMD_0:
2763                     case XRAN_CP_SECTIONEXTCMD_3:
2764                     default:
2765                         printf("Invalid section extension type!\n");
2766                     }
2767                 }
2768             }
2769         }
2770 #endif
2771
2772     return(ret);
2773 }