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