ecefbc05596c191aed823bf8455fef1985a3732d
[o-du/phy.git] / fhi_lib / lib / src / xran_cp_api.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 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
29 #include <rte_branch_prediction.h>
30
31 #include "xran_common.h"
32 #include "xran_transport.h"
33 #include "xran_cp_api.h"
34 #include "xran_printf.h"
35 #include "xran_compression.h"
36
37
38 /**
39  * This structure to store the section information of C-Plane
40  * in order to generate and parse corresponding U-Plane */
41 struct xran_sectioninfo_db {
42     uint32_t    cur_index;  /**< Current index to store for this eAXC */
43     struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /**< The array of section information */
44     };
45
46 static struct xran_sectioninfo_db sectiondb[XRAN_MAX_SECTIONDB_CTX][XRAN_DIR_MAX][XRAN_COMPONENT_CARRIERS_MAX][XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR];
47
48 static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };
49 static const uint8_t bitmask[] = { 0x00, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
50
51
52 /**
53  * @brief Initialize section database.
54  *   Allocate required memory space to store section information.
55  *   Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.
56  *   Total entry size : number of CC * number of antenna * max number of sections * 2(direction)
57  *
58  * @ingroup xran_cp_pkt
59  *
60  * @param pHandle
61  *  handle for xRAN interface, currently not being used
62  * @return
63  *  XRAN_STATUS_SUCCESS on success
64  *  XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area
65  */
66 int xran_cp_init_sectiondb(void *pHandle)
67 {
68   int ctx, dir, cc, ant;
69
70     for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)
71         for(dir=0; dir < XRAN_DIR_MAX; dir++)
72             for(cc=0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)
73                 for(ant=0; ant < XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR; ant++)
74                     sectiondb[ctx][dir][cc][ant].cur_index = 0;
75
76     return (XRAN_STATUS_SUCCESS);
77 }
78
79 /**
80  * @brief Release and free section database
81  *
82  * @ingroup xran_cp_pkt
83  *
84  * @param pHandle
85  *  handle for xRAN interface, currently not being used
86  * @return
87  *  XRAN_STATUS_SUCCESS on success
88  */
89 int xran_cp_free_sectiondb(void *pHandle)
90 {
91     return (XRAN_STATUS_SUCCESS);
92 }
93
94 static inline struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,
95         uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
96 {
97   struct xran_sectioninfo_db *ptr;
98
99
100     if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {
101         print_err("Invalid Context id - %d", ctx_id);
102         return (NULL);
103         }
104
105     if(unlikely(dir >= XRAN_DIR_MAX)) {
106         print_err("Invalid direction - %d", dir);
107         return (NULL);
108         }
109
110     if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {
111         print_err("Invalid CC id - %d", cc_id);
112         return (NULL);
113         }
114
115     if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2 + XRAN_MAX_ANT_ARRAY_ELM_NR)) {
116         print_err("Invalid eAxC id - %d", ruport_id);
117         return (NULL);
118         }
119
120     ptr = &sectiondb[ctx_id][dir][cc_id][ruport_id];
121
122     return(ptr);
123 }
124
125 static inline struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
126 {
127     if(unlikely(ptr == NULL))
128         return (NULL);
129
130     if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {
131         print_err("Index is out of range - %d", index);
132         return (NULL);
133         }
134
135     return(&(ptr->list[index]));
136 }
137
138 /**
139  * @brief Add a section information of C-Plane to dabase.
140  *
141  * @ingroup xran_cp_pkt
142  *
143  * @param pHandle
144  *  handle for xRAN interface, currently not being used
145  * @param dir
146  *  Direction of C-Plane message for the section to store
147  * @param cc_id
148  *  CC ID of C-Plane message for the section to store
149  * @param ruport_id
150  *  RU port ID of C-Plane message for the section to store
151  * @param ctx_id
152  *  Context index for the section database
153  * @param info
154  *  The information of this section to store
155  * @return
156  *  XRAN_STATUS_SUCCESS on success
157  *  XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect
158  *  XRAN_STATUS_RESOURCE, if no more space to add on database
159  */
160 int xran_cp_add_section_info(void *pHandle,
161         uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
162         struct xran_section_info *info)
163 {
164   struct xran_sectioninfo_db *ptr;
165   struct xran_section_info *list;
166
167
168     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
169     if(unlikely(ptr == NULL)) {
170         return (XRAN_STATUS_INVALID_PARAM);
171         }
172
173     if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {
174         print_err("No more space to add section information!");
175         return (XRAN_STATUS_RESOURCE);
176         }
177
178     list = xran_get_section_info(ptr, ptr->cur_index);
179
180     rte_memcpy(list, info, sizeof(struct xran_section_info));
181
182     ptr->cur_index++;
183
184     return (XRAN_STATUS_SUCCESS);
185 }
186
187 int xran_cp_add_multisection_info(void *pHandle,
188         uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
189         struct xran_cp_gen_params *gen_info)
190 {
191   int i;
192   uint8_t dir, num_sections;
193   struct xran_sectioninfo_db *ptr;
194   struct xran_section_info *list;
195
196
197     dir             = gen_info->dir;
198     num_sections    = gen_info->numSections;
199
200     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
201     if(unlikely(ptr == NULL)) {
202         return (XRAN_STATUS_INVALID_PARAM);
203         }
204
205     if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {
206         print_err("No more space to add section information!");
207         return (XRAN_STATUS_RESOURCE);
208         }
209
210     list = xran_get_section_info(ptr, ptr->cur_index);
211
212     for(i=0; i<num_sections; i++) {
213         rte_memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));
214         ptr->cur_index++;
215         }
216
217     return (XRAN_STATUS_SUCCESS);
218 }
219
220 /**
221  * @brief Find a section information of C-Plane from dabase
222  *   by given information
223  *
224  * @ingroup xran_cp_pkt
225  *
226  * @param pHandle
227  *  handle for xRAN interface, currently not being used
228  * @param dir
229  *  The direction of the section to find
230  * @param cc_id
231  *  The CC ID of the section to find
232  * @param ruport_id
233  *  RU port ID of the section to find
234  * @param ctx_id
235  *  Context index for the section database
236  * @param section_id
237  *  The ID of section to find
238  * @return
239  *  The pointer of section information if matched section is found
240  *  NULL if failed to find matched section
241  */
242 struct xran_section_info *xran_cp_find_section_info(void *pHandle,
243         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
244         uint8_t ctx_id, uint16_t section_id)
245 {
246   int index, num_index;
247   struct xran_sectioninfo_db *ptr;
248
249
250     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
251     if(unlikely(ptr == NULL))
252         return (NULL);
253
254     if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)
255         num_index = XRAN_MAX_NUM_SECTIONS;
256     else
257         num_index = ptr->cur_index;
258
259     for(index=0; index < num_index; index++) {
260         if(ptr->list[index].id == section_id) {
261             return (xran_get_section_info(ptr, index));
262             }
263         }
264
265     print_dbg("No section ID in the list - %d", section_id);
266     return (NULL);
267 }
268
269 /**
270  * @brief Iterate each section information of C-Plane
271  *  from the database of eAxC by given information
272  *
273  * @ingroup xran_cp_pkt
274  *
275  * @param pHandle
276  *  handle for xRAN interface, currently not being used
277  * @param dir
278  *  The direction of the section to find
279  * @param cc_id
280  *  The CC ID of the section to find
281  * @param ruport_id
282  *  RU port ID of the section to find
283  * @param ctx_id
284  *  Context index for the section database
285  * @param next
286  *  The pointer to store the position of next entry
287  * @return
288  *  The pointer of section information in the list
289  *  NULL if reached at the end of the list
290  */
291 struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,
292         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
293         uint8_t ctx_id, uint32_t *next)
294 {
295   int index;
296   struct xran_sectioninfo_db *ptr;
297
298
299     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
300     if(unlikely(ptr == NULL))
301         return (NULL);
302
303     index = *next;
304     if(*next < ptr->cur_index) {
305         (*next)++;
306         return (xran_get_section_info(ptr, index));
307         }
308     else {
309         print_dbg("No more sections in the list");
310         return (NULL);
311         }
312 }
313
314 /**
315  * @brief Get the size of stored entries
316  *  for the database of eAxC by given information
317  *
318  * @ingroup xran_cp_pkt
319  *
320  * @param pHandle
321  *  handle for xRAN interface, currently not being used
322  * @param dir
323  *  The direction of the section to find
324  * @param cc_id
325  *  The CC ID of the section to find
326  * @param ruport_id
327  *  RU port ID of the section to find
328  * @param ctx_id
329  *  Context index for the section database
330  * @return
331  *  The size of stored entries
332  *  -1 if failed to find matched database
333  */
334 int32_t xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
335 {
336   int index;
337   struct xran_sectioninfo_db *ptr;
338
339
340     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
341     if(unlikely(ptr == NULL))
342         return (-1);
343
344     return (ptr->cur_index);
345 }
346
347 /**
348  * @brief Reset a database of eAxC by given information
349  *
350  * @ingroup xran_cp_pkt
351  *
352  * @param pHandle
353  *  handle for xRAN interface, currently not being used
354  * @param dir
355  *  The direction of the section to find
356  * @param cc_id
357  *  The CC ID of the section to find
358  * @param ruport_id
359  *  RU port ID of the section to find
360  * @param ctx_id
361  *  Context index for the section database
362  * @return
363  *  XRAN_STATUS_SUCCESS on success
364  *  XRAN_STATUS_INVALID_PARM if failed to find matched database
365  */
366 int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
367 {
368   struct xran_sectioninfo_db *ptr;
369
370     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
371     if(unlikely(ptr == NULL)) {
372         return (XRAN_STATUS_INVALID_PARAM);
373         }
374
375     ptr->cur_index = 0;
376
377     return (XRAN_STATUS_SUCCESS);
378 }
379
380
381 int xran_dump_sectiondb(void)
382 {
383     // TODO:
384     return (0);
385 }
386
387 int32_t xran_cp_populate_section_ext_1(int8_t  *p_ext1_dst,    /**< destination buffer */
388                                        uint16_t  ext1_dst_len, /**< dest buffer size */
389                                        int16_t  *p_bfw_iq_src, /**< source buffer of IQs */
390                                        uint16_t  rbNum,        /* number RBs to ext1 chain */
391                                        uint16_t  bfwNumPerRb,  /* number of bf weights per RB (i.e. antenna elements) */
392                                        uint8_t   bfwiqWidth,   /* bit size of IQs */
393                                        uint8_t   bfwCompMeth)  /* compression method */
394 {
395     struct xran_cp_radioapp_section_ext1 *p_ext1;
396
397     uint8_t *p_bfw_content = NULL;
398     int32_t parm_size   = 0;
399     int32_t bfw_iq_bits = 0;
400     int32_t total_len   = 0;
401     int32_t comp_len    = 0;
402     uint8_t ext_flag    = XRAN_EF_F_ANOTHER_ONE;
403     int16_t idxRb       = 0;
404     int16_t cur_ext_len = 0;
405     int8_t  *p_ext1_dst_cur = NULL;
406
407     struct xranlib_compress_request  bfp_com_req;
408     struct xranlib_compress_response bfp_com_rsp;
409
410     memset(&bfp_com_req, 0, sizeof(struct xranlib_compress_request));
411     memset(&bfp_com_rsp, 0, sizeof(struct xranlib_compress_response));
412
413     print_dbg("%s comp %d\n", __FUNCTION__, bfwCompMeth);
414     print_dbg("bfwNumPerRb %d bfwiqWidth %d\n", bfwNumPerRb, bfwiqWidth);
415
416     if(p_ext1_dst)
417         p_ext1_dst_cur = p_ext1_dst;
418     else
419         return (XRAN_STATUS_INVALID_PARAM);
420
421     /* create extType=1 section for each RB */
422     for (idxRb = 0; idxRb < rbNum; idxRb++) {
423         print_dbg("%s RB %d\n", __FUNCTION__, idxRb);
424
425         if(total_len >= ext1_dst_len){
426             print_err("p_ext1_dst overflow\n");
427             return -1;
428         }
429
430         cur_ext_len = 0; /** populate one extType=1 section with BFW for 1 RB */
431         parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
432         p_ext1 = (struct xran_cp_radioapp_section_ext1 *)p_ext1_dst_cur;
433         if(p_ext1 == NULL) {
434             print_err("p_ext1 is null!\n");
435             return (XRAN_STATUS_INVALID_PARAM);
436         }
437
438         cur_ext_len += parm_size;
439
440         if(idxRb+1 == rbNum)
441             ext_flag = XRAN_EF_F_LAST;
442
443         p_ext1->extType       = XRAN_CP_SECTIONEXTCMD_1;
444         p_ext1->ef            = ext_flag;
445         p_ext1->bfwCompMeth   = bfwCompMeth;
446         p_ext1->bfwIqWidth    = XRAN_CONVERT_BFWIQWIDTH(bfwiqWidth);
447
448         switch(bfwCompMeth) {
449             case XRAN_BFWCOMPMETHOD_BLKFLOAT:
450                 p_bfw_content = (uint8_t *)(p_ext1+1);
451                 if(p_bfw_content == NULL) {
452                     print_err("Fail to allocate the space for section extension 1");
453                     return (XRAN_STATUS_RESOURCE);
454                 }
455                 bfp_com_req.data_in    = (int16_t*)p_bfw_iq_src;
456                 bfp_com_req.len        =  bfwNumPerRb*4;
457                 bfp_com_req.compMethod = p_ext1->bfwCompMeth;
458                 bfp_com_req.iqWidth    = p_ext1->bfwIqWidth;
459
460                 print_dbg("req 0x%08p iqWidth %d\n",bfp_com_req.data_in, bfp_com_req.iqWidth);
461
462                 parm_size = 1; /* exponent as part of bfwCompParam 1 octet */
463                 break;
464             case XRAN_BFWCOMPMETHOD_BLKSCALE:
465                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
466                 break;
467
468             case XRAN_BFWCOMPMETHOD_ULAW:
469                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
470                 break;
471
472             case XRAN_BFWCOMPMETHOD_BEAMSPACE:
473                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
474                 break;
475
476             case XRAN_BFWCOMPMETHOD_NONE:
477             default:
478                 p_bfw_content = (uint8_t *)(p_ext1+1);
479                 /* bfwCompParam is absent for no compression case */
480                 parm_size = 0;
481         }
482
483         if(p_bfw_content == NULL) {
484             print_err("Fail to allocate the space for section extension 1");
485             return (XRAN_STATUS_RESOURCE);
486             }
487
488         bfw_iq_bits = bfwNumPerRb* bfwiqWidth * 2;
489
490         parm_size += bfw_iq_bits>>3;
491         if(bfw_iq_bits%8)
492             parm_size++;
493
494         print_dbg("copy BF W %p -> %p size %d \n", p_bfw_iq_src, p_bfw_content, parm_size);
495         if (p_ext1->bfwIqWidth == 0 || p_ext1->bfwIqWidth == 16){
496             rte_memcpy(p_bfw_content, p_bfw_iq_src, parm_size);
497         } else {
498             bfp_com_rsp.data_out = (int8_t*)p_bfw_content;
499             if(xranlib_compress_avx512_bfw(&bfp_com_req, &bfp_com_rsp) == 0){
500                 comp_len = bfp_com_rsp.len;
501                 print_dbg("comp_len %d\n", comp_len);
502             } else {
503                 print_err("compression failed\n");
504                 return (XRAN_STATUS_FAIL);
505             }
506         }
507
508         p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
509
510         cur_ext_len += parm_size;
511         parm_size = cur_ext_len % XRAN_SECTIONEXT_ALIGN;
512         if(parm_size) {
513             parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
514             p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
515             rte_memcpy(p_bfw_content, zeropad, parm_size);
516             cur_ext_len += parm_size;
517             print_dbg("zeropad %d cur_ext_len %d\n", parm_size, cur_ext_len);
518         }
519
520         if(cur_ext_len % XRAN_SECTIONEXT_ALIGN)
521             rte_panic("ext1 should be aligned on 4-bytes boundary");
522
523         p_ext1->extLen = cur_ext_len / XRAN_SECTIONEXT_ALIGN;
524         print_dbg("p_ext1->extLen %d\n", p_ext1->extLen);
525
526         /* update for next RB */
527         p_ext1_dst_cur += cur_ext_len;
528         p_bfw_iq_src   = p_bfw_iq_src + bfwNumPerRb*2;
529
530         total_len += cur_ext_len;
531     }
532
533     print_dbg("total_len %d\n", total_len);
534     return (total_len);
535 }
536
537
538 // Cyclic Prefix Length 5.4.4.14
539 //   CP_length = cpLength * Ts,  Ts = 1/30.72MHz
540 //    i.e cpLength = CP_length / Ts ?
541 #define CPLEN_TS           (30720000)
542 inline uint16_t xran_get_cplength(int CP_length)
543 {
544     return (CP_length);
545 }
546
547 // Frequency offset 5.4.5.11
548 //   frequency_offset = freqOffset * SCS * 0.5
549 //    i.e freqOffset = (frequency_offset *2 )/ SCS ?
550 inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)
551 {
552     return (freqOffset);
553 }
554
555 static int xran_copy_sectionext_1(struct rte_mbuf *mbuf,
556                 struct xran_sectionext1_info *params, int last_flag)
557 {
558     int32_t total_len;
559     int8_t *p_dst = (int8_t *)rte_pktmbuf_append(mbuf, params->bfwIQ_sz);
560     if(p_dst == NULL) {
561         print_err("Fail to allocate the space for section extension 1 [%d]", params->bfwIQ_sz);
562         return (XRAN_STATUS_RESOURCE);
563     }
564     if(params->p_bfwIQ){
565         /* copy formated extType1 with all the headers */
566         rte_memcpy(p_dst, params->p_bfwIQ, params->bfwIQ_sz);
567         total_len = params->bfwIQ_sz;
568     }
569     else
570         total_len = 0;
571
572
573     return (total_len);
574 }
575
576
577 static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,
578                 struct xran_sectionext1_info *params, int last_flag)
579 {
580     struct xran_cp_radioapp_section_ext1 *ext1;
581     uint8_t *data;
582     int parm_size, iq_size;
583     int total_len;
584
585     total_len = 0;
586
587     print_dbg("%s %d\n", __FUNCTION__, last_flag);
588
589     parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
590     ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);
591     if(ext1 == NULL) {
592         print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
593         return (XRAN_STATUS_RESOURCE);
594     }
595
596     total_len += parm_size;
597
598     ext1->extType       = XRAN_CP_SECTIONEXTCMD_1;
599     ext1->ef            = last_flag;
600     ext1->bfwCompMeth   = params->bfwCompMeth;
601     ext1->bfwIqWidth    = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);
602
603     switch(params->bfwCompMeth) {
604         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
605             parm_size = 1;
606             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
607             if(data == NULL) {
608                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
609                 return (XRAN_STATUS_RESOURCE);
610             }
611             total_len += parm_size;
612             *data = (params->bfwCompParam.exponent & 0x0f);
613             break;
614
615         case XRAN_BFWCOMPMETHOD_BLKSCALE:
616             parm_size = 1;
617             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
618             if(data == NULL) {
619                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
620                 return (XRAN_STATUS_RESOURCE);
621             }
622             total_len += parm_size;
623             *data = params->bfwCompParam.blockScaler;
624             break;
625
626         case XRAN_BFWCOMPMETHOD_ULAW:
627             parm_size = 1;
628             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
629             if(data == NULL) {
630                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
631                 return (XRAN_STATUS_RESOURCE);
632                 }
633             total_len += parm_size;
634             *data = params->bfwCompParam.compBitWidthShift;
635             break;
636
637         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
638             parm_size = params->bfwNumber>>3;
639             if(params->bfwNumber%8) parm_size++;
640             parm_size *= 8;
641             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
642             if(data == NULL) {
643                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
644                 return (XRAN_STATUS_RESOURCE);
645                 }
646             rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
647             total_len += parm_size;
648             break;
649
650         case XRAN_BFWCOMPMETHOD_NONE:
651         default:
652             parm_size = 0;
653         }
654
655     print_dbg("params->bfwNumber %d params->bfwiqWidth %d\n", params->bfwNumber, params->bfwiqWidth);
656
657     iq_size = params->bfwNumber * params->bfwiqWidth * 2;
658
659     parm_size = iq_size>>3;
660     if(iq_size%8)
661         parm_size++;
662
663     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
664     if(data == NULL) {
665         print_err("Fail to allocate the space for section extension 1 BF W iq_size: [%d]", parm_size);
666         return (XRAN_STATUS_RESOURCE);
667     }
668     rte_memcpy(data, params->p_bfwIQ, parm_size);
669
670     total_len += parm_size;
671     parm_size = total_len % XRAN_SECTIONEXT_ALIGN;
672     if(parm_size) {
673         parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
674         data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
675         if(data == NULL) {
676             print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
677             return (XRAN_STATUS_RESOURCE);
678         }
679         rte_memcpy(data, zeropad, parm_size);
680         total_len += parm_size;
681     }
682
683     ext1->extLen        = total_len / XRAN_SECTIONEXT_ALIGN;
684
685     return (total_len);
686 }
687
688 static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,
689                 struct xran_sectionext2_info *params, int last_flag)
690 {
691   struct xran_cp_radioapp_section_ext2 *ext2;
692   uint8_t *data;
693   int total_len;
694   int parm_size;
695   uint32_t val, shift_val;
696   int val_size, pad_size;
697
698
699     total_len = 0;
700
701     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
702     ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
703     if(ext2 == NULL) {
704         print_err("Fail to allocate the space for section extension 2");
705         return (XRAN_STATUS_RESOURCE);
706         }
707     total_len += parm_size;
708
709     ext2->extType           = XRAN_CP_SECTIONEXTCMD_2;
710     ext2->ef                = last_flag;
711     ext2->bfZe3ddWidth      = params->bfZe3ddWidth;
712     ext2->bfAz3ddWidth      = params->bfAz3ddWidth;
713     ext2->bfZePtWidth       = params->bfZePtWidth;
714     ext2->bfAzPtWidth       = params->bfAzPtWidth;
715     ext2->bfaCompResv0      = 0;
716     ext2->bfaCompResv1      = 0;
717
718     val = 0;
719     shift_val = 0;
720     if(params->bfAzPtWidth) {
721         val += params->bfAzPt & bitmask[params->bfAzPtWidth];
722         shift_val += 8 - (params->bfAzPtWidth+1);
723         }
724     else
725         shift_val += 8;
726
727     if(params->bfZePtWidth) {
728         val = val << (params->bfZePtWidth+1);
729         val += params->bfZePt & bitmask[params->bfZePtWidth];
730         shift_val += 8 - (params->bfZePtWidth+1);
731         }
732     else
733         shift_val += 8;
734
735     if(params->bfAz3ddWidth) {
736         val = val << (params->bfAz3ddWidth+1);
737         val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];
738         shift_val += 8 - (params->bfAz3ddWidth+1);
739         }
740     else
741         shift_val += 8;
742
743     if(params->bfZe3ddWidth) {
744         val = val << (params->bfZe3ddWidth+1);
745         val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];
746         shift_val += 8 - (params->bfZe3ddWidth+1);
747         }
748     else
749         shift_val += 8;
750
751     if(val) {
752         val = val << shift_val;
753         val = rte_cpu_to_be_32(val);
754         }
755
756     val_size = 4 - (shift_val/8);   /* ceil(total bit/8) */
757     parm_size = val_size + 1;       /* additional 1 byte for bfxxSI */
758
759     // alignment
760     total_len += parm_size;
761     pad_size = total_len % XRAN_SECTIONEXT_ALIGN;
762     if(pad_size) {
763         pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;
764         parm_size += pad_size;
765         total_len += pad_size;
766         }
767
768     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
769     if(data == NULL) {
770         print_err("Fail to allocate the space for section extension 2");
771         return (XRAN_STATUS_RESOURCE);
772         }
773
774     rte_memcpy(data, &val, val_size);
775     data += val_size;
776     *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
777     data++;
778     rte_memcpy(data, zeropad, pad_size);
779
780     ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
781     *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
782
783     return (total_len);
784 }
785
786 static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
787                 struct xran_sectionext4_info *params, int last_flag)
788 {
789   struct xran_cp_radioapp_section_ext4 *ext4;
790   int parm_size;
791   int total_len;
792   int ret;
793
794
795     total_len = 0;
796
797     parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
798     ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
799     if(ext4 == NULL) {
800         print_err("Fail to allocate the space for section extension 4");
801         return(XRAN_STATUS_RESOURCE);
802         }
803     else {
804         total_len += parm_size;
805
806         ext4->extType       = XRAN_CP_SECTIONEXTCMD_4;
807         ext4->ef            = last_flag;
808         ext4->modCompScaler = params->modCompScaler;
809         ext4->csf           = params->csf?1:0;
810         ext4->extLen        = total_len / XRAN_SECTIONEXT_ALIGN;
811
812         *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
813         }
814
815     return (total_len);
816 }
817
818 static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
819                 struct xran_sectionext5_info *params, int last_flag)
820 {
821   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
822   struct xran_cp_radioapp_section_ext5 ext5;
823   int padding;
824   int total_len;
825   uint8_t *data;
826   int i;
827
828
829     if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {
830         print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);
831         return (0);
832         }
833
834     total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)
835                 + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2
836                 - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust
837
838     /* for alignment */
839     padding = total_len % XRAN_SECTIONEXT_ALIGN;
840     if(padding) {
841         padding = XRAN_SECTIONEXT_ALIGN - padding;
842         total_len += padding;
843         }
844
845     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);
846     if(ext_hdr == NULL) {
847         print_err("Fail to allocate the space for section extension 5");
848         return (XRAN_STATUS_RESOURCE);
849         }
850
851     ext_hdr->extType    = XRAN_CP_SECTIONEXTCMD_5;
852     ext_hdr->ef         = last_flag;
853     ext_hdr->extLen     = total_len / XRAN_SECTIONEXT_ALIGN;
854
855     *(uint16_t *)ext_hdr    = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));
856
857     data = (uint8_t *)(ext_hdr + 1);
858     i = 0;
859     while(i < params->num_sets) {
860         if(i%2) { // odd index
861             ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;
862             ext5.csf2           = params->mc[i].csf;
863             ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;
864             ext5.reserved0      = 0;
865             i++;
866
867             // adding two sets at once (due to the definition of structure)
868             *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
869             rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));
870             data += sizeof(struct xran_cp_radioapp_section_ext5);
871             }
872         else { // even index
873             ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;
874             ext5.csf1           = params->mc[i].csf;
875             ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;
876             ext5.mcScaleReMask2 = 0;
877             i++;
878
879             if(i == params->num_sets) { // adding last even index
880                 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
881                 rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);
882                 data += sizeof(struct xran_cp_radioapp_section_ext5)/2;
883                 break;
884                 }
885             }
886         }
887
888     /* zero padding */
889     if(padding)
890         rte_memcpy(data, zeropad, padding);
891
892     return (total_len);
893 }
894
895 /**
896  * @brief add section extension to C-Plane packet
897  *
898  * @param mbuf
899  *  A pointer to the packet buffer
900  * @param params
901  *  A porinter to the information to generate a C-Plane packet
902  * @return
903  *  XRAN_STATUS_SUCCESS on success
904  *  XRAN_STATUS_INVALID_PARM
905  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
906  */
907 int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
908 {
909     int i, ret;
910     uint32_t totalen;
911     int last_flag;
912     int ext_size;
913
914     if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {
915         print_err("Invalid total number of extensions - %d", params->exDataSize);
916         return (XRAN_STATUS_INVALID_PARAM);
917     }
918
919     totalen = 0;
920
921     ret = XRAN_STATUS_SUCCESS;
922
923     print_dbg("params->exDataSize %d\n", params->exDataSize);
924     for(i=0; i < params->exDataSize; i++) {
925         if(params->exData[i].data == NULL) {
926             print_err("Invalid parameter - extension data %d is NULL", i);
927             ret = XRAN_STATUS_INVALID_PARAM;
928             continue;
929         }
930
931         last_flag = (params->exDataSize == (i+1))?0:1;
932
933         switch(params->exData[i].type) {
934             case XRAN_CP_SECTIONEXTCMD_1:
935                 ext_size = xran_copy_sectionext_1(mbuf, params->exData[i].data, last_flag);
936                     //xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);
937                 break;
938             case XRAN_CP_SECTIONEXTCMD_2:
939                 ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
940                 break;
941             case XRAN_CP_SECTIONEXTCMD_4:
942                 ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
943                 break;
944             case XRAN_CP_SECTIONEXTCMD_5:
945                 ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
946                 break;
947             case XRAN_CP_SECTIONEXTCMD_0:
948             case XRAN_CP_SECTIONEXTCMD_3:
949             default:
950                 print_err("Extension Type %d is not supported!", params->exData[i].type);
951                 ret = XRAN_STATUS_INVALID_PARAM;
952                 ext_size = 0;
953             }
954
955         if(ext_size == XRAN_STATUS_RESOURCE) {
956             break;
957         }
958
959         totalen += ext_size;
960     }
961
962     return (totalen);
963 }
964
965
966 /**
967  * @brief Fill the section body of type 0 in C-Plane packet
968  *
969  * @param section
970  *  A pointer to the section in the packet buffer
971  * @param params
972  *  A porinter to the information to generate a C-Plane packet
973  * @return
974  *  XRAN_STATUS_SUCCESS on success
975  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
976  */
977 static int xran_prepare_section0(
978                 struct xran_cp_radioapp_section0 *section,
979                 struct xran_section_gen_info *params)
980 {
981 #if (XRAN_STRICT_PARM_CHECK)
982     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
983         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
984         return (XRAN_STATUS_INVALID_PARAM);
985         }
986 #endif
987
988     section->hdr.sectionId      = params->info.id;
989     section->hdr.rb             = params->info.rb;
990     section->hdr.symInc         = params->info.symInc;
991     section->hdr.startPrbc      = params->info.startPrbc;
992     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
993
994     section->hdr.u.s0.reMask    = params->info.reMask;
995     section->hdr.u.s0.numSymbol = params->info.numSymbol;
996     section->hdr.u.s0.reserved  = 0;
997
998     // for network byte order
999     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1000
1001     return (XRAN_STATUS_SUCCESS);
1002 }
1003 /**
1004  * @brief Fill the section header of type 0 in C-Plane packet
1005  *
1006  * @param s0hdr
1007  *  A pointer to the section header in the packet buffer
1008  * @param params
1009  *  A porinter to the information to generate a C-Plane packet
1010  * @return
1011  *  XRAN_STATUS_SUCCESS always
1012  */
1013 static int xran_prepare_section0_hdr(
1014                 struct xran_cp_radioapp_section0_header *s0hdr,
1015                 struct xran_cp_gen_params *params)
1016
1017 {
1018     s0hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1019     s0hdr->frameStructure.fftSize   = params->hdr.fftSize;
1020     s0hdr->frameStructure.uScs      = params->hdr.scs;
1021     s0hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1022     s0hdr->reserved                 = 0;
1023
1024     return (XRAN_STATUS_SUCCESS);
1025 }
1026
1027 /**
1028  * @brief Fill the section body of type 1 in C-Plane packet
1029  *  Extension is not supported.
1030  *
1031  * @param section
1032  *  A pointer to the section header in the packet buffer
1033  * @param params
1034  *  A porinter to the information to generate a C-Plane packet
1035  * @return
1036  *  XRAN_STATUS_SUCCESS on success
1037  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1038  */
1039 static int xran_prepare_section1(
1040                 struct xran_cp_radioapp_section1 *section,
1041                 struct xran_section_gen_info *params)
1042 {
1043 #if (XRAN_STRICT_PARM_CHECK)
1044     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1045         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1046         return (XRAN_STATUS_INVALID_PARAM);
1047         }
1048 #endif
1049
1050     section->hdr.sectionId      = params->info.id;
1051     section->hdr.rb             = params->info.rb;
1052     section->hdr.symInc         = params->info.symInc;
1053     section->hdr.startPrbc      = params->info.startPrbc;
1054     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1055
1056     section->hdr.u.s1.reMask    = params->info.reMask;
1057     section->hdr.u.s1.numSymbol = params->info.numSymbol;
1058     section->hdr.u.s1.beamId    = params->info.beamId;
1059
1060     section->hdr.u.s1.ef        = params->info.ef;
1061
1062     // for network byte order
1063     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1064
1065     return (XRAN_STATUS_SUCCESS);
1066 }
1067 /**
1068  * @brief Fill the section header of type 1 in C-Plane packet
1069  *
1070  * @param s1hdr
1071  *  A pointer to the section header in the packet buffer
1072  * @param params
1073  *  A porinter to the information to generate a C-Plane packet
1074  * @return
1075  *  XRAN_STATUS_SUCCESS always
1076  */
1077 static int xran_prepare_section1_hdr(
1078                 struct xran_cp_radioapp_section1_header *s1hdr,
1079                 struct xran_cp_gen_params *params)
1080 {
1081     s1hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1082     s1hdr->udComp.udCompMeth        = params->hdr.compMeth;
1083     s1hdr->reserved                 = 0;
1084
1085     return (XRAN_STATUS_SUCCESS);
1086 }
1087
1088 /**
1089  * @brief Fill the section body of type 3 in C-Plane packet
1090  *  Extension is not supported.
1091  *
1092  * @param section
1093  *  A pointer to the section header in the packet buffer
1094  * @param params
1095  *  A porinter to the information to generate a C-Plane packet
1096  * @return
1097  *  XRAN_STATUS_SUCCESS on success
1098  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1099  */
1100 static int xran_prepare_section3(
1101                 struct xran_cp_radioapp_section3 *section,
1102                 struct xran_section_gen_info *params)
1103 {
1104 #if (XRAN_STRICT_PARM_CHECK)
1105     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1106         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1107         return (XRAN_STATUS_INVALID_PARAM);
1108         }
1109 #endif
1110
1111     section->hdr.sectionId      = params->info.id;
1112     section->hdr.rb             = params->info.rb;
1113     section->hdr.symInc         = params->info.symInc;
1114     section->hdr.startPrbc      = params->info.startPrbc;
1115     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1116
1117     section->hdr.u.s3.reMask    = params->info.reMask;
1118     section->hdr.u.s3.numSymbol = params->info.numSymbol;
1119     section->hdr.u.s3.beamId    = params->info.beamId;
1120
1121     section->freqOffset         = rte_cpu_to_be_32(params->info.freqOffset)>>8;
1122     section->reserved           = 0;
1123
1124     section->hdr.u.s3.ef        = params->info.ef;
1125
1126     // for network byte order (header, 8 bytes)
1127     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1128
1129     return (XRAN_STATUS_SUCCESS);
1130 }
1131 /**
1132  * @brief Fill the section header of type 3 in C-Plane packet
1133  *
1134  * @param s3hdr
1135  *  A pointer to the section header in the packet buffer
1136  * @param params
1137  *  A porinter to the information to generate a C-Plane packet
1138  * @return
1139  *  XRAN_STATUS_SUCCESS always
1140  */
1141 static int xran_prepare_section3_hdr(
1142                 struct xran_cp_radioapp_section3_header *s3hdr,
1143                 struct xran_cp_gen_params *params)
1144
1145 {
1146     s3hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1147     s3hdr->frameStructure.fftSize   = params->hdr.fftSize;
1148     s3hdr->frameStructure.uScs      = params->hdr.scs;
1149     s3hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1150     s3hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1151     s3hdr->udComp.udCompMeth        = params->hdr.compMeth;
1152
1153     return (XRAN_STATUS_SUCCESS);
1154 }
1155
1156 /**
1157  * @brief add sections to C-Plane packet
1158  *  Section type 1 and 3 are supported.
1159  *
1160  * @param mbuf
1161  *  A pointer to the packet buffer
1162  * @param params
1163  *  A porinter to the information to generate a C-Plane packet
1164  * @return
1165  *  XRAN_STATUS_SUCCESS on success
1166  *  XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
1167  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1168  */
1169 int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1170 {
1171   int i, ret, ext_flag;
1172   uint32_t totalen;
1173   void *section;
1174   int section_size;
1175   int (*xran_prepare_section_func)(void *section, void *params);
1176
1177
1178     totalen = 0;
1179     switch(params->sectionType) {
1180         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1181             section_size                = sizeof(struct xran_cp_radioapp_section0);
1182             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section0;
1183             break;
1184
1185         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1186             section_size                = sizeof(struct xran_cp_radioapp_section1);
1187             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section1;
1188             break;
1189
1190         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1191             section_size                = sizeof(struct xran_cp_radioapp_section3);
1192             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section3;
1193             break;
1194
1195         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1196         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1197         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1198         default:
1199             section_size                = 0;
1200             xran_prepare_section_func   = NULL;
1201             print_err("Section Type %d is not supported!", params->sectionType);
1202             return (XRAN_STATUS_INVALID_PARAM);
1203         }
1204
1205     if(unlikely(xran_prepare_section_func == NULL)) {
1206        print_err("Section Type %d is not supported!", params->sectionType);
1207        return (XRAN_STATUS_INVALID_PARAM);
1208     }
1209
1210     for(i=0; i < params->numSections; i++) {
1211         section = rte_pktmbuf_append(mbuf, section_size);
1212         if(section == NULL) {
1213             print_err("Fail to allocate the space for section[%d]!", i);
1214             return (XRAN_STATUS_RESOURCE);
1215         }
1216         print_dbg("%s %d ef %d\n", __FUNCTION__, i, params->sections[i].info.ef);
1217         ret = xran_prepare_section_func((void *)section,
1218                             (void *)&params->sections[i]);
1219         if(ret < 0){
1220             print_err("%s %d\n", __FUNCTION__, ret);
1221             return (ret);
1222         }
1223         totalen += section_size;
1224
1225         if(params->sections[i].info.ef) {
1226             print_dbg("sections[%d].info.ef %d exDataSize %d  type %d\n", i, params->sections[i].info.ef,
1227                 params->sections[i].exDataSize, params->sections[i].exData[0].type);
1228             ret = xran_append_section_extensions(mbuf, &params->sections[i]);
1229             if(ret < 0)
1230                 return (ret);
1231             totalen += ret;
1232        }
1233     }
1234
1235     return (totalen);
1236 }
1237
1238 /**
1239  * @brief fill the information of a radio application header in a C-Plane packet
1240  *
1241  * @param apphdr
1242  *  A pointer to the application header in the packet buffer
1243  * @param params
1244  *  A porinter to the information to generate a C-Plane packet
1245  * @return
1246  *  XRAN_STATUS_SUCCESS on success
1247  *  XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
1248  */
1249 static inline int xran_prepare_radioapp_common_header(
1250                 struct xran_cp_radioapp_common_header *apphdr,
1251                 struct xran_cp_gen_params *params)
1252 {
1253
1254 #if (XRAN_STRICT_PARM_CHECK)
1255     if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
1256         print_err("Invalid direction!");
1257         return (XRAN_STATUS_INVALID_PARAM);
1258         }
1259     if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
1260         print_err("Invalid Slot ID!");
1261         return (XRAN_STATUS_INVALID_PARAM);
1262         }
1263     if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
1264         print_err("Invalid Symbol ID!");
1265         return (XRAN_STATUS_INVALID_PARAM);
1266         }
1267 #endif
1268
1269     apphdr->dataDirection   = params->dir;
1270     apphdr->payloadVer      = XRAN_PAYLOAD_VER;
1271     apphdr->filterIndex     = params->hdr.filterIdx;
1272     apphdr->frameId         = params->hdr.frameId;
1273     apphdr->subframeId      = params->hdr.subframeId;
1274     apphdr->slotId          = params->hdr.slotId;
1275     apphdr->startSymbolId   = params->hdr.startSymId;
1276     apphdr->numOfSections   = params->numSections;
1277     apphdr->sectionType     = params->sectionType;
1278
1279     /* radio app header has common parts of 4bytes for all section types */
1280     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1281
1282     return (XRAN_STATUS_SUCCESS);
1283 }
1284
1285 /**
1286  * @brief add a radio application header in a C-Plane packet
1287  *
1288  * @param mbuf
1289  *  A pointer to the packet buffer
1290  * @param params
1291  *  A porinter to the information to generate a C-Plane packet
1292  * @return
1293  *  The length of added section (>0) on success
1294  *  XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
1295  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1296  */
1297 int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1298 {
1299   int ret;
1300   uint32_t totalen;
1301   struct xran_cp_radioapp_common_header *apphdr;
1302   int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
1303
1304
1305 #if (XRAN_STRICT_PARM_CHECK)
1306     if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
1307         print_err("Invalid Section Type - %d", params->sectionType);
1308         return (XRAN_STATUS_INVALID_PARAM);
1309         }
1310 #endif
1311
1312     switch(params->sectionType) {
1313         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1314             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;
1315             totalen = sizeof(struct xran_cp_radioapp_section0_header);
1316             break;
1317
1318         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1319             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;
1320             totalen = sizeof(struct xran_cp_radioapp_section1_header);
1321             break;
1322
1323         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1324             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;
1325             totalen = sizeof(struct xran_cp_radioapp_section3_header);
1326             break;
1327
1328         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1329         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1330         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1331         default:
1332             print_err("Section Type %d is not supported!", params->sectionType);
1333             xran_prepare_radioapp_section_hdr_func = NULL;
1334             totalen = 0;
1335             return (XRAN_STATUS_INVALID_PARAM);
1336         }
1337
1338     apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
1339     if(unlikely(apphdr == NULL)) {
1340         print_err("Fail to reserve the space for radio application header!");
1341         return (XRAN_STATUS_RESOURCE);
1342         }
1343
1344     ret = xran_prepare_radioapp_common_header(apphdr, params);
1345     if(unlikely(ret < 0)) {
1346         return (ret);
1347         }
1348
1349     if(likely(xran_prepare_radioapp_section_hdr_func)) {
1350         totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
1351         }
1352     else {
1353         print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
1354         return (XRAN_STATUS_INVALID_PARAM);
1355         }
1356
1357     return (totalen);
1358 }
1359
1360 /**
1361  * @brief Create a C-Plane packet
1362  *  Transport layer fragmentation is not supported.
1363  *
1364  * @ingroup xran_cp_pkt
1365  *
1366  * @param mbuf
1367  *  A pointer to the packet buffer
1368  * @param params
1369  *  A porinter to the information to generate a C-Plane packet
1370  * @param CC_ID
1371  *  Component Carrier ID for this C-Plane message
1372  * @param Ant_ID
1373  *  Antenna ID(RU Port ID) for this C-Plane message
1374  * @param seq_id
1375  *  Sequence ID for this C-Plane message
1376  * @return
1377  *  XRAN_STATUS_SUCCESS on success
1378  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1379  *  XRAN_STATUS_INVALID_PARM if section type is invalid
1380  */
1381 int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
1382                         struct xran_cp_gen_params *params,
1383                         uint8_t CC_ID, uint8_t Ant_ID,
1384                         uint8_t seq_id)
1385 {
1386   int ret;
1387   uint32_t payloadlen;
1388   struct xran_ecpri_hdr *ecpri_hdr;
1389
1390
1391     payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
1392
1393     ret = xran_append_radioapp_header(mbuf, params);
1394     if(ret < 0) {
1395         print_err("%s %d\n", __FUNCTION__, ret);
1396         return (ret);
1397     }
1398     payloadlen += ret;
1399
1400     ret = xran_append_control_section(mbuf, params);
1401     if(ret < 0) {
1402         print_err("%s %d\n", __FUNCTION__, ret);
1403         return (ret);
1404     }
1405     payloadlen += ret;
1406
1407     /* set payload length */
1408     ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
1409
1410     return (XRAN_STATUS_SUCCESS);
1411 }
1412
1413
1414 ///////////////////////////////////////
1415 // for RU emulation
1416 int xran_parse_section_ext1(void *ext,
1417                 struct xran_sectionext1_info *extinfo)
1418 {
1419   int len;
1420   int total_len;
1421   struct xran_cp_radioapp_section_ext1 *ext1;
1422   uint8_t *data;
1423   int parm_size, iq_size;
1424   int N;
1425   void *pHandle;
1426
1427     pHandle = NULL;
1428     N = xran_get_conf_num_bfweights(pHandle);
1429     extinfo->bfwNumber = N;
1430
1431     ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
1432     data = (uint8_t *)ext;
1433
1434     len = 0;
1435     total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1436
1437     extinfo->bfwCompMeth    = ext1->bfwCompMeth;
1438     extinfo->bfwiqWidth     = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
1439
1440     len     += sizeof(struct xran_cp_radioapp_section_ext1);
1441     data    += sizeof(struct xran_cp_radioapp_section_ext1);
1442
1443     switch(ext1->bfwCompMeth) {
1444         case XRAN_BFWCOMPMETHOD_NONE:
1445             parm_size = 0;
1446             break;
1447
1448         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1449             parm_size = 1;
1450             extinfo->bfwCompParam.exponent = *data & 0x0f;
1451             break;
1452
1453         case XRAN_BFWCOMPMETHOD_BLKSCALE:
1454             parm_size = 1;
1455             extinfo->bfwCompParam.blockScaler = *data;
1456             break;
1457
1458         case XRAN_BFWCOMPMETHOD_ULAW:
1459             parm_size = 1;
1460             extinfo->bfwCompParam.compBitWidthShift = *data;
1461             break;
1462
1463         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
1464             parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
1465             rte_memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
1466             break;
1467
1468         default:
1469             print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
1470             parm_size = 0;
1471         }
1472
1473     len     += parm_size;
1474     data    += parm_size;
1475
1476     /* Get BF weights */
1477     iq_size = N * extinfo->bfwiqWidth * 2;  // total in bits
1478     parm_size = iq_size>>3;                 // total in bytes (/8)
1479     if(iq_size%8) parm_size++;              // round up
1480
1481     //rte_memcpy(data, extinfo->p_bfwIQ, parm_size);
1482     extinfo->p_bfwIQ =  (int16_t*)data;
1483
1484     len += parm_size;
1485
1486     parm_size = len % XRAN_SECTIONEXT_ALIGN;
1487     if(parm_size)
1488         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1489
1490     if(len != total_len) {
1491         // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
1492     }
1493
1494     return (total_len);
1495 }
1496
1497 int xran_parse_section_ext2(void *ext,
1498                 struct xran_sectionext2_info *extinfo)
1499 {
1500   int len;
1501   int total_len;
1502   struct xran_cp_radioapp_section_ext2 *ext2;
1503   uint8_t *data;
1504   int parm_size;
1505   uint32_t val;
1506   int val_size;
1507
1508
1509     ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
1510     data = (uint8_t *)ext;
1511     *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
1512
1513     len = 0;
1514     total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1515
1516     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
1517
1518     extinfo->bfAzPtWidth    = ext2->bfAzPtWidth;
1519     extinfo->bfZePtWidth    = ext2->bfZePtWidth;
1520     extinfo->bfAz3ddWidth   = ext2->bfAz3ddWidth;
1521     extinfo->bfZe3ddWidth   = ext2->bfZe3ddWidth;
1522
1523     if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
1524         print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
1525
1526     data    += parm_size;
1527     len     += parm_size;
1528
1529     val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
1530                 + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
1531                 + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
1532                 + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
1533     if(val_size) {
1534         val = rte_cpu_to_be_32(*(uint32_t *)data);
1535         val >>= (32 - val_size);
1536
1537         if(extinfo->bfZe3ddWidth) {
1538             extinfo->bfZe3dd    = val & bitmask[extinfo->bfZe3ddWidth];
1539             val >>= (extinfo->bfZe3ddWidth + 1);
1540             }
1541         if(extinfo->bfAz3ddWidth) {
1542             extinfo->bfAz3dd    = val & bitmask[extinfo->bfAz3ddWidth];
1543             val >>= (extinfo->bfAz3ddWidth + 1);
1544             }
1545         if(extinfo->bfZePtWidth) {
1546             extinfo->bfZePt     = val & bitmask[extinfo->bfZePtWidth];
1547             val >>= (extinfo->bfZePtWidth + 1);
1548             }
1549         if(extinfo->bfAzPtWidth) {
1550             extinfo->bfAzPt     = val & bitmask[extinfo->bfAzPtWidth];
1551             val >>= (extinfo->bfAzPtWidth + 1);
1552             }
1553         }
1554
1555     parm_size = val_size/8;
1556     if(val_size%8) parm_size += 1;
1557
1558     data    += parm_size;
1559     len     += parm_size;
1560
1561     extinfo->bfAzSI = (*data >> 3) & 0x07;
1562     extinfo->bfZeSI = *data & 0x07;
1563
1564     data++;
1565     len++;
1566
1567     parm_size = len % XRAN_SECTIONEXT_ALIGN;
1568     if(parm_size)
1569         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1570
1571     if(len != total_len) {
1572         print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
1573         }
1574
1575     return (total_len);
1576
1577 }
1578
1579 int xran_parse_section_ext4(void *ext,
1580                 struct xran_sectionext4_info *extinfo)
1581 {
1582   int len;
1583   struct xran_cp_radioapp_section_ext4 *ext4;
1584   int total_len;
1585
1586
1587     ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
1588
1589     *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t *)ext4);
1590
1591     len = 0;
1592     total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1593
1594     extinfo->modCompScaler  = ext4->modCompScaler;
1595     extinfo->csf            = ext4->csf;
1596 //    extinfo->pad0;
1597
1598     len += sizeof(struct xran_cp_radioapp_section_ext4);
1599     if(len != total_len) {
1600         print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
1601         }
1602
1603     return (total_len);
1604 }
1605
1606 int xran_parse_section_ext5(void *ext,
1607                 struct xran_sectionext5_info *extinfo)
1608 {
1609   int len;
1610   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
1611   struct xran_cp_radioapp_section_ext5 ext5;
1612   int parm_size;
1613   int total_len;
1614   uint8_t *data;
1615   uint16_t i;
1616
1617
1618     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
1619     *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*(uint16_t *)ext_hdr);
1620
1621     total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1622
1623     // one set has 3.5 bytes, so enforcing double to do integer calculation
1624     parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
1625
1626     if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
1627         print_err("Exceeds maximum number of parameters - %d", parm_size);
1628         parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
1629     }
1630
1631     len = 0;
1632     data = (uint8_t *)(ext_hdr + 1);
1633
1634     i = 0;
1635     while(i < parm_size) {
1636         // For odd number set, more data can be copied
1637         *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)data));
1638
1639         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset1;
1640         extinfo->mc[i].csf              = ext5.csf1;
1641         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask1;
1642         i++;
1643
1644         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset2;
1645         extinfo->mc[i].csf              = ext5.csf2;
1646         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask2;
1647         i++;
1648
1649         data += sizeof(struct xran_cp_radioapp_section_ext5);
1650         }
1651
1652     // check the values of last set
1653     // due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
1654     // don't check mcScaleOffset might not be zero (some part is out of zero-padding)
1655     i--;
1656     if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
1657         if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
1658             extinfo->num_sets = i;
1659         else
1660             extinfo->num_sets = i+1;
1661     }else {
1662         print_err("Maximum total number %d is not correct!", i);
1663     }
1664
1665     return (total_len);
1666 }
1667
1668 int xran_parse_section_extension(struct rte_mbuf *mbuf,
1669                     void *ext,
1670                     struct xran_section_gen_info *section)
1671 {
1672   int total_len, len, numext;
1673   uint8_t *ptr;
1674   int flag_last;
1675   int ext_type;
1676   int i;
1677
1678     total_len = 0;
1679     ptr = (uint8_t *)ext;
1680
1681     numext = 0;
1682
1683     flag_last = 1;
1684     i = 0;
1685     while(flag_last) {
1686         /* check ef */
1687         flag_last = (*ptr & 0x80);
1688
1689         ext_type = *ptr & 0x7f;
1690         section->exData[numext].type = ext_type;
1691         switch(ext_type) {
1692             case XRAN_CP_SECTIONEXTCMD_1:
1693                 section->exData[numext].data = &section->m_ext1[numext];
1694                 len = xran_parse_section_ext1(ptr, section->exData[numext].data);
1695                 section->exData[numext].len = len;
1696                 break;
1697             case XRAN_CP_SECTIONEXTCMD_2:
1698                 section->exData[numext].data = &section->m_ext2[numext];
1699                 len = xran_parse_section_ext2(ptr, section->exData[numext].data);
1700                 break;
1701             case XRAN_CP_SECTIONEXTCMD_4:
1702                 section->exData[numext].data = &section->m_ext4[numext];
1703                 len = xran_parse_section_ext4(ptr, section->exData[numext].data);
1704                 break;
1705             case XRAN_CP_SECTIONEXTCMD_5:
1706                 section->exData[numext].data = &section->m_ext5[numext];
1707                 len = xran_parse_section_ext5(ptr, section->exData[numext].data);
1708                 break;
1709
1710             case XRAN_CP_SECTIONEXTCMD_0:
1711             case XRAN_CP_SECTIONEXTCMD_3:
1712             default:
1713                 print_err("Extension %d is not supported!", ext_type);
1714                 len = 0;
1715             }
1716
1717         section->exData[numext].len = len;
1718         ptr += len; total_len += len;
1719
1720         i++;
1721         if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
1722
1723         /* exceeds maximum number of extensions */
1724         break;
1725         }
1726
1727     section->exDataSize = numext;
1728
1729     return (total_len);
1730
1731 }
1732
1733 /**
1734  * @brief Parse a C-Plane packet (for RU emulation)
1735  *  Transport layer fragmentation is not supported.
1736  *
1737  * @ingroup xran_cp_pkt
1738  *
1739  * @param mbuf
1740  *  The pointer of the packet buffer to be parsed
1741  * @param params
1742  *  The pointer of structure to store the information of parsed packet
1743  * @param eaxc
1744  *  The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
1745  * @return
1746  *  XRAN_STATUS_SUCCESS on success
1747  *  XRAN_STATUS_INVALID_PACKET if failed to parse the packet
1748  */
1749 int xran_parse_cp_pkt(struct rte_mbuf *mbuf,
1750                     struct xran_cp_gen_params *result,
1751                     struct xran_recv_packet_info *pkt_info)
1752 {
1753   struct xran_ecpri_hdr *ecpri_hdr;
1754   struct xran_cp_radioapp_common_header *apphdr;
1755   int i, ret;
1756   int extlen;
1757
1758
1759     ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
1760     if(ret < 0 && ecpri_hdr == NULL)
1761         return (XRAN_STATUS_INVALID_PACKET);
1762
1763     /* Process radio header. */
1764     apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
1765     if(apphdr == NULL) {
1766         print_err("Invalid packet - radio app hedaer!");
1767         return (XRAN_STATUS_INVALID_PACKET);
1768         }
1769
1770     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1771
1772     if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {
1773         print_err("Invalid Payload version - %d", apphdr->payloadVer);
1774         ret = XRAN_STATUS_INVALID_PACKET;
1775         }
1776
1777     result->dir             = apphdr->dataDirection;
1778     result->hdr.filterIdx   = apphdr->filterIndex;
1779     result->hdr.frameId     = apphdr->frameId;
1780     result->hdr.subframeId  = apphdr->subframeId;
1781     result->hdr.slotId      = apphdr->slotId;
1782     result->hdr.startSymId  = apphdr->startSymbolId;
1783     result->sectionType     = apphdr->sectionType;
1784     result->numSections     = apphdr->numOfSections;
1785
1786 #if 0
1787     printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
1788         pkt_info->payload_len,
1789         pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
1790         pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
1791         result->dir?"DL":"UL",
1792         pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
1793         result->sectionType, result->numSections,
1794         result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1795         result->hdr.startSymId
1796         );
1797 #endif
1798
1799     switch(apphdr->sectionType) {
1800         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
1801             {
1802             struct xran_cp_radioapp_section0_header *hdr;
1803             struct xran_cp_radioapp_section0 *section;
1804
1805                 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
1806
1807                 result->hdr.fftSize     = rte_be_to_cpu_16(hdr->timeOffset);
1808                 result->hdr.scs         = hdr->frameStructure.fftSize;
1809                 result->hdr.timeOffset  = hdr->frameStructure.uScs;
1810                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1811                 //hdr->reserved;    /* should be zero */
1812
1813                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
1814                 if(section == NULL) {
1815                     print_err("Invalid packet 0 - radio app hedaer!");
1816                     return (XRAN_STATUS_INVALID_PACKET);
1817                     }
1818                 for(i=0; i<result->numSections; i++) {
1819                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1820
1821                     result->sections[i].info.type       = apphdr->sectionType;
1822                     result->sections[i].info.id         = section->hdr.sectionId;
1823                     result->sections[i].info.rb         = section->hdr.rb;
1824                     result->sections[i].info.symInc     = section->hdr.symInc;
1825                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1826                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1827                     result->sections[i].info.numSymbol  = section->hdr.u.s0.numSymbol;
1828                     result->sections[i].info.reMask     = section->hdr.u.s0.reMask;
1829                     //section->hdr.u.s0.reserved;   /* should be zero */
1830
1831                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
1832                     if(section == NULL) {
1833                         print_err("Invalid packet 0 - number of section [%d:%d]!",
1834                                     result->numSections, i);
1835                         result->numSections = i;
1836                         ret = XRAN_STATUS_INVALID_PACKET;
1837                         break;
1838                         }
1839                     }
1840             }
1841             break;
1842
1843         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
1844             {
1845             struct xran_cp_radioapp_section1_header *hdr;
1846             struct xran_cp_radioapp_section1 *section;
1847
1848                 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
1849
1850                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1851                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
1852
1853                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
1854                 if(section == NULL) {
1855                     print_err("Invalid packet 1 - radio app hedaer!");
1856                     return (XRAN_STATUS_INVALID_PACKET);
1857                     }
1858
1859                 for(i=0; i<result->numSections; i++) {
1860                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1861
1862                     result->sections[i].info.type       = apphdr->sectionType;
1863                     result->sections[i].info.id         = section->hdr.sectionId;
1864                     result->sections[i].info.rb         = section->hdr.rb;
1865                     result->sections[i].info.symInc     = section->hdr.symInc;
1866                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1867                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1868                     result->sections[i].info.numSymbol  = section->hdr.u.s1.numSymbol;
1869                     result->sections[i].info.reMask     = section->hdr.u.s1.reMask;
1870                     result->sections[i].info.beamId     = section->hdr.u.s1.beamId;
1871                     result->sections[i].info.ef         = section->hdr.u.s1.ef;
1872
1873                     section = (void *)rte_pktmbuf_adj(mbuf,
1874                                     sizeof(struct xran_cp_radioapp_section1));
1875                     if(section == NULL) {
1876                         print_err("Invalid packet 1 - number of section [%d:%d]!",
1877                                     result->numSections, i);
1878                         result->numSections = i;
1879                         ret = XRAN_STATUS_INVALID_PACKET;
1880                         break;
1881                         }
1882
1883                     if(result->sections[i].info.ef) {
1884                         // parse section extension
1885                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
1886                         if(extlen > 0) {
1887                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
1888                             if(section == NULL) {
1889                                 print_err("Invalid packet 1 - section extension [%d]!", i);
1890                                 ret = XRAN_STATUS_INVALID_PACKET;
1891                                 break;
1892                                 }
1893                             }
1894                         }
1895                     else extlen = 0;
1896                     }
1897             }
1898             break;
1899
1900         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
1901             {
1902             struct xran_cp_radioapp_section3_header *hdr;
1903             struct xran_cp_radioapp_section3 *section;
1904
1905                 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
1906
1907                 result->hdr.timeOffset  = rte_be_to_cpu_16(hdr->timeOffset);
1908                 result->hdr.scs         = hdr->frameStructure.uScs;
1909                 result->hdr.fftSize     = hdr->frameStructure.fftSize;
1910                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1911                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1912                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
1913
1914                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
1915                 if(section == NULL) {
1916                     print_err("Invalid packet 3 - radio app hedaer!");
1917                     return (XRAN_STATUS_INVALID_PACKET);
1918                     }
1919
1920                 for(i=0; i<result->numSections; i++) {
1921                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1922
1923                     result->sections[i].info.type       = apphdr->sectionType;
1924                     result->sections[i].info.id         = section->hdr.sectionId;
1925                     result->sections[i].info.rb         = section->hdr.rb;
1926                     result->sections[i].info.symInc     = section->hdr.symInc;
1927                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1928                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1929                     result->sections[i].info.numSymbol  = section->hdr.u.s3.numSymbol;
1930                     result->sections[i].info.reMask     = section->hdr.u.s3.reMask;
1931                     result->sections[i].info.beamId     = section->hdr.u.s3.beamId;
1932                     result->sections[i].info.ef         = section->hdr.u.s3.ef;
1933                     result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
1934
1935                     if(section->reserved) {
1936                         print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);
1937                         ret = XRAN_STATUS_INVALID_PACKET;
1938                         }
1939
1940                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3));
1941                     if(section == NULL) {
1942                         print_err("Invalid packet 3 - number of section [%d:%d]!",
1943                                     result->numSections, i);
1944                         result->numSections = i;
1945                         ret = XRAN_STATUS_INVALID_PACKET;
1946                         break;
1947                         }
1948
1949                     if(result->sections[i].info.ef) {
1950                         // parse section extension
1951                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
1952                         if(extlen > 0) {
1953                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
1954                             if(section == NULL) {
1955                                 print_err("Invalid packet 3 - section extension [%d]!", i);
1956                                 ret = XRAN_STATUS_INVALID_PACKET;
1957                                 break;
1958                                 }
1959                             }
1960                         }
1961                     else extlen = 0;
1962                     }
1963             }
1964             break;
1965
1966         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
1967         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
1968         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
1969         default:
1970             ret = XRAN_STATUS_INVALID_PARAM;
1971             print_err("Non-supported Section Type - %d", apphdr->sectionType);
1972         }
1973
1974 #if 0
1975     printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
1976             result->dir?"DL":"UL",
1977             result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1978             result->sectionType, result->numSections,
1979             result->hdr.startSymId,
1980             result->hdr.filterIdx,
1981             result->hdr.iqWidth, result->hdr.compMeth);
1982
1983     for(i=0; i<result->numSections; i++) {
1984         printf("  || %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
1985             i, result->sections[i].info.id,
1986             result->sections[i].info.rb,
1987             result->sections[i].info.symInc, result->sections[i].info.numSymbol,
1988             result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
1989             result->sections[i].info.reMask,
1990             result->sections[i].info.beamId,
1991             result->sections[i].info.freqOffset,
1992             result->sections[i].info.ef);
1993
1994         if(result->sections[i].info.ef) {
1995             for(int j=0; j<result->sections[i].exDataSize; j++) {
1996                 printf("      || %2d : type=%d len=%d\n",
1997                         j, result->sections[i].exData[j].type, result->sections[i].exData[j].len);
1998                 switch(result->sections[i].exData[j].type) {
1999                     case XRAN_CP_SECTIONEXTCMD_1:
2000                         {
2001                         struct xran_sectionext1_info *ext1;
2002                         ext1 = result->sections[i].exData[j].data;
2003                         printf("      ||    bfwNumber=%d bfwiqWidth=%d bfwCompMeth=%d\n",
2004                                 ext1->bfwNumber, ext1->bfwiqWidth, ext1->bfwCompMeth);
2005                         }
2006                         break;
2007                     case XRAN_CP_SECTIONEXTCMD_2:
2008                         {
2009                         struct xran_sectionext2_info *ext2;
2010                         ext2 = result->sections[i].exData[j].data;
2011                         printf("      ||    AzPt=%02x(%d) ZePt=%02x(%d) Az3dd=%02x(%d) Ze3dd=%02x(%d) AzSI=%02x ZeSI=%02x\n",
2012                                 ext2->bfAzPt, ext2->bfAzPtWidth,
2013                                 ext2->bfZePt, ext2->bfZePtWidth,
2014                                 ext2->bfAz3dd, ext2->bfAz3ddWidth,
2015                                 ext2->bfZe3dd, ext2->bfZe3ddWidth,
2016                                 ext2->bfAzSI, ext2->bfZeSI);
2017                         }
2018                         break;
2019                     case XRAN_CP_SECTIONEXTCMD_4:
2020                         {
2021                         struct xran_sectionext4_info *ext4;
2022                         ext4 = result->sections[i].exData[j].data;
2023                         printf("      ||    csf=%d modCompScaler=%d\n",
2024                                 ext4->csf, ext4->modCompScaler);
2025                         }
2026                         break;
2027                     case XRAN_CP_SECTIONEXTCMD_5:
2028                         {
2029                         struct xran_sectionext5_info *ext5;
2030                         ext5 = result->sections[i].exData[j].data;
2031                         printf("      ||    num_sets=%d\n", ext5->num_sets);
2032                         for(int k=0; k<ext5->num_sets; k++) {
2033                             printf("          || %d - csf=%d mcScaleReMask=%04x mcScaleOffset=%04x\n",
2034                                 k, ext5->mc[k].csf,
2035                                 ext5->mc[k].mcScaleReMask, ext5->mc[k].mcScaleOffset);
2036                             }
2037                         }
2038                         break;
2039
2040                     case XRAN_CP_SECTIONEXTCMD_0:
2041                     case XRAN_CP_SECTIONEXTCMD_3:
2042                     default:
2043                         printf("Invalid section extension type!\n");
2044                     }
2045                 }
2046             }
2047         }
2048 #endif
2049
2050     return(ret);
2051 }
2052