Update to odulow per maintenance bronze
[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.numRBs          = 1;
457                 bfp_com_req.numDataElements = bfwNumPerRb*2;
458                 bfp_com_req.len             = bfwNumPerRb*4;
459                 bfp_com_req.compMethod      = p_ext1->bfwCompMeth;
460                 bfp_com_req.iqWidth         = p_ext1->bfwIqWidth;
461
462                 print_dbg("req 0x%08p iqWidth %d\n",bfp_com_req.data_in, bfp_com_req.iqWidth);
463
464                 parm_size = 1; /* exponent as part of bfwCompParam 1 octet */
465                 break;
466             case XRAN_BFWCOMPMETHOD_BLKSCALE:
467                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
468                 break;
469
470             case XRAN_BFWCOMPMETHOD_ULAW:
471                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
472                 break;
473
474             case XRAN_BFWCOMPMETHOD_BEAMSPACE:
475                 rte_panic("XRAN_BFWCOMPMETHOD_BLKSCALE");
476                 break;
477
478             case XRAN_BFWCOMPMETHOD_NONE:
479             default:
480                 p_bfw_content = (uint8_t *)(p_ext1+1);
481                 /* bfwCompParam is absent for no compression case */
482                 parm_size = 0;
483         }
484
485         if(p_bfw_content == NULL) {
486             print_err("Fail to allocate the space for section extension 1");
487             return (XRAN_STATUS_RESOURCE);
488             }
489
490         bfw_iq_bits = bfwNumPerRb* bfwiqWidth * 2;
491
492         parm_size += bfw_iq_bits>>3;
493         if(bfw_iq_bits%8)
494             parm_size++;
495
496         print_dbg("copy BF W %p -> %p size %d \n", p_bfw_iq_src, p_bfw_content, parm_size);
497         if (p_ext1->bfwIqWidth == 0 || p_ext1->bfwIqWidth == 16){
498             rte_memcpy(p_bfw_content, p_bfw_iq_src, parm_size);
499         } else {
500             bfp_com_rsp.data_out = (int8_t*)p_bfw_content;
501             if(xranlib_compress_avx512_bfw(&bfp_com_req, &bfp_com_rsp) == 0){
502                 comp_len = bfp_com_rsp.len;
503                 print_dbg("comp_len %d parm_size %d\n", comp_len, parm_size);
504             } else {
505                 print_err("compression failed\n");
506                 return (XRAN_STATUS_FAIL);
507             }
508         }
509
510         p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
511
512         cur_ext_len += parm_size;
513         parm_size = cur_ext_len % XRAN_SECTIONEXT_ALIGN;
514         if(parm_size) {
515             parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
516             p_bfw_content = (uint8_t *)(p_bfw_content + parm_size);
517             rte_memcpy(p_bfw_content, zeropad, parm_size);
518             cur_ext_len += parm_size;
519             print_dbg("zeropad %d cur_ext_len %d\n", parm_size, cur_ext_len);
520         }
521
522         if(cur_ext_len % XRAN_SECTIONEXT_ALIGN)
523             rte_panic("ext1 should be aligned on 4-bytes boundary");
524
525         p_ext1->extLen = cur_ext_len / XRAN_SECTIONEXT_ALIGN;
526         print_dbg("[%d] %p iq %p p_ext1->extLen %d\n",idxRb, p_ext1, p_ext1+1,  p_ext1->extLen);
527
528         /* update for next RB */
529         p_ext1_dst_cur += cur_ext_len;
530         p_bfw_iq_src   = p_bfw_iq_src + bfwNumPerRb*2;
531
532         total_len += cur_ext_len;
533     }
534
535     print_dbg("total_len %d\n", total_len);
536     return (total_len);
537 }
538
539
540 // Cyclic Prefix Length 5.4.4.14
541 //   CP_length = cpLength * Ts,  Ts = 1/30.72MHz
542 //    i.e cpLength = CP_length / Ts ?
543 #define CPLEN_TS           (30720000)
544 inline uint16_t xran_get_cplength(int CP_length)
545 {
546     return (CP_length);
547 }
548
549 // Frequency offset 5.4.5.11
550 //   frequency_offset = freqOffset * SCS * 0.5
551 //    i.e freqOffset = (frequency_offset *2 )/ SCS ?
552 inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)
553 {
554     return (freqOffset);
555 }
556
557 static int xran_append_sectionext_1(struct rte_mbuf *mbuf,
558                 struct xran_sectionext1_info *params, int last_flag)
559 {
560     int32_t total_len = 0;
561
562     if(params->bfwIQ_sz) {
563         int8_t *p_dst = (int8_t *)rte_pktmbuf_append(mbuf, params->bfwIQ_sz);
564
565         if(p_dst == NULL) {
566             print_err("Fail to allocate the space for section extension 1 [%d]", params->bfwIQ_sz);
567             return (XRAN_STATUS_RESOURCE);
568         }
569
570         /* extType1 with all the headers created by xran_cp_populate_section_ext_1() earlier */
571         total_len = params->bfwIQ_sz;
572     }
573
574     return (total_len);
575 }
576
577
578 static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,
579                 struct xran_sectionext1_info *params, int last_flag)
580 {
581     struct xran_cp_radioapp_section_ext1 *ext1;
582     uint8_t *data;
583     int parm_size, iq_size;
584     int total_len;
585
586     total_len = 0;
587
588     print_dbg("%s %d\n", __FUNCTION__, last_flag);
589
590     parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
591     ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);
592     if(ext1 == NULL) {
593         print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
594         return (XRAN_STATUS_RESOURCE);
595     }
596
597     total_len += parm_size;
598
599     ext1->extType       = XRAN_CP_SECTIONEXTCMD_1;
600     ext1->ef            = last_flag;
601     ext1->bfwCompMeth   = params->bfwCompMeth;
602     ext1->bfwIqWidth    = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);
603
604     switch(params->bfwCompMeth) {
605         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
606             parm_size = 1;
607             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
608             if(data == NULL) {
609                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
610                 return (XRAN_STATUS_RESOURCE);
611             }
612             total_len += parm_size;
613             *data = (params->bfwCompParam.exponent & 0x0f);
614             break;
615
616         case XRAN_BFWCOMPMETHOD_BLKSCALE:
617             parm_size = 1;
618             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
619             if(data == NULL) {
620                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
621                 return (XRAN_STATUS_RESOURCE);
622             }
623             total_len += parm_size;
624             *data = params->bfwCompParam.blockScaler;
625             break;
626
627         case XRAN_BFWCOMPMETHOD_ULAW:
628             parm_size = 1;
629             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
630             if(data == NULL) {
631                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
632                 return (XRAN_STATUS_RESOURCE);
633                 }
634             total_len += parm_size;
635             *data = params->bfwCompParam.compBitWidthShift;
636             break;
637
638         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
639             parm_size = params->bfwNumber>>3;
640             if(params->bfwNumber%8) parm_size++;
641             parm_size *= 8;
642             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
643             if(data == NULL) {
644                 print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
645                 return (XRAN_STATUS_RESOURCE);
646                 }
647             rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
648             total_len += parm_size;
649             break;
650
651         case XRAN_BFWCOMPMETHOD_NONE:
652         default:
653             parm_size = 0;
654         }
655
656     print_dbg("params->bfwNumber %d params->bfwiqWidth %d\n", params->bfwNumber, params->bfwiqWidth);
657
658     iq_size = params->bfwNumber * params->bfwiqWidth * 2;
659
660     parm_size = iq_size>>3;
661     if(iq_size%8)
662         parm_size++;
663
664     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
665     if(data == NULL) {
666         print_err("Fail to allocate the space for section extension 1 BF W iq_size: [%d]", parm_size);
667         return (XRAN_STATUS_RESOURCE);
668     }
669     rte_memcpy(data, params->p_bfwIQ, parm_size);
670
671     total_len += parm_size;
672     parm_size = total_len % XRAN_SECTIONEXT_ALIGN;
673     if(parm_size) {
674         parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
675         data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
676         if(data == NULL) {
677             print_err("Fail to allocate the space for section extension 1 [%d]", parm_size);
678             return (XRAN_STATUS_RESOURCE);
679         }
680         rte_memcpy(data, zeropad, parm_size);
681         total_len += parm_size;
682     }
683
684     ext1->extLen        = total_len / XRAN_SECTIONEXT_ALIGN;
685
686     return (total_len);
687 }
688
689 static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,
690                 struct xran_sectionext2_info *params, int last_flag)
691 {
692   struct xran_cp_radioapp_section_ext2 *ext2;
693   uint8_t *data;
694   int total_len;
695   int parm_size;
696   uint32_t val, shift_val;
697   int val_size, pad_size;
698
699
700     total_len = 0;
701
702     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
703     ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
704     if(ext2 == NULL) {
705         print_err("Fail to allocate the space for section extension 2");
706         return (XRAN_STATUS_RESOURCE);
707         }
708     total_len += parm_size;
709
710     ext2->extType           = XRAN_CP_SECTIONEXTCMD_2;
711     ext2->ef                = last_flag;
712     ext2->bfZe3ddWidth      = params->bfZe3ddWidth;
713     ext2->bfAz3ddWidth      = params->bfAz3ddWidth;
714     ext2->bfZePtWidth       = params->bfZePtWidth;
715     ext2->bfAzPtWidth       = params->bfAzPtWidth;
716     ext2->bfaCompResv0      = 0;
717     ext2->bfaCompResv1      = 0;
718
719     val = 0;
720     shift_val = 0;
721     if(params->bfAzPtWidth) {
722         val += params->bfAzPt & bitmask[params->bfAzPtWidth];
723         shift_val += 8 - (params->bfAzPtWidth+1);
724         }
725     else
726         shift_val += 8;
727
728     if(params->bfZePtWidth) {
729         val = val << (params->bfZePtWidth+1);
730         val += params->bfZePt & bitmask[params->bfZePtWidth];
731         shift_val += 8 - (params->bfZePtWidth+1);
732         }
733     else
734         shift_val += 8;
735
736     if(params->bfAz3ddWidth) {
737         val = val << (params->bfAz3ddWidth+1);
738         val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];
739         shift_val += 8 - (params->bfAz3ddWidth+1);
740         }
741     else
742         shift_val += 8;
743
744     if(params->bfZe3ddWidth) {
745         val = val << (params->bfZe3ddWidth+1);
746         val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];
747         shift_val += 8 - (params->bfZe3ddWidth+1);
748         }
749     else
750         shift_val += 8;
751
752     if(val) {
753         val = val << shift_val;
754         val = rte_cpu_to_be_32(val);
755         }
756
757     val_size = 4 - (shift_val/8);   /* ceil(total bit/8) */
758     parm_size = val_size + 1;       /* additional 1 byte for bfxxSI */
759
760     // alignment
761     total_len += parm_size;
762     pad_size = total_len % XRAN_SECTIONEXT_ALIGN;
763     if(pad_size) {
764         pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;
765         parm_size += pad_size;
766         total_len += pad_size;
767         }
768
769     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
770     if(data == NULL) {
771         print_err("Fail to allocate the space for section extension 2");
772         return (XRAN_STATUS_RESOURCE);
773         }
774
775     rte_memcpy(data, &val, val_size);
776     data += val_size;
777     *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
778     data++;
779     rte_memcpy(data, zeropad, pad_size);
780
781     ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
782     *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
783
784     return (total_len);
785 }
786
787 static int xran_prepare_sectionext_3(struct rte_mbuf *mbuf,
788                 struct xran_sectionext3_info *params, int last_flag)
789 {
790   int total_len;
791   int adj;
792
793
794     if(params->layerId == XRAN_LAYERID_0
795         || params->layerId == XRAN_LAYERID_TXD) {   /* first data layer */
796
797         struct xran_cp_radioapp_section_ext3_first *ext3_f;
798         uint64_t *tmp;
799
800         total_len = sizeof(struct xran_cp_radioapp_section_ext3_first);
801         ext3_f = (struct xran_cp_radioapp_section_ext3_first *)rte_pktmbuf_append(mbuf, total_len);
802         if(ext3_f == NULL) {
803             print_err("Fail to allocate the space for section extension 3");
804             return (XRAN_STATUS_RESOURCE);
805             }
806
807         ext3_f->layerId         = params->layerId;
808         ext3_f->ef              = last_flag;
809         ext3_f->extType         = XRAN_CP_SECTIONEXTCMD_3;
810         ext3_f->crsSymNum       = params->crsSymNum;
811         ext3_f->crsShift        = params->crsShift;
812         ext3_f->crsReMask       = params->crsReMask;
813         ext3_f->txScheme        = params->txScheme;
814         ext3_f->numLayers       = params->numLayers;
815         ext3_f->codebookIndex   = params->codebookIdx;
816
817         if(params->numAntPort == 2) {
818             ext3_f->beamIdAP3   = params->beamIdAP1;
819             ext3_f->beamIdAP2   = 0;
820             ext3_f->beamIdAP1   = 0;
821             ext3_f->extLen      = 3;
822             adj = 4;
823             total_len -= adj;
824             }
825         else {
826             ext3_f->beamIdAP3   = params->beamIdAP1;
827             ext3_f->beamIdAP2   = params->beamIdAP2;
828             ext3_f->beamIdAP1   = params->beamIdAP3;
829             ext3_f->extLen      = 4;
830             adj = 0;
831             }
832         ext3_f->reserved0       = 0;
833         ext3_f->reserved1       = 0;
834         ext3_f->reserved2       = 0;
835
836         /* convert byte order */
837         tmp = (uint64_t *)ext3_f;
838         *tmp = rte_cpu_to_be_64(*tmp); tmp++;
839         *tmp = rte_cpu_to_be_64(*tmp);
840
841         if(adj)
842             rte_pktmbuf_trim(mbuf, adj);
843         }
844     else {  /* non-first data layer */
845         struct xran_cp_radioapp_section_ext3_non_first *ext3_nf;
846
847         total_len = sizeof(struct xran_cp_radioapp_section_ext3_non_first);
848         ext3_nf = (struct xran_cp_radioapp_section_ext3_non_first *)rte_pktmbuf_append(mbuf, total_len);
849         if(ext3_nf == NULL) {
850             print_err("Fail to allocate the space for section extension 3");
851             return (XRAN_STATUS_RESOURCE);
852             }
853
854         ext3_nf->layerId        = params->layerId;
855         ext3_nf->ef             = last_flag;
856         ext3_nf->extType        = XRAN_CP_SECTIONEXTCMD_3;
857         ext3_nf->numLayers      = params->numLayers;
858         ext3_nf->codebookIndex  = params->codebookIdx;
859
860         ext3_nf->extLen         = sizeof(struct xran_cp_radioapp_section_ext3_non_first)/XRAN_SECTIONEXT_ALIGN;
861
862         *(uint32_t *)ext3_nf = rte_cpu_to_be_32(*(uint32_t *)ext3_nf);
863         }
864
865     return (total_len);
866 }
867
868 static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
869                 struct xran_sectionext4_info *params, int last_flag)
870 {
871   struct xran_cp_radioapp_section_ext4 *ext4;
872   int parm_size;
873   int total_len;
874   int ret;
875
876
877     total_len = 0;
878
879     parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
880     ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
881     if(ext4 == NULL) {
882         print_err("Fail to allocate the space for section extension 4");
883         return(XRAN_STATUS_RESOURCE);
884         }
885     else {
886         total_len += parm_size;
887
888         ext4->extType       = XRAN_CP_SECTIONEXTCMD_4;
889         ext4->ef            = last_flag;
890         ext4->modCompScaler = params->modCompScaler;
891         ext4->csf           = params->csf?1:0;
892         ext4->extLen        = total_len / XRAN_SECTIONEXT_ALIGN;
893
894         *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
895         }
896
897     return (total_len);
898 }
899
900 static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
901                 struct xran_sectionext5_info *params, int last_flag)
902 {
903   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
904   struct xran_cp_radioapp_section_ext5 ext5;
905   int padding;
906   int total_len;
907   uint8_t *data;
908   int i;
909
910
911     if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {
912         print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);
913         return (0);
914         }
915
916     total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)
917                 + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2
918                 - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust
919
920     /* for alignment */
921     padding = total_len % XRAN_SECTIONEXT_ALIGN;
922     if(padding) {
923         padding = XRAN_SECTIONEXT_ALIGN - padding;
924         total_len += padding;
925         }
926
927     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);
928     if(ext_hdr == NULL) {
929         print_err("Fail to allocate the space for section extension 5");
930         return (XRAN_STATUS_RESOURCE);
931         }
932
933     ext_hdr->extType    = XRAN_CP_SECTIONEXTCMD_5;
934     ext_hdr->ef         = last_flag;
935     ext_hdr->extLen     = total_len / XRAN_SECTIONEXT_ALIGN;
936
937     *(uint16_t *)ext_hdr    = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));
938
939     data = (uint8_t *)(ext_hdr + 1);
940     i = 0;
941     while(i < params->num_sets) {
942         if(i%2) { // odd index
943             ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;
944             ext5.csf2           = params->mc[i].csf;
945             ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;
946             ext5.reserved0      = 0;
947             i++;
948
949             // adding two sets at once (due to the definition of structure)
950             *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
951             rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));
952             data += sizeof(struct xran_cp_radioapp_section_ext5);
953             }
954         else { // even index
955             ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;
956             ext5.csf1           = params->mc[i].csf;
957             ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;
958             ext5.mcScaleReMask2 = 0;
959             i++;
960
961             if(i == params->num_sets) { // adding last even index
962                 *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
963                 rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);
964                 data += sizeof(struct xran_cp_radioapp_section_ext5)/2;
965                 break;
966                 }
967             }
968         }
969
970     /* zero padding */
971     if(padding)
972         rte_memcpy(data, zeropad, padding);
973
974     return (total_len);
975 }
976
977 /**
978  * @brief add section extension to C-Plane packet
979  *
980  * @param mbuf
981  *  A pointer to the packet buffer
982  * @param params
983  *  A porinter to the information to generate a C-Plane packet
984  * @return
985  *  XRAN_STATUS_SUCCESS on success
986  *  XRAN_STATUS_INVALID_PARM
987  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
988  */
989 int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
990 {
991     int i, ret;
992     uint32_t totalen;
993     int last_flag;
994     int ext_size;
995
996     if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {
997         print_err("Invalid total number of extensions - %d", params->exDataSize);
998         return (XRAN_STATUS_INVALID_PARAM);
999     }
1000
1001     totalen = 0;
1002
1003     ret = XRAN_STATUS_SUCCESS;
1004
1005     print_dbg("params->exDataSize %d\n", params->exDataSize);
1006     for(i=0; i < params->exDataSize; i++) {
1007         if(params->exData[i].data == NULL) {
1008             print_err("Invalid parameter - extension data %d is NULL", i);
1009             ret = XRAN_STATUS_INVALID_PARAM;
1010             continue;
1011         }
1012
1013         last_flag = (params->exDataSize == (i+1))?0:1;
1014
1015         switch(params->exData[i].type) {
1016             case XRAN_CP_SECTIONEXTCMD_1:
1017                 ext_size = xran_append_sectionext_1(mbuf, params->exData[i].data, last_flag);
1018                 break;
1019             case XRAN_CP_SECTIONEXTCMD_2:
1020                 ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
1021                 break;
1022             case XRAN_CP_SECTIONEXTCMD_3:
1023                 ext_size = xran_prepare_sectionext_3(mbuf, params->exData[i].data, last_flag);
1024                 break;
1025             case XRAN_CP_SECTIONEXTCMD_4:
1026                 ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
1027                 break;
1028             case XRAN_CP_SECTIONEXTCMD_5:
1029                 ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
1030                 break;
1031             default:
1032                 print_err("Extension Type %d is not supported!", params->exData[i].type);
1033                 ret = XRAN_STATUS_INVALID_PARAM;
1034                 ext_size = 0;
1035             }
1036
1037         if(ext_size == XRAN_STATUS_RESOURCE) {
1038             break;
1039         }
1040
1041         totalen += ext_size;
1042     }
1043
1044     return (totalen);
1045 }
1046
1047
1048 /**
1049  * @brief Fill the section body of type 0 in C-Plane packet
1050  *
1051  * @param section
1052  *  A pointer to the section in the packet buffer
1053  * @param params
1054  *  A porinter to the information to generate a C-Plane packet
1055  * @return
1056  *  XRAN_STATUS_SUCCESS on success
1057  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1058  */
1059 static int xran_prepare_section0(
1060                 struct xran_cp_radioapp_section0 *section,
1061                 struct xran_section_gen_info *params)
1062 {
1063 #if (XRAN_STRICT_PARM_CHECK)
1064     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1065         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1066         return (XRAN_STATUS_INVALID_PARAM);
1067         }
1068 #endif
1069
1070     section->hdr.sectionId      = params->info.id;
1071     section->hdr.rb             = params->info.rb;
1072     section->hdr.symInc         = params->info.symInc;
1073     section->hdr.startPrbc      = params->info.startPrbc;
1074     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1075
1076     section->hdr.u.s0.reMask    = params->info.reMask;
1077     section->hdr.u.s0.numSymbol = params->info.numSymbol;
1078     section->hdr.u.s0.reserved  = 0;
1079
1080     // for network byte order
1081     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1082
1083     return (XRAN_STATUS_SUCCESS);
1084 }
1085 /**
1086  * @brief Fill the section header of type 0 in C-Plane packet
1087  *
1088  * @param s0hdr
1089  *  A pointer to the section header in the packet buffer
1090  * @param params
1091  *  A porinter to the information to generate a C-Plane packet
1092  * @return
1093  *  XRAN_STATUS_SUCCESS always
1094  */
1095 static int xran_prepare_section0_hdr(
1096                 struct xran_cp_radioapp_section0_header *s0hdr,
1097                 struct xran_cp_gen_params *params)
1098
1099 {
1100     s0hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1101     s0hdr->frameStructure.fftSize   = params->hdr.fftSize;
1102     s0hdr->frameStructure.uScs      = params->hdr.scs;
1103     s0hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1104     s0hdr->reserved                 = 0;
1105
1106     return (XRAN_STATUS_SUCCESS);
1107 }
1108
1109 /**
1110  * @brief Fill the section body of type 1 in C-Plane packet
1111  *  Extension is not supported.
1112  *
1113  * @param section
1114  *  A pointer to the section header in the packet buffer
1115  * @param params
1116  *  A porinter to the information to generate a C-Plane packet
1117  * @return
1118  *  XRAN_STATUS_SUCCESS on success
1119  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1120  */
1121 static int xran_prepare_section1(
1122                 struct xran_cp_radioapp_section1 *section,
1123                 struct xran_section_gen_info *params)
1124 {
1125 #if (XRAN_STRICT_PARM_CHECK)
1126     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1127         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1128         return (XRAN_STATUS_INVALID_PARAM);
1129         }
1130 #endif
1131
1132     section->hdr.sectionId      = params->info.id;
1133     section->hdr.rb             = params->info.rb;
1134     section->hdr.symInc         = params->info.symInc;
1135     section->hdr.startPrbc      = params->info.startPrbc;
1136     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1137
1138     section->hdr.u.s1.reMask    = params->info.reMask;
1139     section->hdr.u.s1.numSymbol = params->info.numSymbol;
1140     section->hdr.u.s1.beamId    = params->info.beamId;
1141
1142     section->hdr.u.s1.ef        = params->info.ef;
1143
1144     // for network byte order
1145     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1146
1147     return (XRAN_STATUS_SUCCESS);
1148 }
1149 /**
1150  * @brief Fill the section header of type 1 in C-Plane packet
1151  *
1152  * @param s1hdr
1153  *  A pointer to the section header in the packet buffer
1154  * @param params
1155  *  A porinter to the information to generate a C-Plane packet
1156  * @return
1157  *  XRAN_STATUS_SUCCESS always
1158  */
1159 static int xran_prepare_section1_hdr(
1160                 struct xran_cp_radioapp_section1_header *s1hdr,
1161                 struct xran_cp_gen_params *params)
1162 {
1163     s1hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1164     s1hdr->udComp.udCompMeth        = params->hdr.compMeth;
1165     s1hdr->reserved                 = 0;
1166
1167     return (XRAN_STATUS_SUCCESS);
1168 }
1169
1170 /**
1171  * @brief Fill the section body of type 3 in C-Plane packet
1172  *  Extension is not supported.
1173  *
1174  * @param section
1175  *  A pointer to the section header in the packet buffer
1176  * @param params
1177  *  A porinter to the information to generate a C-Plane packet
1178  * @return
1179  *  XRAN_STATUS_SUCCESS on success
1180  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
1181  */
1182 static int xran_prepare_section3(
1183                 struct xran_cp_radioapp_section3 *section,
1184                 struct xran_section_gen_info *params)
1185 {
1186 #if (XRAN_STRICT_PARM_CHECK)
1187     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
1188         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
1189         return (XRAN_STATUS_INVALID_PARAM);
1190         }
1191 #endif
1192
1193     section->hdr.sectionId      = params->info.id;
1194     section->hdr.rb             = params->info.rb;
1195     section->hdr.symInc         = params->info.symInc;
1196     section->hdr.startPrbc      = params->info.startPrbc;
1197     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
1198
1199     section->hdr.u.s3.reMask    = params->info.reMask;
1200     section->hdr.u.s3.numSymbol = params->info.numSymbol;
1201     section->hdr.u.s3.beamId    = params->info.beamId;
1202
1203     section->freqOffset         = rte_cpu_to_be_32(params->info.freqOffset)>>8;
1204     section->reserved           = 0;
1205
1206     section->hdr.u.s3.ef        = params->info.ef;
1207
1208     // for network byte order (header, 8 bytes)
1209     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
1210
1211     return (XRAN_STATUS_SUCCESS);
1212 }
1213 /**
1214  * @brief Fill the section header of type 3 in C-Plane packet
1215  *
1216  * @param s3hdr
1217  *  A pointer to the section header in the packet buffer
1218  * @param params
1219  *  A porinter to the information to generate a C-Plane packet
1220  * @return
1221  *  XRAN_STATUS_SUCCESS always
1222  */
1223 static int xran_prepare_section3_hdr(
1224                 struct xran_cp_radioapp_section3_header *s3hdr,
1225                 struct xran_cp_gen_params *params)
1226
1227 {
1228     s3hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
1229     s3hdr->frameStructure.fftSize   = params->hdr.fftSize;
1230     s3hdr->frameStructure.uScs      = params->hdr.scs;
1231     s3hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
1232     s3hdr->udComp.udIqWidth         = params->hdr.iqWidth;
1233     s3hdr->udComp.udCompMeth        = params->hdr.compMeth;
1234
1235     return (XRAN_STATUS_SUCCESS);
1236 }
1237
1238 /**
1239  * @brief add sections to C-Plane packet
1240  *  Section type 1 and 3 are supported.
1241  *
1242  * @param mbuf
1243  *  A pointer to the packet buffer
1244  * @param params
1245  *  A porinter to the information to generate a C-Plane packet
1246  * @return
1247  *  XRAN_STATUS_SUCCESS on success
1248  *  XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
1249  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1250  */
1251 int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1252 {
1253   int i, ret, ext_flag;
1254   uint32_t totalen;
1255   void *section;
1256   int section_size;
1257   int (*xran_prepare_section_func)(void *section, void *params);
1258
1259
1260     totalen = 0;
1261     switch(params->sectionType) {
1262         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1263             section_size                = sizeof(struct xran_cp_radioapp_section0);
1264             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section0;
1265             break;
1266
1267         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1268             section_size                = sizeof(struct xran_cp_radioapp_section1);
1269             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section1;
1270             break;
1271
1272         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1273             section_size                = sizeof(struct xran_cp_radioapp_section3);
1274             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section3;
1275             break;
1276
1277         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1278         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1279         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1280         default:
1281             section_size                = 0;
1282             xran_prepare_section_func   = NULL;
1283             print_err("Section Type %d is not supported!", params->sectionType);
1284             return (XRAN_STATUS_INVALID_PARAM);
1285         }
1286
1287     if(unlikely(xran_prepare_section_func == NULL)) {
1288        print_err("Section Type %d is not supported!", params->sectionType);
1289        return (XRAN_STATUS_INVALID_PARAM);
1290     }
1291
1292     for(i=0; i < params->numSections; i++) {
1293         section = rte_pktmbuf_append(mbuf, section_size);
1294         if(section == NULL) {
1295             print_err("Fail to allocate the space for section[%d]!", i);
1296             return (XRAN_STATUS_RESOURCE);
1297         }
1298         print_dbg("%s %d ef %d\n", __FUNCTION__, i, params->sections[i].info.ef);
1299         ret = xran_prepare_section_func((void *)section,
1300                             (void *)&params->sections[i]);
1301         if(ret < 0){
1302             print_err("%s %d\n", __FUNCTION__, ret);
1303             return (ret);
1304         }
1305         totalen += section_size;
1306
1307         if(params->sections[i].info.ef) {
1308             print_dbg("sections[%d].info.ef %d exDataSize %d  type %d\n", i, params->sections[i].info.ef,
1309                 params->sections[i].exDataSize, params->sections[i].exData[0].type);
1310             ret = xran_append_section_extensions(mbuf, &params->sections[i]);
1311             if(ret < 0)
1312                 return (ret);
1313             totalen += ret;
1314        }
1315     }
1316
1317     return (totalen);
1318 }
1319
1320 /**
1321  * @brief fill the information of a radio application header in a C-Plane packet
1322  *
1323  * @param apphdr
1324  *  A pointer to the application header in the packet buffer
1325  * @param params
1326  *  A porinter to the information to generate a C-Plane packet
1327  * @return
1328  *  XRAN_STATUS_SUCCESS on success
1329  *  XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
1330  */
1331 static inline int xran_prepare_radioapp_common_header(
1332                 struct xran_cp_radioapp_common_header *apphdr,
1333                 struct xran_cp_gen_params *params)
1334 {
1335
1336 #if (XRAN_STRICT_PARM_CHECK)
1337     if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
1338         print_err("Invalid direction!");
1339         return (XRAN_STATUS_INVALID_PARAM);
1340         }
1341     if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
1342         print_err("Invalid Slot ID!");
1343         return (XRAN_STATUS_INVALID_PARAM);
1344         }
1345     if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
1346         print_err("Invalid Symbol ID!");
1347         return (XRAN_STATUS_INVALID_PARAM);
1348         }
1349 #endif
1350
1351     apphdr->dataDirection   = params->dir;
1352     apphdr->payloadVer      = XRAN_PAYLOAD_VER;
1353     apphdr->filterIndex     = params->hdr.filterIdx;
1354     apphdr->frameId         = params->hdr.frameId;
1355     apphdr->subframeId      = params->hdr.subframeId;
1356     apphdr->slotId          = xran_slotid_convert(params->hdr.slotId, 0);
1357     apphdr->startSymbolId   = params->hdr.startSymId;
1358     apphdr->numOfSections   = params->numSections;
1359     apphdr->sectionType     = params->sectionType;
1360
1361     /* radio app header has common parts of 4bytes for all section types */
1362     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1363
1364     return (XRAN_STATUS_SUCCESS);
1365 }
1366
1367 /**
1368  * @brief add a radio application header in a C-Plane packet
1369  *
1370  * @param mbuf
1371  *  A pointer to the packet buffer
1372  * @param params
1373  *  A porinter to the information to generate a C-Plane packet
1374  * @return
1375  *  The length of added section (>0) on success
1376  *  XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
1377  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1378  */
1379 int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1380 {
1381   int ret;
1382   uint32_t totalen;
1383   struct xran_cp_radioapp_common_header *apphdr;
1384   int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
1385
1386
1387 #if (XRAN_STRICT_PARM_CHECK)
1388     if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
1389         print_err("Invalid Section Type - %d", params->sectionType);
1390         return (XRAN_STATUS_INVALID_PARAM);
1391         }
1392 #endif
1393
1394     switch(params->sectionType) {
1395         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1396             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;
1397             totalen = sizeof(struct xran_cp_radioapp_section0_header);
1398             break;
1399
1400         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1401             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;
1402             totalen = sizeof(struct xran_cp_radioapp_section1_header);
1403             break;
1404
1405         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1406             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;
1407             totalen = sizeof(struct xran_cp_radioapp_section3_header);
1408             break;
1409
1410         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1411         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1412         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1413         default:
1414             print_err("Section Type %d is not supported!", params->sectionType);
1415             xran_prepare_radioapp_section_hdr_func = NULL;
1416             totalen = 0;
1417             return (XRAN_STATUS_INVALID_PARAM);
1418         }
1419
1420     apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
1421     if(unlikely(apphdr == NULL)) {
1422         print_err("Fail to reserve the space for radio application header!");
1423         return (XRAN_STATUS_RESOURCE);
1424         }
1425
1426     ret = xran_prepare_radioapp_common_header(apphdr, params);
1427     if(unlikely(ret < 0)) {
1428         return (ret);
1429         }
1430
1431     if(likely(xran_prepare_radioapp_section_hdr_func)) {
1432         totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
1433         }
1434     else {
1435         print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
1436         return (XRAN_STATUS_INVALID_PARAM);
1437         }
1438
1439     return (totalen);
1440 }
1441
1442 /**
1443  * @brief Create a C-Plane packet
1444  *  Transport layer fragmentation is not supported.
1445  *
1446  * @ingroup xran_cp_pkt
1447  *
1448  * @param mbuf
1449  *  A pointer to the packet buffer
1450  * @param params
1451  *  A porinter to the information to generate a C-Plane packet
1452  * @param CC_ID
1453  *  Component Carrier ID for this C-Plane message
1454  * @param Ant_ID
1455  *  Antenna ID(RU Port ID) for this C-Plane message
1456  * @param seq_id
1457  *  Sequence ID for this C-Plane message
1458  * @return
1459  *  XRAN_STATUS_SUCCESS on success
1460  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1461  *  XRAN_STATUS_INVALID_PARM if section type is invalid
1462  */
1463 int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
1464                         struct xran_cp_gen_params *params,
1465                         uint8_t CC_ID, uint8_t Ant_ID,
1466                         uint8_t seq_id)
1467 {
1468   int ret;
1469   uint32_t payloadlen;
1470   struct xran_ecpri_hdr *ecpri_hdr;
1471
1472
1473     payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
1474
1475     ret = xran_append_radioapp_header(mbuf, params);
1476     if(ret < 0) {
1477         print_err("%s %d\n", __FUNCTION__, ret);
1478         return (ret);
1479     }
1480     payloadlen += ret;
1481
1482     ret = xran_append_control_section(mbuf, params);
1483     if(ret < 0) {
1484         print_err("%s %d\n", __FUNCTION__, ret);
1485         return (ret);
1486     }
1487     payloadlen += ret;
1488
1489     /* set payload length */
1490     ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
1491
1492     return (XRAN_STATUS_SUCCESS);
1493 }
1494
1495
1496 ///////////////////////////////////////
1497 // for RU emulation
1498 int xran_parse_section_ext1(void *ext,
1499                 struct xran_sectionext1_info *extinfo)
1500 {
1501   int len;
1502   int total_len;
1503   struct xran_cp_radioapp_section_ext1 *ext1;
1504   uint8_t *data;
1505   int parm_size, iq_size;
1506   int N;
1507   void *pHandle;
1508
1509     pHandle = NULL;
1510     N = xran_get_conf_num_bfweights(pHandle);
1511     extinfo->bfwNumber = N;
1512
1513     ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
1514     data = (uint8_t *)ext;
1515
1516     len = 0;
1517     total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1518
1519     extinfo->bfwCompMeth    = ext1->bfwCompMeth;
1520     extinfo->bfwiqWidth     = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
1521
1522     len     += sizeof(struct xran_cp_radioapp_section_ext1);
1523     data    += sizeof(struct xran_cp_radioapp_section_ext1);
1524
1525     switch(ext1->bfwCompMeth) {
1526         case XRAN_BFWCOMPMETHOD_NONE:
1527             parm_size = 0;
1528             break;
1529
1530         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
1531             parm_size = 1;
1532             extinfo->bfwCompParam.exponent = *data & 0x0f;
1533             break;
1534
1535         case XRAN_BFWCOMPMETHOD_BLKSCALE:
1536             parm_size = 1;
1537             extinfo->bfwCompParam.blockScaler = *data;
1538             break;
1539
1540         case XRAN_BFWCOMPMETHOD_ULAW:
1541             parm_size = 1;
1542             extinfo->bfwCompParam.compBitWidthShift = *data;
1543             break;
1544
1545         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
1546             parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
1547             rte_memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
1548             break;
1549
1550         default:
1551             print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
1552             parm_size = 0;
1553         }
1554
1555     len     += parm_size;
1556     data    += parm_size;
1557
1558     /* Get BF weights */
1559     iq_size = N * extinfo->bfwiqWidth * 2;  // total in bits
1560     parm_size = iq_size>>3;                 // total in bytes (/8)
1561     if(iq_size%8) parm_size++;              // round up
1562
1563     //rte_memcpy(data, extinfo->p_bfwIQ, parm_size);
1564     extinfo->p_bfwIQ =  (int16_t*)data;
1565
1566     len += parm_size;
1567
1568     parm_size = len % XRAN_SECTIONEXT_ALIGN;
1569     if(parm_size)
1570         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1571
1572     if(len != total_len) {
1573         // TODO: fix this print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
1574     }
1575
1576     return (total_len);
1577 }
1578
1579 int xran_parse_section_ext2(void *ext,
1580                 struct xran_sectionext2_info *extinfo)
1581 {
1582   int len;
1583   int total_len;
1584   struct xran_cp_radioapp_section_ext2 *ext2;
1585   uint8_t *data;
1586   int parm_size;
1587   uint32_t val;
1588   int val_size;
1589
1590
1591     ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
1592     data = (uint8_t *)ext;
1593     *(uint32_t *)ext2 = rte_be_to_cpu_32(*(uint32_t *)ext2);
1594
1595     len = 0;
1596     total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1597
1598     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
1599
1600     extinfo->bfAzPtWidth    = ext2->bfAzPtWidth;
1601     extinfo->bfZePtWidth    = ext2->bfZePtWidth;
1602     extinfo->bfAz3ddWidth   = ext2->bfAz3ddWidth;
1603     extinfo->bfZe3ddWidth   = ext2->bfZe3ddWidth;
1604
1605     if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
1606         print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
1607
1608     data    += parm_size;
1609     len     += parm_size;
1610
1611     val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
1612                 + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
1613                 + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
1614                 + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
1615     if(val_size) {
1616         val = rte_be_to_cpu_32(*(uint32_t *)data);
1617         val >>= (32 - val_size);
1618
1619         if(extinfo->bfZe3ddWidth) {
1620             extinfo->bfZe3dd    = val & bitmask[extinfo->bfZe3ddWidth];
1621             val >>= (extinfo->bfZe3ddWidth + 1);
1622             }
1623         if(extinfo->bfAz3ddWidth) {
1624             extinfo->bfAz3dd    = val & bitmask[extinfo->bfAz3ddWidth];
1625             val >>= (extinfo->bfAz3ddWidth + 1);
1626             }
1627         if(extinfo->bfZePtWidth) {
1628             extinfo->bfZePt     = val & bitmask[extinfo->bfZePtWidth];
1629             val >>= (extinfo->bfZePtWidth + 1);
1630             }
1631         if(extinfo->bfAzPtWidth) {
1632             extinfo->bfAzPt     = val & bitmask[extinfo->bfAzPtWidth];
1633             val >>= (extinfo->bfAzPtWidth + 1);
1634             }
1635         }
1636
1637     parm_size = val_size/8;
1638     if(val_size%8) parm_size += 1;
1639
1640     data    += parm_size;
1641     len     += parm_size;
1642
1643     extinfo->bfAzSI = (*data >> 3) & 0x07;
1644     extinfo->bfZeSI = *data & 0x07;
1645
1646     data++;
1647     len++;
1648
1649     parm_size = len % XRAN_SECTIONEXT_ALIGN;
1650     if(parm_size)
1651         len += (XRAN_SECTIONEXT_ALIGN - parm_size);
1652
1653     if(len != total_len) {
1654         print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
1655         }
1656
1657     return (total_len);
1658
1659 }
1660
1661 int xran_parse_section_ext3(void *ext,
1662                 struct xran_sectionext3_info *extinfo)
1663 {
1664   int len;
1665   int total_len;
1666
1667     total_len = 0;
1668     len = *((uint8_t *)ext + 1);
1669
1670     switch(len) {
1671         case 1:     /* non-first data layer */
1672             {
1673             struct xran_cp_radioapp_section_ext3_non_first *ext3_nf;
1674
1675             ext3_nf = (struct xran_cp_radioapp_section_ext3_non_first *)ext;
1676             *(uint32_t *)ext3_nf = rte_be_to_cpu_32(*(uint32_t *)ext3_nf);
1677
1678             total_len = ext3_nf->extLen * XRAN_SECTIONEXT_ALIGN;    /* from word to byte */
1679
1680             extinfo->codebookIdx= ext3_nf->codebookIndex;
1681             extinfo->layerId    = ext3_nf->layerId;
1682             extinfo->numLayers  = ext3_nf->numLayers;
1683             }
1684             break;
1685
1686         case 3:     /* first data layer with two antenna */
1687         case 4:     /* first data layer with four antenna */
1688             {
1689             struct xran_cp_radioapp_section_ext3_first *ext3_f;
1690             uint16_t *beamid;
1691
1692             ext3_f = (struct xran_cp_radioapp_section_ext3_first *)ext;
1693             *(uint64_t *)ext3_f = rte_be_to_cpu_64(*(uint64_t *)ext3_f);
1694
1695             total_len = ext3_f->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
1696
1697             extinfo->codebookIdx= ext3_f->codebookIndex;
1698             extinfo->layerId    = ext3_f->layerId;
1699             extinfo->numLayers  = ext3_f->numLayers;
1700             extinfo->txScheme   = ext3_f->txScheme;
1701             extinfo->crsReMask  = ext3_f->crsReMask;
1702             extinfo->crsShift   = ext3_f->crsShift;
1703             extinfo->crsSymNum  = ext3_f->crsSymNum;
1704
1705             /* beam IDs are stored from 10th octet */
1706             beamid = (uint16_t *)((uint8_t *)ext + 10);
1707
1708             extinfo->beamIdAP1  = rte_be_to_cpu_16(*beamid++);
1709             if(len == 4) {
1710                 extinfo->beamIdAP2  = rte_be_to_cpu_16(*beamid++);
1711                 extinfo->beamIdAP3  = rte_be_to_cpu_16(*beamid);
1712                 extinfo->numAntPort = 4;
1713                 }
1714             else {
1715                 extinfo->numAntPort = 2;
1716                 }
1717             }
1718             break;
1719
1720         default:
1721             print_err("Invalid length of extension 3 - %d", len);
1722         }
1723
1724     return (total_len);
1725 }
1726
1727 int xran_parse_section_ext4(void *ext,
1728                 struct xran_sectionext4_info *extinfo)
1729 {
1730   int len;
1731   struct xran_cp_radioapp_section_ext4 *ext4;
1732   int total_len;
1733
1734
1735     ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
1736
1737     *(uint32_t *)ext4 = rte_be_to_cpu_32(*(uint32_t *)ext4);
1738
1739     len = 0;
1740     total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1741
1742     extinfo->modCompScaler  = ext4->modCompScaler;
1743     extinfo->csf            = ext4->csf;
1744
1745     len += sizeof(struct xran_cp_radioapp_section_ext4);
1746     if(len != total_len) {
1747         print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
1748         }
1749
1750     return (total_len);
1751 }
1752
1753 int xran_parse_section_ext5(void *ext,
1754                 struct xran_sectionext5_info *extinfo)
1755 {
1756   int len;
1757   struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
1758   struct xran_cp_radioapp_section_ext5 ext5;
1759   int parm_size;
1760   int total_len;
1761   uint8_t *data;
1762   uint16_t i;
1763
1764     ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
1765     *(uint16_t *)ext_hdr = rte_be_to_cpu_16(*(uint16_t *)ext_hdr);
1766
1767     total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN;   /* from word to byte */
1768
1769     /* one set has 3.5 bytes, so enforcing double to do integer calculation */
1770     parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
1771
1772     if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
1773         print_err("Exceeds maximum number of parameters - %d", parm_size);
1774         parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
1775     }
1776
1777     len = 0;
1778     data = (uint8_t *)(ext_hdr + 1);
1779
1780     i = 0;
1781     while(i < parm_size) {
1782         // For odd number set, more data can be copied
1783         *((uint64_t *)&ext5) = rte_be_to_cpu_64(*((uint64_t *)data));
1784
1785         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset1;
1786         extinfo->mc[i].csf              = ext5.csf1;
1787         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask1;
1788         i++;
1789
1790         extinfo->mc[i].mcScaleOffset    = ext5.mcScaleOffset2;
1791         extinfo->mc[i].csf              = ext5.csf2;
1792         extinfo->mc[i].mcScaleReMask    = ext5.mcScaleReMask2;
1793         i++;
1794
1795         data += sizeof(struct xran_cp_radioapp_section_ext5);
1796         }
1797
1798     /* check the values of last set
1799      * due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
1800      * don't check mcScaleOffset might not be zero (some part is out of zero-padding) */
1801     i--;
1802     if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
1803         if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
1804             extinfo->num_sets = i;
1805         else
1806             extinfo->num_sets = i+1;
1807     }else {
1808         print_err("Maximum total number %d is not correct!", i);
1809     }
1810
1811     return (total_len);
1812 }
1813
1814 int xran_parse_section_extension(struct rte_mbuf *mbuf,
1815                     void *ext,
1816                     struct xran_section_gen_info *section)
1817 {
1818   int total_len, len, numext;
1819   uint8_t *ptr;
1820   int flag_last;
1821   int ext_type;
1822   int i;
1823
1824     total_len = 0;
1825     ptr = (uint8_t *)ext;
1826
1827     numext = 0;
1828
1829     flag_last = 1;
1830     i = 0;
1831     while(flag_last) {
1832         /* check ef */
1833         flag_last = (*ptr & 0x80);
1834
1835         ext_type = *ptr & 0x7f;
1836         section->exData[numext].type = ext_type;
1837         switch(ext_type) {
1838             case XRAN_CP_SECTIONEXTCMD_1:
1839                 section->exData[numext].data = &section->m_ext1[numext];
1840                 len = xran_parse_section_ext1(ptr, section->exData[numext].data);
1841                 section->exData[numext].len = len;
1842                 break;
1843             case XRAN_CP_SECTIONEXTCMD_2:
1844                 section->exData[numext].data = &section->m_ext2[numext];
1845                 len = xran_parse_section_ext2(ptr, section->exData[numext].data);
1846                 break;
1847             case XRAN_CP_SECTIONEXTCMD_3:
1848                 section->exData[numext].data = &section->m_ext3[numext];
1849                 len = xran_parse_section_ext3(ptr, section->exData[numext].data);
1850                 break;
1851             case XRAN_CP_SECTIONEXTCMD_4:
1852                 section->exData[numext].data = &section->m_ext4[numext];
1853                 len = xran_parse_section_ext4(ptr, section->exData[numext].data);
1854                 break;
1855             case XRAN_CP_SECTIONEXTCMD_5:
1856                 section->exData[numext].data = &section->m_ext5[numext];
1857                 len = xran_parse_section_ext5(ptr, section->exData[numext].data);
1858                 break;
1859
1860             default:
1861                 print_err("Extension %d is not supported!", ext_type);
1862                 len = 0;
1863             }
1864
1865         section->exData[numext].len = len;
1866         ptr += len; total_len += len;
1867
1868         i++;
1869         if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
1870
1871         /* exceeds maximum number of extensions */
1872         break;
1873         }
1874
1875     section->exDataSize = numext;
1876
1877     return (total_len);
1878
1879 }
1880
1881 /**
1882  * @brief Parse a C-Plane packet (for RU emulation)
1883  *  Transport layer fragmentation is not supported.
1884  *
1885  * @ingroup xran_cp_pkt
1886  *
1887  * @param mbuf
1888  *  The pointer of the packet buffer to be parsed
1889  * @param params
1890  *  The pointer of structure to store the information of parsed packet
1891  * @param eaxc
1892  *  The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
1893  * @return
1894  *  XRAN_STATUS_SUCCESS on success
1895  *  XRAN_STATUS_INVALID_PACKET if failed to parse the packet
1896  */
1897 int xran_parse_cp_pkt(struct rte_mbuf *mbuf,
1898                     struct xran_cp_gen_params *result,
1899                     struct xran_recv_packet_info *pkt_info)
1900 {
1901   struct xran_ecpri_hdr *ecpri_hdr;
1902   struct xran_cp_radioapp_common_header *apphdr;
1903   int i, ret;
1904   int extlen;
1905
1906
1907     ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
1908     if(ret < 0 && ecpri_hdr == NULL)
1909         return (XRAN_STATUS_INVALID_PACKET);
1910
1911     /* Process radio header. */
1912     apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
1913     if(apphdr == NULL) {
1914         print_err("Invalid packet - radio app hedaer!");
1915         return (XRAN_STATUS_INVALID_PACKET);
1916         }
1917
1918     *((uint32_t *)apphdr) = rte_be_to_cpu_32(*((uint32_t *)apphdr));
1919
1920     if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {
1921         print_err("Invalid Payload version - %d", apphdr->payloadVer);
1922         ret = XRAN_STATUS_INVALID_PACKET;
1923         }
1924
1925     result->dir             = apphdr->dataDirection;
1926     result->hdr.filterIdx   = apphdr->filterIndex;
1927     result->hdr.frameId     = apphdr->frameId;
1928     result->hdr.subframeId  = apphdr->subframeId;
1929     result->hdr.slotId      = apphdr->slotId;
1930     result->hdr.startSymId  = apphdr->startSymbolId;
1931     result->sectionType     = apphdr->sectionType;
1932     result->numSections     = apphdr->numOfSections;
1933
1934 #if 0
1935     printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
1936         pkt_info->payload_len,
1937         pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
1938         pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
1939         result->dir?"DL":"UL",
1940         pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
1941         result->sectionType, result->numSections,
1942         result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1943         result->hdr.startSymId
1944         );
1945 #endif
1946
1947     switch(apphdr->sectionType) {
1948         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
1949             {
1950             struct xran_cp_radioapp_section0_header *hdr;
1951             struct xran_cp_radioapp_section0 *section;
1952
1953                 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
1954
1955                 result->hdr.fftSize     = rte_be_to_cpu_16(hdr->timeOffset);
1956                 result->hdr.scs         = hdr->frameStructure.fftSize;
1957                 result->hdr.timeOffset  = hdr->frameStructure.uScs;
1958                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1959                 //hdr->reserved;    /* should be zero */
1960
1961                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
1962                 if(section == NULL) {
1963                     print_err("Invalid packet 0 - radio app hedaer!");
1964                     return (XRAN_STATUS_INVALID_PACKET);
1965                     }
1966                 for(i=0; i<result->numSections; i++) {
1967                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1968
1969                     result->sections[i].info.type       = apphdr->sectionType;
1970                     result->sections[i].info.id         = section->hdr.sectionId;
1971                     result->sections[i].info.rb         = section->hdr.rb;
1972                     result->sections[i].info.symInc     = section->hdr.symInc;
1973                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1974                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1975                     result->sections[i].info.numSymbol  = section->hdr.u.s0.numSymbol;
1976                     result->sections[i].info.reMask     = section->hdr.u.s0.reMask;
1977                     //section->hdr.u.s0.reserved;   /* should be zero */
1978
1979                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
1980                     if(section == NULL) {
1981                         print_err("Invalid packet 0 - number of section [%d:%d]!",
1982                                     result->numSections, i);
1983                         result->numSections = i;
1984                         ret = XRAN_STATUS_INVALID_PACKET;
1985                         break;
1986                         }
1987                     }
1988             }
1989             break;
1990
1991         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
1992             {
1993             struct xran_cp_radioapp_section1_header *hdr;
1994             struct xran_cp_radioapp_section1 *section;
1995
1996                 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
1997
1998                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1999                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
2000
2001                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
2002                 if(section == NULL) {
2003                     print_err("Invalid packet 1 - radio app hedaer!");
2004                     return (XRAN_STATUS_INVALID_PACKET);
2005                     }
2006
2007                 for(i=0; i<result->numSections; i++) {
2008                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
2009
2010                     result->sections[i].info.type       = apphdr->sectionType;
2011                     result->sections[i].info.id         = section->hdr.sectionId;
2012                     result->sections[i].info.rb         = section->hdr.rb;
2013                     result->sections[i].info.symInc     = section->hdr.symInc;
2014                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
2015                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
2016                     result->sections[i].info.numSymbol  = section->hdr.u.s1.numSymbol;
2017                     result->sections[i].info.reMask     = section->hdr.u.s1.reMask;
2018                     result->sections[i].info.beamId     = section->hdr.u.s1.beamId;
2019                     result->sections[i].info.ef         = section->hdr.u.s1.ef;
2020
2021                     section = (void *)rte_pktmbuf_adj(mbuf,
2022                                     sizeof(struct xran_cp_radioapp_section1));
2023                     if(section == NULL) {
2024                         print_err("Invalid packet 1 - number of section [%d:%d]!",
2025                                     result->numSections, i);
2026                         result->numSections = i;
2027                         ret = XRAN_STATUS_INVALID_PACKET;
2028                         break;
2029                         }
2030
2031                     if(result->sections[i].info.ef) {
2032                         // parse section extension
2033                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
2034                         if(extlen > 0) {
2035                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
2036                             if(section == NULL) {
2037                                 print_err("Invalid packet 1 - section extension [%d]!", i);
2038                                 ret = XRAN_STATUS_INVALID_PACKET;
2039                                 break;
2040                                 }
2041                             }
2042                         }
2043                     else extlen = 0;
2044                     }
2045             }
2046             break;
2047
2048         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
2049             {
2050             struct xran_cp_radioapp_section3_header *hdr;
2051             struct xran_cp_radioapp_section3 *section;
2052
2053                 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
2054
2055                 result->hdr.timeOffset  = rte_be_to_cpu_16(hdr->timeOffset);
2056                 result->hdr.scs         = hdr->frameStructure.uScs;
2057                 result->hdr.fftSize     = hdr->frameStructure.fftSize;
2058                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
2059                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
2060                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
2061
2062                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
2063                 if(section == NULL) {
2064                     print_err("Invalid packet 3 - radio app hedaer!");
2065                     return (XRAN_STATUS_INVALID_PACKET);
2066                     }
2067
2068                 for(i=0; i<result->numSections; i++) {
2069                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
2070
2071                     result->sections[i].info.type       = apphdr->sectionType;
2072                     result->sections[i].info.id         = section->hdr.sectionId;
2073                     result->sections[i].info.rb         = section->hdr.rb;
2074                     result->sections[i].info.symInc     = section->hdr.symInc;
2075                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
2076                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
2077                     result->sections[i].info.numSymbol  = section->hdr.u.s3.numSymbol;
2078                     result->sections[i].info.reMask     = section->hdr.u.s3.reMask;
2079                     result->sections[i].info.beamId     = section->hdr.u.s3.beamId;
2080                     result->sections[i].info.ef         = section->hdr.u.s3.ef;
2081                     result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
2082
2083                     if(section->reserved) {
2084                         print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);
2085                         ret = XRAN_STATUS_INVALID_PACKET;
2086                         }
2087
2088                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3));
2089                     if(section == NULL) {
2090                         print_err("Invalid packet 3 - number of section [%d:%d]!",
2091                                     result->numSections, i);
2092                         result->numSections = i;
2093                         ret = XRAN_STATUS_INVALID_PACKET;
2094                         break;
2095                         }
2096
2097                     if(result->sections[i].info.ef) {
2098                         // parse section extension
2099                         extlen = xran_parse_section_extension(mbuf, (void *)section, &result->sections[i]);
2100                         if(extlen > 0) {
2101                             section = (void *)rte_pktmbuf_adj(mbuf, extlen);
2102                             if(section == NULL) {
2103                                 print_err("Invalid packet 3 - section extension [%d]!", i);
2104                                 ret = XRAN_STATUS_INVALID_PACKET;
2105                                 break;
2106                                 }
2107                             }
2108                         }
2109                     else extlen = 0;
2110                     }
2111             }
2112             break;
2113
2114         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
2115         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
2116         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
2117         default:
2118             ret = XRAN_STATUS_INVALID_PARAM;
2119             print_err("Non-supported Section Type - %d", apphdr->sectionType);
2120         }
2121
2122 #if 0
2123     printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
2124             result->dir?"DL":"UL",
2125             result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
2126             result->sectionType, result->numSections,
2127             result->hdr.startSymId,
2128             result->hdr.filterIdx,
2129             result->hdr.iqWidth, result->hdr.compMeth);
2130
2131     for(i=0; i<result->numSections; i++) {
2132         printf("  || %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
2133             i, result->sections[i].info.id,
2134             result->sections[i].info.rb,
2135             result->sections[i].info.symInc, result->sections[i].info.numSymbol,
2136             result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
2137             result->sections[i].info.reMask,
2138             result->sections[i].info.beamId,
2139             result->sections[i].info.freqOffset,
2140             result->sections[i].info.ef);
2141
2142         if(result->sections[i].info.ef) {
2143             for(int j=0; j<result->sections[i].exDataSize; j++) {
2144                 printf("      || %2d : type=%d len=%d\n",
2145                         j, result->sections[i].exData[j].type, result->sections[i].exData[j].len);
2146                 switch(result->sections[i].exData[j].type) {
2147                     case XRAN_CP_SECTIONEXTCMD_1:
2148                         {
2149                         struct xran_sectionext1_info *ext1;
2150                         ext1 = result->sections[i].exData[j].data;
2151                         printf("      ||    bfwNumber=%d bfwiqWidth=%d bfwCompMeth=%d\n",
2152                                 ext1->bfwNumber, ext1->bfwiqWidth, ext1->bfwCompMeth);
2153                         }
2154                         break;
2155                     case XRAN_CP_SECTIONEXTCMD_2:
2156                         {
2157                         struct xran_sectionext2_info *ext2;
2158                         ext2 = result->sections[i].exData[j].data;
2159                         printf("      ||    AzPt=%02x(%d) ZePt=%02x(%d) Az3dd=%02x(%d) Ze3dd=%02x(%d) AzSI=%02x ZeSI=%02x\n",
2160                                 ext2->bfAzPt, ext2->bfAzPtWidth,
2161                                 ext2->bfZePt, ext2->bfZePtWidth,
2162                                 ext2->bfAz3dd, ext2->bfAz3ddWidth,
2163                                 ext2->bfZe3dd, ext2->bfZe3ddWidth,
2164                                 ext2->bfAzSI, ext2->bfZeSI);
2165                         }
2166                         break;
2167                     case XRAN_CP_SECTIONEXTCMD_4:
2168                         {
2169                         struct xran_sectionext4_info *ext4;
2170                         ext4 = result->sections[i].exData[j].data;
2171                         printf("      ||    csf=%d modCompScaler=%d\n",
2172                                 ext4->csf, ext4->modCompScaler);
2173                         }
2174                         break;
2175                     case XRAN_CP_SECTIONEXTCMD_5:
2176                         {
2177                         struct xran_sectionext5_info *ext5;
2178                         ext5 = result->sections[i].exData[j].data;
2179                         printf("      ||    num_sets=%d\n", ext5->num_sets);
2180                         for(int k=0; k<ext5->num_sets; k++) {
2181                             printf("          || %d - csf=%d mcScaleReMask=%04x mcScaleOffset=%04x\n",
2182                                 k, ext5->mc[k].csf,
2183                                 ext5->mc[k].mcScaleReMask, ext5->mc[k].mcScaleOffset);
2184                             }
2185                         }
2186                         break;
2187
2188                     case XRAN_CP_SECTIONEXTCMD_0:
2189                     case XRAN_CP_SECTIONEXTCMD_3:
2190                     default:
2191                         printf("Invalid section extension type!\n");
2192                     }
2193                 }
2194             }
2195         }
2196 #endif
2197
2198     return(ret);
2199 }
2200