03becc9c1eda5328ad51dca235d8359425d50fa3
[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
36
37 /**
38  * This structure to store the section information of C-Plane
39  * in order to generate and parse corresponding U-Plane */
40 struct xran_sectioninfo_db {
41     uint32_t    cur_index;  /**< Current index to store fro this eAXC */
42     struct xran_section_info list[XRAN_MAX_NUM_SECTIONS]; /**< The array of section information */
43     };
44
45 static struct xran_sectioninfo_db sectiondb[XRAN_MAX_SECTIONDB_CTX][XRAN_DIR_MAX][XRAN_COMPONENT_CARRIERS_MAX][XRAN_MAX_ANTENNA_NR*2];
46
47
48 /**
49  * @brief Initialize section database.
50  *   Allocate required memory space to store section information.
51  *   Each eAxC allocates dedicated storage and the entry size is the maximum number of sections.
52  *   Total entry size : number of CC * number of antenna * max number of sections * 2(direction)
53  *
54  * @ingroup xran_cp_pkt
55  *
56  * @param pHandle
57  *  handle for xRAN interface, currently not being used
58  * @return
59  *  XRAN_STATUS_SUCCESS on success
60  *  XRAN_STATUS_RESOURCE, if memory is not enough to allocate database area
61  */
62 int xran_cp_init_sectiondb(void *pHandle)
63 {
64   int ctx, dir, cc, ant;
65
66     for(ctx=0; ctx < XRAN_MAX_SECTIONDB_CTX; ctx++)
67         for(dir=0; dir < XRAN_DIR_MAX; dir++)
68             for(cc=0; cc < XRAN_COMPONENT_CARRIERS_MAX; cc++)
69                 for(ant=0; ant < XRAN_MAX_ANTENNA_NR*2; ant++)
70                     sectiondb[ctx][dir][cc][ant].cur_index = 0;
71
72     return (XRAN_STATUS_SUCCESS);
73 }
74
75 /**
76  * @brief Release and free section database
77  *
78  * @ingroup xran_cp_pkt
79  *
80  * @param pHandle
81  *  handle for xRAN interface, currently not being used
82  * @return
83  *  XRAN_STATUS_SUCCESS on success
84  */
85 int xran_cp_free_sectiondb(void *pHandle)
86 {
87     return (XRAN_STATUS_SUCCESS);
88 }
89
90 static inline struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,
91         uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
92 {
93   struct xran_sectioninfo_db *ptr;
94
95
96     if(unlikely(ctx_id >= XRAN_MAX_SECTIONDB_CTX)) {
97         print_err("Invalid Context id - %d", ctx_id);
98         return (NULL);
99         }
100
101     if(unlikely(dir >= XRAN_DIR_MAX)) {
102         print_err("Invalid direction - %d", dir);
103         return (NULL);
104         }
105
106     if(unlikely(cc_id >= XRAN_COMPONENT_CARRIERS_MAX)) {
107         print_err("Invalid CC id - %d", cc_id);
108         return (NULL);
109         }
110
111     if(unlikely(ruport_id >= XRAN_MAX_ANTENNA_NR*2)) {
112         print_err("Invalid eAxC id - %d", ruport_id);
113         return (NULL);
114         }
115
116     ptr = &sectiondb[ctx_id][dir][cc_id][ruport_id];
117
118     return(ptr);
119 }
120
121 static inline struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
122 {
123     if(unlikely(ptr == NULL))
124         return (NULL);
125
126     if(unlikely(index > XRAN_MAX_NUM_SECTIONS)) {
127         print_err("Index is out of range - %d", index);
128         return (NULL);
129         }
130
131     return(&(ptr->list[index]));
132 }
133
134 /**
135  * @brief Add a section information of C-Plane to dabase.
136  *
137  * @ingroup xran_cp_pkt
138  *
139  * @param pHandle
140  *  handle for xRAN interface, currently not being used
141  * @param dir
142  *  Direction of C-Plane message for the section to store
143  * @param cc_id
144  *  CC ID of C-Plane message for the section to store
145  * @param ruport_id
146  *  RU port ID of C-Plane message for the section to store
147  * @param ctx_id
148  *  Context index for the section database
149  * @param info
150  *  The information of this section to store
151  * @return
152  *  XRAN_STATUS_SUCCESS on success
153  *  XRAN_STATUS_INVALID_PARAM, if direction, CC ID or RU port ID is incorrect
154  *  XRAN_STATUS_RESOURCE, if no more space to add on database
155  */
156 int xran_cp_add_section_info(void *pHandle,
157         uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
158         struct xran_section_info *info)
159 {
160   struct xran_sectioninfo_db *ptr;
161   struct xran_section_info *list;
162
163
164     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
165     if(unlikely(ptr == NULL)) {
166         return (XRAN_STATUS_INVALID_PARAM);
167         }
168
169     if(unlikely(ptr->cur_index >= XRAN_MAX_NUM_SECTIONS)) {
170         print_err("No more space to add section information!");
171         return (XRAN_STATUS_RESOURCE);
172         }
173
174     list = xran_get_section_info(ptr, ptr->cur_index);
175
176     rte_memcpy(list, info, sizeof(struct xran_section_info));
177
178     ptr->cur_index++;
179
180     return (XRAN_STATUS_SUCCESS);
181 }
182
183 int xran_cp_add_multisection_info(void *pHandle,
184         uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id,
185         struct xran_cp_gen_params *gen_info)
186 {
187   int i;
188   uint8_t dir, num_sections;
189   struct xran_sectioninfo_db *ptr;
190   struct xran_section_info *list;
191
192
193     dir             = gen_info->dir;
194     num_sections    = gen_info->numSections;
195
196     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
197     if(unlikely(ptr == NULL)) {
198         return (XRAN_STATUS_INVALID_PARAM);
199         }
200
201     if(unlikely(ptr->cur_index+num_sections >= XRAN_MAX_NUM_SECTIONS)) {
202         print_err("No more space to add section information!");
203         return (XRAN_STATUS_RESOURCE);
204         }
205
206     list = xran_get_section_info(ptr, ptr->cur_index);
207
208     for(i=0; i<num_sections; i++) {
209         rte_memcpy(&list[i], &gen_info->sections[i].info, sizeof(struct xran_section_info));
210         ptr->cur_index++;
211         }
212
213     return (XRAN_STATUS_SUCCESS);
214 }
215
216 /**
217  * @brief Find a section information of C-Plane from dabase
218  *   by given information
219  *
220  * @ingroup xran_cp_pkt
221  *
222  * @param pHandle
223  *  handle for xRAN interface, currently not being used
224  * @param dir
225  *  The direction of the section to find
226  * @param cc_id
227  *  The CC ID of the section to find
228  * @param ruport_id
229  *  RU port ID of the section to find
230  * @param ctx_id
231  *  Context index for the section database
232  * @param section_id
233  *  The ID of section to find
234  * @return
235  *  The pointer of section information if matched section is found
236  *  NULL if failed to find matched section
237  */
238 struct xran_section_info *xran_cp_find_section_info(void *pHandle,
239         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
240         uint8_t ctx_id, uint16_t section_id)
241 {
242   int index, num_index;
243   struct xran_sectioninfo_db *ptr;
244
245
246     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
247     if(unlikely(ptr == NULL))
248         return (NULL);
249
250     if(ptr->cur_index > XRAN_MAX_NUM_SECTIONS)
251         num_index = XRAN_MAX_NUM_SECTIONS;
252     else
253         num_index = ptr->cur_index;
254
255     for(index=0; index < num_index; index++) {
256         if(ptr->list[index].id == section_id) {
257             return (xran_get_section_info(ptr, index));
258             }
259         }
260
261     print_dbg("No section ID in the list - %d", section_id);
262     return (NULL);
263 }
264
265 /**
266  * @brief Iterate each section information of C-Plane
267  *  from the database of eAxC by given information
268  *
269  * @ingroup xran_cp_pkt
270  *
271  * @param pHandle
272  *  handle for xRAN interface, currently not being used
273  * @param dir
274  *  The direction of the section to find
275  * @param cc_id
276  *  The CC ID of the section to find
277  * @param ruport_id
278  *  RU port ID of the section to find
279  * @param ctx_id
280  *  Context index for the section database
281  * @param next
282  *  The pointer to store the position of next entry
283  * @return
284  *  The pointer of section information in the list
285  *  NULL if reached at the end of the list
286  */
287 struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,
288         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
289         uint8_t ctx_id, uint32_t *next)
290 {
291   int index;
292   struct xran_sectioninfo_db *ptr;
293
294
295     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
296     if(unlikely(ptr == NULL))
297         return (NULL);
298
299     index = *next;
300     if(*next < ptr->cur_index) {
301         (*next)++;
302         return (xran_get_section_info(ptr, index));
303         }
304     else {
305         print_dbg("No more sections in the list");
306         return (NULL);
307         }
308 }
309
310 /**
311  * @brief Get the size of stored entries
312  *  for the database of eAxC by given information
313  *
314  * @ingroup xran_cp_pkt
315  *
316  * @param pHandle
317  *  handle for xRAN interface, currently not being used
318  * @param dir
319  *  The direction of the section to find
320  * @param cc_id
321  *  The CC ID of the section to find
322  * @param ruport_id
323  *  RU port ID of the section to find
324  * @param ctx_id
325  *  Context index for the section database
326  * @return
327  *  The size of stored entries
328  *  -1 if failed to find matched database
329  */
330 int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
331 {
332   int i, index;
333   struct xran_sectioninfo_db *ptr;
334
335
336     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
337     if(unlikely(ptr == NULL))
338         return (-1);
339
340     return (ptr->cur_index);
341 }
342
343 /**
344  * @brief Reset a database of eAxC by given information
345  *
346  * @ingroup xran_cp_pkt
347  *
348  * @param pHandle
349  *  handle for xRAN interface, currently not being used
350  * @param dir
351  *  The direction of the section to find
352  * @param cc_id
353  *  The CC ID of the section to find
354  * @param ruport_id
355  *  RU port ID of the section to find
356  * @param ctx_id
357  *  Context index for the section database
358  * @return
359  *  XRAN_STATUS_SUCCESS on success
360  *  XRAN_STATUS_INVALID_PARM if failed to find matched database
361  */
362 int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id, uint8_t ctx_id)
363 {
364   struct xran_sectioninfo_db *ptr;
365
366     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id, ctx_id);
367     if(unlikely(ptr == NULL)) {
368         return (XRAN_STATUS_INVALID_PARAM);
369         }
370
371     ptr->cur_index = 0;
372
373     return (XRAN_STATUS_SUCCESS);
374 }
375
376
377 int xran_dump_sectiondb(void)
378 {
379     // TODO:
380     return (0);
381 }
382
383 // Cyclic Prefix Length 5.4.4.14
384 //   CP_length = cpLength * Ts,  Ts = 1/30.72MHz
385 //    i.e cpLength = CP_length / Ts ?
386 #define CPLEN_TS           (30720000)
387 inline uint16_t xran_get_cplength(int CP_length)
388 {
389     return (CP_length);
390 }
391
392 // Frequency offset 5.4.5.11
393 //   frequency_offset = freqOffset * SCS * 0.5
394 //    i.e freqOffset = (frequency_offset *2 )/ SCS ?
395 inline int32_t xran_get_freqoffset(int32_t freqOffset, int32_t scs)
396 {
397     return (freqOffset);
398 }
399
400
401 static int xran_prepare_sectionext_1(struct rte_mbuf *mbuf,
402                 struct xran_sectionext1_info *params, int last_flag)
403 {
404   struct xran_cp_radioapp_section_ext1 *ext1;
405   uint8_t *data;
406   int parm_size, iq_size;
407   int total_len;
408   static const uint8_t zeropad[XRAN_SECTIONEXT_ALIGN] = { 0, 0, 0, 0 };
409
410
411     total_len = 0;
412
413     parm_size = sizeof(struct xran_cp_radioapp_section_ext1);
414     ext1 = (struct xran_cp_radioapp_section_ext1 *)rte_pktmbuf_append(mbuf, parm_size);
415     if(ext1 == NULL) {
416         print_err("Fail to allocate the space for section extension 1");
417         return (XRAN_STATUS_RESOURCE);
418         }
419
420     total_len += parm_size;
421
422     ext1->extType       = XRAN_CP_SECTIONEXTCMD_1;
423     ext1->ef            = last_flag;
424     ext1->bfwCompMeth   = params->bfwCompMeth;
425     ext1->bfwIqWidth    = XRAN_CONVERT_BFWIQWIDTH(params->bfwiqWidth);
426
427     switch(params->bfwCompMeth) {
428         case XRAN_BFWCOMPMETHOD_BLKFLOAT:
429             parm_size = 1;
430             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
431             if(data == NULL) {
432                 print_err("Fail to allocate the space for section extension 1");
433                 return (XRAN_STATUS_RESOURCE);
434                 }
435             total_len += parm_size;
436             *data = (params->bfwCompParam.exponent & 0x0f);
437             break;
438
439         case XRAN_BFWCOMPMETHOD_BLKSCALE:
440             parm_size = 1;
441             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
442             if(data == NULL) {
443                 print_err("Fail to allocate the space for section extension 1");
444                 return (XRAN_STATUS_RESOURCE);
445                 }
446             total_len += parm_size;
447             *data = params->bfwCompParam.blockScaler;
448             break;
449
450         case XRAN_BFWCOMPMETHOD_ULAW:
451             parm_size = 1;
452             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
453             if(data == NULL) {
454                 print_err("Fail to allocate the space for section extension 1");
455                 return (XRAN_STATUS_RESOURCE);
456                 }
457             total_len += parm_size;
458             *data = params->bfwCompParam.compBitWidthShift;
459             break;
460
461         case XRAN_BFWCOMPMETHOD_BEAMSPACE:
462 #if 0
463             parm_size = ceil(params->bfwNumber/8)*8;
464 #else
465             parm_size = params->bfwNumber>>3;
466             if(params->bfwNumber%8) parm_size++;
467             parm_size *= 8;
468 #endif
469             data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
470             if(data == NULL) {
471                 print_err("Fail to allocate the space for section extension 1");
472                 return (XRAN_STATUS_RESOURCE);
473                 }
474             rte_memcpy(data, params->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
475             total_len += parm_size;
476             break;
477
478         case XRAN_BFWCOMPMETHOD_NONE:
479         default:
480             parm_size = 0;
481         }
482
483     iq_size = params->bfwNumber * params->bfwiqWidth * 2;
484 #if 0
485     parm_size = ceil(iq_size/8);
486 #else
487     parm_size = iq_size>>3;
488     if(iq_size%8) parm_size++;
489 #endif
490
491     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
492     if(data == NULL) {
493         print_err("Fail to allocate the space for section extension 1");
494         return (XRAN_STATUS_RESOURCE);
495         }
496     rte_memcpy(data, params->bfwIQ, parm_size);
497
498     total_len += parm_size;
499     parm_size = total_len % XRAN_SECTIONEXT_ALIGN;
500     if(parm_size) {
501         parm_size = XRAN_SECTIONEXT_ALIGN - parm_size;
502         data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
503         if(data == NULL) {
504             print_err("Fail to allocate the space for section extension 1");
505             return (XRAN_STATUS_RESOURCE);
506             }
507         rte_memcpy(data, zeropad, parm_size);
508         total_len += parm_size;
509         }
510
511     ext1->extLen        = total_len / XRAN_SECTIONEXT_ALIGN;
512
513     return (total_len);
514 }
515
516 static int xran_prepare_sectionext_2(struct rte_mbuf *mbuf,
517                 struct xran_sectionext2_info *params, int last_flag)
518 {
519   struct xran_cp_radioapp_section_ext2 *ext2;
520   uint8_t *data;
521   int total_len;
522   int parm_size;
523   uint32_t val, shift_val;
524   int val_size;
525
526
527     total_len = 0;
528
529     parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
530     ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
531     if(ext2 == NULL) {
532         print_err("Fail to allocate the space for section extension 2");
533         return (XRAN_STATUS_RESOURCE);
534         }
535     total_len += parm_size;
536
537     ext2->extType           = XRAN_CP_SECTIONEXTCMD_2;
538     ext2->ef                = last_flag;
539     ext2->bfZe3ddWidth      = params->bfZe3ddWidth;
540     ext2->bfAz3ddWidth      = params->bfAz3ddWidth;
541     ext2->bfZePtWidth       = params->bfZePtWidth;
542     ext2->bfAzPtWidth       = params->bfAzPtWidth;
543     ext2->bfaCompResv0      = 0;
544     ext2->bfaCompResv1      = 0;
545
546     val = 0;
547     shift_val = 0;
548     if(params->bfAzPtWidth) {
549         val += params->bfAzPt;
550         shift_val += 8 - (params->bfAzPtWidth+1);
551         }
552     else
553         shift_val += 8;
554
555     if(params->bfZePtWidth) {
556         val = val << (params->bfZePtWidth+1);
557         val += params->bfZePt;
558         shift_val += 8 - (params->bfZePtWidth+1);
559         }
560     else
561         shift_val += 8;
562
563     if(params->bfAz3ddWidth) {
564         val = val << (params->bfAz3ddWidth+1);
565         val += params->bfAz3dd;
566         shift_val += 8 - (params->bfAz3ddWidth+1);
567         }
568     else
569         shift_val += 8;
570
571     if(params->bfZe3ddWidth) {
572         val = val << (params->bfZe3ddWidth+1);
573         val += params->bfZe3dd;
574         shift_val += 8 - (params->bfZe3ddWidth+1);
575         }
576     else
577         shift_val += 8;
578
579     if(val) {
580         val = val << shift_val;
581         val = rte_cpu_to_be_32(val);
582         }
583
584     val_size = 4 - (shift_val/8);   /* ceil(total bit/8) */
585     parm_size = val_size + 1;       /* additional 1 byte for bfxxSI */
586
587     data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
588     if(data == NULL) {
589         print_err("Fail to allocate the space for section extension 2");
590         return (XRAN_STATUS_RESOURCE);
591         }
592     total_len += parm_size;
593
594     rte_memcpy(data, &val, val_size);
595     data += val_size;
596     *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
597
598     ext2->extLen            = total_len / XRAN_SECTIONEXT_ALIGN;
599     *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
600
601     return (total_len);
602 }
603
604 static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
605                 struct xran_sectionext4_info *params, int last_flag)
606 {
607   struct xran_cp_radioapp_section_ext4 *ext4;
608   int parm_size;
609   int total_len;
610   int ret;
611
612
613     total_len = 0;
614
615     parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
616     ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
617     if(ext4 == NULL) {
618         print_err("Fail to allocate the space for section extension 4");
619         return(XRAN_STATUS_RESOURCE);
620         }
621     else {
622         total_len += parm_size;
623
624         ext4->extType       = XRAN_CP_SECTIONEXTCMD_4;
625         ext4->ef            = last_flag;
626         ext4->modCompScaler = params->modCompScaler;
627         ext4->csf           = params->csf?1:0;
628         ext4->extLen        = 1;
629
630         *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
631         }
632
633     return (total_len);
634 }
635
636 static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
637                 struct xran_sectionext5_info *params, int last_flag)
638 {
639   struct xran_cp_radioapp_section_ext5_1 *ext5_1;
640   struct xran_cp_radioapp_section_ext5_2 *ext5_2;
641   int parm_size;
642   int total_len;
643   uint32_t *data;
644
645
646     total_len = 0;
647
648     if(params->num_sets == 1) {
649         parm_size = sizeof(struct xran_cp_radioapp_section_ext5_1);
650         ext5_1 = (struct xran_cp_radioapp_section_ext5_1 *)rte_pktmbuf_append(mbuf, parm_size);
651         if(ext5_1 == NULL) {
652             print_err("Fail to allocate the space for section extension 5-1");
653             return (XRAN_STATUS_RESOURCE);
654             }
655         else {
656             total_len += parm_size;
657
658             ext5_1->extType         = XRAN_CP_SECTIONEXTCMD_5;
659             ext5_1->ef              = last_flag;
660
661             ext5_1->mcScaleOffset   = params->mc[0].mcScaleOffset;
662             ext5_1->csf             = params->mc[0].csf;
663             ext5_1->mcScaleReMask   = params->mc[0].mcScaleReMask;
664             ext5_1->reserved        = 0;
665
666             ext5_1->extLen          = 2;
667
668             *(uint64_t *)ext5_1 = rte_cpu_to_be_64(*(uint64_t *)ext5_1);
669             }
670         }
671     else if(params->num_sets == 2) {
672         parm_size = sizeof(struct xran_cp_radioapp_section_ext5_2);
673         ext5_2 = (struct xran_cp_radioapp_section_ext5_2 *)rte_pktmbuf_append(mbuf, parm_size);
674         if(ext5_2 == NULL) {
675             print_err("Fail to allocate the space for section extension 5-2");
676             return (XRAN_STATUS_RESOURCE);
677             }
678         else {
679             total_len += parm_size;
680
681             ext5_2->extType         = XRAN_CP_SECTIONEXTCMD_5;
682             ext5_2->ef              = last_flag;
683
684             ext5_2->mcScaleOffset1  = params->mc[0].mcScaleOffset;
685             ext5_2->csf1            = params->mc[0].csf;
686             ext5_2->mcScaleReMask1  = params->mc[0].mcScaleReMask;
687             ext5_2->mcScaleOffset2  = params->mc[1].mcScaleOffset;
688             ext5_2->csf2            = params->mc[1].csf;
689             ext5_2->mcScaleReMask2  = params->mc[1].mcScaleReMask;
690
691             ext5_2->reserved0       = 0;
692             ext5_2->reserved1       = 0;
693
694             ext5_2->extLen          = 3;
695
696             *(uint64_t *)ext5_2 = rte_cpu_to_be_64(*(uint64_t *)ext5_2);
697             data = (uint32_t *)((uint8_t *)ext5_2 + 8);
698             *data = rte_cpu_to_be_32(*data);
699             }
700         }
701     else {
702         print_err("Invalid number of scalar values - %d", params->num_sets);
703         return (XRAN_STATUS_INVALID_PARAM);
704         }
705
706     return (total_len);
707 }
708
709 /**
710  * @brief add section extension to C-Plane packet
711  *
712  * @param mbuf
713  *  A pointer to the packet buffer
714  * @param params
715  *  A porinter to the information to generate a C-Plane packet
716  * @return
717  *  XRAN_STATUS_SUCCESS on success
718  *  XRAN_STATUS_INVALID_PARM
719  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
720  */
721 int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
722 {
723   int i, ret;
724   uint32_t totalen;
725   int last_flag;
726   int ext_size;
727
728
729     if(unlikely(params->exDataSize >= XRAN_MAX_NUM_EXTENSIONS)) {
730         print_err("Invalid total number of extensions - %d", params->exDataSize);
731         return (XRAN_STATUS_INVALID_PARAM);
732         }
733
734     totalen = 0;
735
736
737     ret = XRAN_STATUS_SUCCESS;
738
739     for(i=0; i < params->exDataSize; i++) {
740         if(params->exData[i].data == NULL) {
741             print_err("Invalid parameter - extension data %d is NULL", i);
742             ret = XRAN_STATUS_INVALID_PARAM;
743             continue;
744             }
745
746 //    params->exData[].len
747         last_flag = ((params->exDataSize - i)==1)?0:1;
748         switch(params->exData[i].type) {
749             case XRAN_CP_SECTIONEXTCMD_1:
750                 ext_size = xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);
751                 break;
752             case XRAN_CP_SECTIONEXTCMD_2:
753                 ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
754                 break;
755             case XRAN_CP_SECTIONEXTCMD_4:
756                 ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
757                 break;
758             case XRAN_CP_SECTIONEXTCMD_5:
759                 ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
760                 break;
761
762             case XRAN_CP_SECTIONEXTCMD_0:
763             case XRAN_CP_SECTIONEXTCMD_3:
764             default:
765                 print_err("Extension Type %d is not supported!", params->exData[i].type);
766                 ret = XRAN_STATUS_INVALID_PARAM;
767                 ext_size = 0;
768             }
769
770         if(ext_size == XRAN_STATUS_RESOURCE) {
771             break;
772             }
773
774         totalen += ext_size;
775         }
776
777     return (totalen);
778 }
779
780
781 /**
782  * @brief Fill the section body of type 0 in C-Plane packet
783  *
784  * @param section
785  *  A pointer to the section in the packet buffer
786  * @param params
787  *  A porinter to the information to generate a C-Plane packet
788  * @return
789  *  XRAN_STATUS_SUCCESS on success
790  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
791  */
792 static int xran_prepare_section0(
793                 struct xran_cp_radioapp_section0 *section,
794                 struct xran_section_gen_info *params)
795 {
796 #if (XRAN_STRICT_PARM_CHECK)
797     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
798         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
799         return (XRAN_STATUS_INVALID_PARAM);
800         }
801 #endif
802
803     section->hdr.sectionId      = params->info.id;
804     section->hdr.rb             = params->info.rb;
805     section->hdr.symInc         = params->info.symInc;
806     section->hdr.startPrbc      = params->info.startPrbc;
807     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
808
809     section->hdr.u.s0.reMask    = params->info.reMask;
810     section->hdr.u.s0.numSymbol = params->info.numSymbol;
811     section->hdr.u.s0.reserved  = 0;
812
813     // for network byte order
814     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
815
816     return (XRAN_STATUS_SUCCESS);
817 }
818 /**
819  * @brief Fill the section header of type 0 in C-Plane packet
820  *
821  * @param s0hdr
822  *  A pointer to the section header in the packet buffer
823  * @param params
824  *  A porinter to the information to generate a C-Plane packet
825  * @return
826  *  XRAN_STATUS_SUCCESS always
827  */
828 static int xran_prepare_section0_hdr(
829                 struct xran_cp_radioapp_section0_header *s0hdr,
830                 struct xran_cp_gen_params *params)
831
832 {
833     s0hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
834     s0hdr->frameStructure.fftSize   = params->hdr.fftSize;
835     s0hdr->frameStructure.uScs      = params->hdr.scs;
836     s0hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
837     s0hdr->reserved                 = 0;
838
839     return (XRAN_STATUS_SUCCESS);
840 }
841
842 /**
843  * @brief Fill the section body of type 1 in C-Plane packet
844  *  Extension is not supported.
845  *
846  * @param section
847  *  A pointer to the section header in the packet buffer
848  * @param params
849  *  A porinter to the information to generate a C-Plane packet
850  * @return
851  *  XRAN_STATUS_SUCCESS on success
852  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
853  */
854 static int xran_prepare_section1(
855                 struct xran_cp_radioapp_section1 *section,
856                 struct xran_section_gen_info *params)
857 {
858 #if (XRAN_STRICT_PARM_CHECK)
859     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
860         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
861         return (XRAN_STATUS_INVALID_PARAM);
862         }
863 #endif
864
865     section->hdr.sectionId      = params->info.id;
866     section->hdr.rb             = params->info.rb;
867     section->hdr.symInc         = params->info.symInc;
868     section->hdr.startPrbc      = params->info.startPrbc;
869     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
870
871     section->hdr.u.s1.reMask    = params->info.reMask;
872     section->hdr.u.s1.numSymbol = params->info.numSymbol;
873     section->hdr.u.s1.beamId    = params->info.beamId;
874
875     section->hdr.u.s1.ef        = params->info.ef;
876
877     // for network byte order
878     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
879
880     return (XRAN_STATUS_SUCCESS);
881 }
882 /**
883  * @brief Fill the section header of type 1 in C-Plane packet
884  *
885  * @param s1hdr
886  *  A pointer to the section header in the packet buffer
887  * @param params
888  *  A porinter to the information to generate a C-Plane packet
889  * @return
890  *  XRAN_STATUS_SUCCESS always
891  */
892 static int xran_prepare_section1_hdr(
893                 struct xran_cp_radioapp_section1_header *s1hdr,
894                 struct xran_cp_gen_params *params)
895 {
896     s1hdr->udComp.udIqWidth         = params->hdr.iqWidth;
897     s1hdr->udComp.udCompMeth        = params->hdr.compMeth;
898     s1hdr->reserved                 = 0;
899
900     return (XRAN_STATUS_SUCCESS);
901 }
902
903 /**
904  * @brief Fill the section body of type 3 in C-Plane packet
905  *  Extension is not supported.
906  *
907  * @param section
908  *  A pointer to the section header in the packet buffer
909  * @param params
910  *  A porinter to the information to generate a C-Plane packet
911  * @return
912  *  XRAN_STATUS_SUCCESS on success
913  *  XRAN_STATUS_INVALID_PARM if the number of symbol is invalid
914  */
915 static int xran_prepare_section3(
916                 struct xran_cp_radioapp_section3 *section,
917                 struct xran_section_gen_info *params)
918 {
919 #if (XRAN_STRICT_PARM_CHECK)
920     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
921         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
922         return (XRAN_STATUS_INVALID_PARAM);
923         }
924 #endif
925
926     section->hdr.sectionId      = params->info.id;
927     section->hdr.rb             = params->info.rb;
928     section->hdr.symInc         = params->info.symInc;
929     section->hdr.startPrbc      = params->info.startPrbc;
930     section->hdr.numPrbc        = XRAN_CONVERT_NUMPRBC(params->info.numPrbc);
931
932     section->hdr.u.s3.reMask    = params->info.reMask;
933     section->hdr.u.s3.numSymbol = params->info.numSymbol;
934     section->hdr.u.s3.beamId    = params->info.beamId;
935
936     section->freqOffset         = rte_cpu_to_be_32(params->info.freqOffset)>>8;
937     section->reserved           = 0;
938
939     section->hdr.u.s3.ef        = params->info.ef;
940
941     // for network byte order (header, 8 bytes)
942     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
943
944     return (XRAN_STATUS_SUCCESS);
945 }
946 /**
947  * @brief Fill the section header of type 3 in C-Plane packet
948  *
949  * @param s3hdr
950  *  A pointer to the section header in the packet buffer
951  * @param params
952  *  A porinter to the information to generate a C-Plane packet
953  * @return
954  *  XRAN_STATUS_SUCCESS always
955  */
956 static int xran_prepare_section3_hdr(
957                 struct xran_cp_radioapp_section3_header *s3hdr,
958                 struct xran_cp_gen_params *params)
959
960 {
961     s3hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
962     s3hdr->frameStructure.fftSize   = params->hdr.fftSize;
963     s3hdr->frameStructure.uScs      = params->hdr.scs;
964     s3hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
965     s3hdr->udComp.udIqWidth         = params->hdr.iqWidth;
966     s3hdr->udComp.udCompMeth        = params->hdr.compMeth;
967
968     return (XRAN_STATUS_SUCCESS);
969 }
970
971 /**
972  * @brief add sections to C-Plane packet
973  *  Section type 1 and 3 are supported.
974  *
975  * @param mbuf
976  *  A pointer to the packet buffer
977  * @param params
978  *  A porinter to the information to generate a C-Plane packet
979  * @return
980  *  XRAN_STATUS_SUCCESS on success
981  *  XRAN_STATUS_INVALID_PARM if section type is not 1 or 3, or handler is NULL
982  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
983  */
984 int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
985 {
986   int i, ret, ext_flag;
987   uint32_t totalen;
988   void *section;
989   int section_size;
990   int (*xran_prepare_section_func)(void *section, void *params);
991
992
993     totalen = 0;
994     switch(params->sectionType) {
995         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
996             section_size                = sizeof(struct xran_cp_radioapp_section0);
997             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section0;
998             break;
999
1000         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1001             section_size                = sizeof(struct xran_cp_radioapp_section1);
1002             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section1;
1003             break;
1004
1005         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1006             section_size                = sizeof(struct xran_cp_radioapp_section3);
1007             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section3;
1008             break;
1009
1010         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1011         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1012         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1013         default:
1014             section_size                = 0;
1015             xran_prepare_section_func   = NULL;
1016             print_err("Section Type %d is not supported!", params->sectionType);
1017             return (XRAN_STATUS_INVALID_PARAM);
1018         }
1019
1020     if(unlikely(xran_prepare_section_func == NULL)) {
1021        print_err("Section Type %d is not supported!", params->sectionType);
1022        return (XRAN_STATUS_INVALID_PARAM);
1023        }
1024
1025     for(i=0; i<params->numSections; i++) {
1026         section = rte_pktmbuf_append(mbuf, section_size);
1027         if(section == NULL) {
1028             print_err("Fail to allocate the space for section[%d]!", i);
1029             return (XRAN_STATUS_RESOURCE);
1030             }
1031
1032         ret = xran_prepare_section_func((void *)section,
1033                             (void *)&params->sections[i]);
1034         if(ret < 0)
1035             return (ret);
1036         totalen += section_size;
1037
1038         if(params->sections[i].info.ef) {
1039             ret = xran_append_section_extensions(mbuf, &params->sections[i]);
1040             if(ret < 0)
1041                 return (ret);
1042             totalen += ret;
1043             }
1044         }
1045
1046     return (totalen);
1047 }
1048
1049 /**
1050  * @brief fill the information of a radio application header in a C-Plane packet
1051  *
1052  * @param apphdr
1053  *  A pointer to the application header in the packet buffer
1054  * @param params
1055  *  A porinter to the information to generate a C-Plane packet
1056  * @return
1057  *  XRAN_STATUS_SUCCESS on success
1058  *  XRAN_STATUS_INVALID_PARM if direction, slot index or symbold index is invalid
1059  */
1060 static inline int xran_prepare_radioapp_common_header(
1061                 struct xran_cp_radioapp_common_header *apphdr,
1062                 struct xran_cp_gen_params *params)
1063 {
1064
1065 #if (XRAN_STRICT_PARM_CHECK)
1066     if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
1067         print_err("Invalid direction!");
1068         return (XRAN_STATUS_INVALID_PARAM);
1069         }
1070     if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
1071         print_err("Invalid Slot ID!");
1072         return (XRAN_STATUS_INVALID_PARAM);
1073         }
1074     if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
1075         print_err("Invalid Symbol ID!");
1076         return (XRAN_STATUS_INVALID_PARAM);
1077         }
1078 #endif
1079
1080     apphdr->dataDirection   = params->dir;
1081     apphdr->payloadVer      = XRAN_PAYLOAD_VER;
1082     apphdr->filterIndex     = params->hdr.filterIdx;
1083     apphdr->frameId         = params->hdr.frameId;
1084     apphdr->subframeId      = params->hdr.subframeId;
1085     apphdr->slotId          = params->hdr.slotId;
1086     apphdr->startSymbolId   = params->hdr.startSymId;
1087     apphdr->numOfSections   = params->numSections;
1088     apphdr->sectionType     = params->sectionType;
1089
1090     /* radio app header has common parts of 4bytes for all section types */
1091     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1092
1093     return (XRAN_STATUS_SUCCESS);
1094 }
1095
1096 /**
1097  * @brief add a radio application header in a C-Plane packet
1098  *
1099  * @param mbuf
1100  *  A pointer to the packet buffer
1101  * @param params
1102  *  A porinter to the information to generate a C-Plane packet
1103  * @return
1104  *  The length of added section (>0) on success
1105  *  XRAN_STATUS_INVALID_PARM if section type is invalid, or handler is NULL
1106  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1107  */
1108 int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
1109 {
1110   int ret;
1111   uint32_t totalen;
1112   struct xran_cp_radioapp_common_header *apphdr;
1113   int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
1114
1115
1116 #if (XRAN_STRICT_PARM_CHECK)
1117     if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
1118         print_err("Invalid Section Type - %d", params->sectionType);
1119         return (XRAN_STATUS_INVALID_PARAM);
1120         }
1121 #endif
1122
1123     switch(params->sectionType) {
1124         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
1125             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;
1126             totalen = sizeof(struct xran_cp_radioapp_section0_header);
1127             break;
1128
1129         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
1130             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;
1131             totalen = sizeof(struct xran_cp_radioapp_section1_header);
1132             break;
1133
1134         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
1135             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;
1136             totalen = sizeof(struct xran_cp_radioapp_section3_header);
1137             break;
1138
1139         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
1140         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
1141         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
1142         default:
1143             print_err("Section Type %d is not supported!", params->sectionType);
1144             xran_prepare_radioapp_section_hdr_func = NULL;
1145             totalen = 0;
1146             return (XRAN_STATUS_INVALID_PARAM);
1147         }
1148
1149     apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
1150     if(unlikely(apphdr == NULL)) {
1151         print_err("Fail to reserve the space for radio application header!");
1152         return (XRAN_STATUS_RESOURCE);
1153         }
1154
1155     ret = xran_prepare_radioapp_common_header(apphdr, params);
1156     if(unlikely(ret < 0)) {
1157         return (ret);
1158         }
1159
1160     if(likely(xran_prepare_radioapp_section_hdr_func)) {
1161         totalen += xran_prepare_radioapp_section_hdr_func(apphdr, params);
1162         }
1163     else {
1164         print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
1165         return (XRAN_STATUS_INVALID_PARAM);
1166         }
1167
1168     return (totalen);
1169 }
1170
1171 /**
1172  * @brief Create a C-Plane packet
1173  *  Transport layer fragmentation is not supported.
1174  *
1175  * @ingroup xran_cp_pkt
1176  *
1177  * @param mbuf
1178  *  A pointer to the packet buffer
1179  * @param params
1180  *  A porinter to the information to generate a C-Plane packet
1181  * @param CC_ID
1182  *  Component Carrier ID for this C-Plane message
1183  * @param Ant_ID
1184  *  Antenna ID(RU Port ID) for this C-Plane message
1185  * @param seq_id
1186  *  Sequence ID for this C-Plane message
1187  * @return
1188  *  XRAN_STATUS_SUCCESS on success
1189  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
1190  *  XRAN_STATUS_INVALID_PARM if section type is invalid
1191  */
1192 int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
1193                         struct xran_cp_gen_params *params,
1194                         uint8_t CC_ID, uint8_t Ant_ID,
1195                         uint8_t seq_id)
1196 {
1197   int ret;
1198   uint32_t payloadlen;
1199   struct xran_ecpri_hdr *ecpri_hdr;
1200
1201
1202     payloadlen = xran_build_ecpri_hdr(mbuf, CC_ID, Ant_ID, seq_id, &ecpri_hdr);
1203
1204     ret = xran_append_radioapp_header(mbuf, params);
1205     if(ret < 0) {
1206         return (ret);
1207         }
1208     payloadlen += ret;
1209
1210     ret = xran_append_control_section(mbuf, params);
1211     if(ret < 0) {
1212         return (ret);
1213         }
1214     payloadlen += ret;
1215
1216     /* set payload length */
1217     ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
1218
1219     return (XRAN_STATUS_SUCCESS);
1220 }
1221
1222
1223 ///////////////////////////////////////
1224 // for RU emulation
1225 /**
1226  * @brief Parse a C-Plane packet (for RU emulation)
1227  *  Transport layer fragmentation is not supported.
1228  *
1229  * @ingroup xran_cp_pkt
1230  *
1231  * @param mbuf
1232  *  The pointer of the packet buffer to be parsed
1233  * @param params
1234  *  The pointer of structure to store the information of parsed packet
1235  * @param eaxc
1236  *  The pointer of sturcture to store the decomposed information of ecpriRtcid/ecpriPcid
1237  * @return
1238  *  XRAN_STATUS_SUCCESS on success
1239  *  XRAN_STATUS_INVALID_PACKET if failed to parse the packet
1240  */
1241 int xran_parse_cp_pkt(struct rte_mbuf *mbuf,
1242                     struct xran_cp_gen_params *result,
1243                     struct xran_recv_packet_info *pkt_info)
1244 {
1245   struct xran_ecpri_hdr *ecpri_hdr;
1246   struct xran_cp_radioapp_common_header *apphdr;
1247   int i, ret;
1248   int extlen;
1249
1250
1251     ret = xran_parse_ecpri_hdr(mbuf, &ecpri_hdr, pkt_info);
1252     if(ret < 0 && ecpri_hdr == NULL)
1253         return (XRAN_STATUS_INVALID_PACKET);
1254
1255     /* Process radio header. */
1256     apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
1257     if(apphdr == NULL) {
1258         print_err("Invalid packet - radio app hedaer!");
1259         return (XRAN_STATUS_INVALID_PACKET);
1260         }
1261
1262     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
1263
1264     if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {
1265         print_err("Invalid Payload version - %d", apphdr->payloadVer);
1266         ret = XRAN_STATUS_INVALID_PACKET;
1267         }
1268
1269     result->dir             = apphdr->dataDirection;
1270     result->hdr.filterIdx   = apphdr->filterIndex;
1271     result->hdr.frameId     = apphdr->frameId;
1272     result->hdr.subframeId  = apphdr->subframeId;
1273     result->hdr.slotId      = apphdr->slotId;
1274     result->hdr.startSymId  = apphdr->startSymbolId;
1275     result->sectionType     = apphdr->sectionType;
1276     result->numSections     = apphdr->numOfSections;
1277
1278 #if 0
1279     printf("[CP%5d] eAxC[%d:%d:%02d:%02d] %s seq[%03d-%03d-%d] sec[%d-%d] frame[%3d-%2d-%2d] sym%02d\n",
1280         pkt_info->payload_len,
1281         pkt_info->eaxc.cuPortId, pkt_info->eaxc.bandSectorId,
1282         pkt_info->eaxc.ccId, pkt_info->eaxc.ruPortId,
1283         result->dir?"DL":"UL",
1284         pkt_info->seq_id, pkt_info->subseq_id, pkt_info->ebit,
1285         result->sectionType, result->numSections,
1286         result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1287         result->hdr.startSymId
1288         );
1289 #endif
1290
1291     switch(apphdr->sectionType) {
1292         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
1293             {
1294             struct xran_cp_radioapp_section0_header *hdr;
1295             struct xran_cp_radioapp_section0 *section;
1296
1297                 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
1298
1299                 result->hdr.fftSize     = rte_be_to_cpu_16(hdr->timeOffset);
1300                 result->hdr.scs         = hdr->frameStructure.fftSize;
1301                 result->hdr.timeOffset  = hdr->frameStructure.uScs;
1302                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1303                 //hdr->reserved;    /* should be zero */
1304
1305                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
1306                 if(section == NULL) {
1307                     print_err("Invalid packet 0 - radio app hedaer!");
1308                     return (XRAN_STATUS_INVALID_PACKET);
1309                     }
1310                 for(i=0; i<result->numSections; i++) {
1311                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1312
1313                     result->sections[i].info.type       = apphdr->sectionType;
1314                     result->sections[i].info.id         = section->hdr.sectionId;
1315                     result->sections[i].info.rb         = section->hdr.rb;
1316                     result->sections[i].info.symInc     = section->hdr.symInc;
1317                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1318                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1319                     result->sections[i].info.numSymbol  = section->hdr.u.s0.numSymbol;
1320                     result->sections[i].info.reMask     = section->hdr.u.s0.reMask;
1321                     //section->hdr.u.s0.reserved;   /* should be zero */
1322
1323                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
1324                     if(section == NULL) {
1325                         print_err("Invalid packet 0 - number of section [%d:%d]!",
1326                                     result->numSections, i);
1327                         result->numSections = i;
1328                         ret = XRAN_STATUS_INVALID_PACKET;
1329                         break;
1330                         }
1331                     }
1332             }
1333             break;
1334
1335         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
1336             {
1337             struct xran_cp_radioapp_section1_header *hdr;
1338             struct xran_cp_radioapp_section1 *section;
1339
1340                 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
1341
1342                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1343                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
1344
1345                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
1346                 if(section == NULL) {
1347                     print_err("Invalid packet 1 - radio app hedaer!");
1348                     return (XRAN_STATUS_INVALID_PACKET);
1349                     }
1350
1351                 for(i=0; i<result->numSections; i++) {
1352                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1353
1354                     result->sections[i].info.type       = apphdr->sectionType;
1355                     result->sections[i].info.id         = section->hdr.sectionId;
1356                     result->sections[i].info.rb         = section->hdr.rb;
1357                     result->sections[i].info.symInc     = section->hdr.symInc;
1358                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1359                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1360                     result->sections[i].info.numSymbol  = section->hdr.u.s1.numSymbol;
1361                     result->sections[i].info.reMask     = section->hdr.u.s1.reMask;
1362                     result->sections[i].info.beamId     = section->hdr.u.s1.beamId;
1363                     result->sections[i].info.ef         = section->hdr.u.s1.ef;
1364
1365                     if(section->hdr.u.s1.ef) {
1366                         // TODO: handle section extension
1367                         extlen = 0;
1368                         }
1369                     else extlen = 0;
1370
1371                     section = (void *)rte_pktmbuf_adj(mbuf,
1372                                     sizeof(struct xran_cp_radioapp_section1)+extlen);
1373                     if(section == NULL) {
1374                         print_err("Invalid packet 1 - number of section [%d:%d]!",
1375                                     result->numSections, i);
1376                         result->numSections = i;
1377                         ret = XRAN_STATUS_INVALID_PACKET;
1378                         break;
1379                         }
1380                     }
1381             }
1382             break;
1383
1384         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
1385             {
1386             struct xran_cp_radioapp_section3_header *hdr;
1387             struct xran_cp_radioapp_section3 *section;
1388
1389                 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
1390
1391                 result->hdr.timeOffset  = rte_be_to_cpu_16(hdr->timeOffset);
1392                 result->hdr.scs         = hdr->frameStructure.uScs;
1393                 result->hdr.fftSize     = hdr->frameStructure.fftSize;
1394                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1395                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1396                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
1397
1398                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
1399                 if(section == NULL) {
1400                     print_err("Invalid packet 3 - radio app hedaer!");
1401                     return (XRAN_STATUS_INVALID_PACKET);
1402                     }
1403
1404                 for(i=0; i<result->numSections; i++) {
1405                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1406
1407                     result->sections[i].info.type       = apphdr->sectionType;
1408                     result->sections[i].info.id         = section->hdr.sectionId;
1409                     result->sections[i].info.rb         = section->hdr.rb;
1410                     result->sections[i].info.symInc     = section->hdr.symInc;
1411                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1412                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1413                     result->sections[i].info.numSymbol  = section->hdr.u.s3.numSymbol;
1414                     result->sections[i].info.reMask     = section->hdr.u.s3.reMask;
1415                     result->sections[i].info.beamId     = section->hdr.u.s3.beamId;
1416                     result->sections[i].info.ef         = section->hdr.u.s3.ef;
1417                     result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
1418
1419                     if(section->reserved) {
1420                         print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);
1421                         ret = XRAN_STATUS_INVALID_PACKET;
1422                         }
1423
1424                     if(section->hdr.u.s3.ef) {
1425                         // TODO: handle section extension
1426                         extlen = 0;
1427                         }
1428                     else extlen = 0;
1429
1430                     section = (void *)rte_pktmbuf_adj(mbuf,
1431                                     sizeof(struct xran_cp_radioapp_section3)+extlen);
1432                     if(section == NULL) {
1433                         print_err("Invalid packet 3 - number of section [%d:%d]!",
1434                                     result->numSections, i);
1435                         result->numSections = i;
1436                         ret = XRAN_STATUS_INVALID_PACKET;
1437                         break;
1438                         }
1439                     }
1440             }
1441             break;
1442
1443         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
1444         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
1445         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
1446         default:
1447             ret = XRAN_STATUS_INVALID_PARAM;
1448             print_err("Non-supported Section Type - %d", apphdr->sectionType);
1449         }
1450
1451 #if 0
1452     printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
1453             result->dir?"DL":"UL",
1454             result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1455             result->sectionType, result->numSections,
1456             result->hdr.startSymId,
1457             result->hdr.filterIdx,
1458             result->hdr.iqWidth, result->hdr.compMeth);
1459
1460     for(i=0; i<result->numSections; i++) {
1461         printf("  >> %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02d numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
1462             i, result->sections[i].info.id,
1463             result->sections[i].info.rb,
1464             result->sections[i].info.symInc, result->sections[i].info.numSymbol,
1465             result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
1466             result->sections[i].info.reMask,
1467             result->sections[i].info.beamId,
1468             result->sections[i].info.freqOffset,
1469             result->sections[i].info.ef);
1470 //                    result->sections[i].info.type
1471         }
1472 #endif
1473
1474     return(ret);
1475 }
1476