Front Haul Interface Library first seed code contribution
[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 /**
21  * @brief This file provides the API functions to build Control Plane Messages
22  *      for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01.
23  *
24  * @file xran_cp_api.c
25  * @ingroup group_lte_source_xran
26  * @author Intel Corporation
27  *
28  **/
29
30 #include <rte_branch_prediction.h>
31
32 #include "xran_common.h"
33 #include "xran_transport.h"
34 #include "xran_cp_api.h"
35 #include "xran_hash.h"
36 #include "xran_printf.h"
37
38
39 struct xran_sectioninfo_db {
40     uint32_t    max_num;
41     uint32_t    cur_index;
42 #if defined(XRAN_CP_USES_HASHTABLE)
43     struct rte_hash *hash;
44 #endif
45     struct xran_section_info *list;
46     };
47
48
49 static struct xran_sectioninfo_db *sectiondb[XRAN_DIR_MAX];
50
51 int xran_cp_init_sectiondb(void *pHandle)
52 {
53   int i, j, k;
54   uint32_t size;
55   uint16_t cid;
56   struct xran_sectioninfo_db *ptr;
57   uint8_t num_eAxc;
58
59
60 #if !defined(PRACH_USES_SHARED_PORT)
61     num_eAxc = xran_get_num_eAxc(pHandle) * 2;
62 #else
63     num_eAxc = xran_get_num_eAxc(pHandle);
64 #endif
65
66     for(i=0; i < XRAN_DIR_MAX; i++) {
67         size = (xran_get_num_cc(pHandle) * num_eAxc * sizeof(struct xran_sectioninfo_db));
68         print_log("Allocation Size for Section DB : %d (%dx%dx%ld)", size
69                     , xran_get_num_cc(pHandle)
70                     , num_eAxc
71                     , sizeof(struct xran_sectioninfo_db));
72         sectiondb[i] = malloc(size);
73
74         if(sectiondb[i] == NULL) {
75             print_err("Allocation Failed for Section DB!");
76             return (-XRAN_ERRCODE_OUTOFMEMORY);
77             }
78
79         for(j=0; j < xran_get_num_cc(pHandle); j++) {         // CC
80             for(k=0; k < num_eAxc; k++) {   // antenna
81                 ptr = sectiondb[i] + num_eAxc*j + k;
82
83                 ptr->max_num = xran_get_max_sections(pHandle);
84                 ptr->cur_index = 0;
85
86                 // allicate array to store section information
87                 size = sizeof(struct xran_section_info)*xran_get_max_sections(pHandle);
88                 print_log("Allocation Size for list : %d (%ldx%d)", size,
89                             sizeof(struct xran_section_info),
90                             xran_get_max_sections(pHandle));
91                 ptr->list = malloc(size);
92                 if(ptr-> list  == NULL) {
93                     print_err("Allocation Failed for Section DB!");
94                     return (-XRAN_ERRCODE_OUTOFMEMORY);
95                     }
96
97 #if defined(XRAN_CP_USES_HASHTABLE)
98                 // Create hash table for section information
99                 cid = rte_be_to_cpu_16(xran_compose_cid(xran_get_llscuid(pHandle), xran_get_sectorid(pHandle), j, k));
100                 print_log("Creating hash for %04X", cid);
101                 ptr->hash = xran_section_init_hash(i, cid, xran_get_max_sections(pHandle));
102 #endif
103                 }
104             }
105         }
106
107     return (XRAN_ERRCODE_OK);
108 }
109
110 int xran_cp_free_sectiondb(void *pHandle)
111 {
112   int i, j, k;
113   uint32_t size;
114   struct xran_sectioninfo_db *ptr;
115   uint8_t num_eAxc;
116
117 #if !defined(PRACH_USES_SHARED_PORT)
118     num_eAxc = xran_get_num_eAxc(pHandle) * 2;
119 #else
120     num_eAxc = xran_get_num_eAxc(pHandle);
121 #endif
122
123     for(i=0; i < XRAN_DIR_MAX; i++) {
124         for(j=0; j < xran_get_num_cc(pHandle); j++) {         // CC
125             for(k=0; k < num_eAxc; k++) {   // antenna
126                 ptr = sectiondb[i] + num_eAxc*j + k;
127
128 #if defined(XRAN_CP_USES_HASHTABLE)
129                 xran_section_free_hash(ptr->hash);
130 #endif
131                 if(ptr->list != NULL)
132                     free(ptr->list);
133                 else print_err("list is NULL");
134                 }
135             }
136         if(sectiondb[i] != NULL)
137             free(sectiondb[i]);
138         else print_err("sectiondb[%d] is NULL", i);
139         }
140
141     return (XRAN_ERRCODE_OK);
142 }
143
144 static struct xran_sectioninfo_db *xran_get_section_db(void *pHandle,
145         uint8_t dir, uint8_t cc_id, uint8_t ruport_id)
146 {
147   struct xran_sectioninfo_db *ptr;
148   uint8_t num_eAxc;
149
150     if(unlikely(dir>=XRAN_DIR_MAX)) {
151         print_err("Invalid direction - %d", dir);
152         return (NULL);
153         }
154
155     if(unlikely(cc_id >= xran_get_num_cc(pHandle))) {
156         print_err("Invalid CC id - %d", cc_id);
157         return (NULL);
158         }
159
160 #if !defined(PRACH_USES_SHARED_PORT)
161     num_eAxc = xran_get_num_eAxc(pHandle) * 2;
162 #else
163     num_eAxc = xran_get_num_eAxc(pHandle);
164 #endif
165
166     if(unlikely(ruport_id >= num_eAxc)) {
167         print_err("Invalid eAxC id - %d", ruport_id);
168         return (NULL);
169         }
170
171     ptr = sectiondb[dir] + xran_get_num_eAxc(pHandle)*cc_id + ruport_id;
172
173     return(ptr);
174 }
175
176 static struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index)
177 {
178     if(unlikely(ptr == NULL))
179         return (NULL);
180
181     if(unlikely(ptr->max_num < index)) {
182         print_err("Index is out of range - %d", index);
183         return (NULL);
184         }
185
186     return(&(ptr->list[index]));
187 }
188
189 int xran_cp_add_section_info(void *pHandle,
190         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
191         uint8_t subframe_id, uint8_t slot_id,
192         struct xran_section_info *info)
193 {
194   struct xran_sectioninfo_db *ptr;
195   struct xran_section_info *list;
196
197     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
198     if(unlikely(ptr == NULL)) {
199         return (-XRAN_ERRCODE_INVALIDPARAM);
200         }
201
202     if(unlikely(ptr->cur_index >= ptr->max_num)) {
203         print_err("No more space to add section information!");
204         return (-XRAN_ERRCODE_OUTOFMEMORY);
205         }
206
207     list = xran_get_section_info(ptr, ptr->cur_index);
208
209     rte_memcpy(list, info, sizeof(struct xran_section_info));
210 #if defined(XRAN_CP_USES_HASHTABLE)
211     xran_section_add_hash(ptr->hash, info->id, ptr->cur_index);
212 #endif
213
214     ptr->cur_index++;
215
216     return (XRAN_ERRCODE_OK);
217 }
218
219 int xran_cp_add_multisection_info(void *pHandle,
220         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
221         uint8_t subframe_id, uint8_t slot_id,
222         uint8_t num_sections, struct xran_section_gen_info *gen_info)
223 {
224   int i;
225   struct xran_sectioninfo_db *ptr;
226   struct xran_section_info *list;
227
228     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
229     if(unlikely(ptr == NULL)) {
230         return (-XRAN_ERRCODE_INVALIDPARAM);
231         }
232
233     if(unlikely(ptr->cur_index >= (ptr->max_num+num_sections))) {
234         print_err("No more space to add section information!");
235         return (-XRAN_ERRCODE_OUTOFMEMORY);
236         }
237
238     list = xran_get_section_info(ptr, ptr->cur_index);
239
240     for(i=0; i<num_sections; i++) {
241         rte_memcpy(&list[i], &gen_info[i].info, sizeof(struct xran_section_info));
242 #if defined(XRAN_CP_USES_HASHTABLE)
243         xran_section_add_hash(ptr->hash, gen_info[i].info.id, ptr->cur_index);
244 #endif
245         ptr->cur_index++;
246         }
247
248     return (XRAN_ERRCODE_OK);
249 }
250
251 struct xran_section_info *xran_cp_find_section_info(void *pHandle,
252         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
253         uint8_t subframe_id, uint8_t slot_id,
254         uint16_t section_id)
255 {
256   int index;
257   struct xran_sectioninfo_db *ptr;
258
259
260     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
261     if(unlikely(ptr == NULL))
262         return (NULL);
263
264 #if defined(XRAN_CP_USES_HASHTABLE)
265     index = xran_section_lookup(ptr->hash, section_id);
266     if(unlikely(index > ptr->max_num)) {
267         print_err("Invalid index - %d", index);
268         return (NULL);
269         }
270
271     if(index < 0) {
272         print_dbg("No section ID in the list - %d", section_id);
273         return (NULL);
274         }
275
276     return (xran_get_section_info(ptr, index));
277 #else
278     for(index=0; index<ptr->cur_index; index++) {
279         if(ptr->list[index].id == section_id) {
280             print_dbg("Found section info %04X", section_id);
281             return (xran_get_section_info(ptr, index));
282             }
283         }
284
285     print_dbg("No section ID in the list - %d", section_id);
286     return (NULL);
287 #endif
288
289 }
290
291 struct xran_section_info *xran_cp_iterate_section_info(void *pHandle,
292         uint8_t dir, uint8_t cc_id, uint8_t ruport_id,
293         uint8_t subframe_id, uint8_t slot_id, uint32_t *next)
294 {
295   int index;
296   struct xran_sectioninfo_db *ptr;
297
298
299     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
300     if(unlikely(ptr == NULL))
301         return (NULL);
302
303 #if defined(XRAN_CP_USES_HASHTABLE)
304     index = xran_section_iterate(ptr->hash, next);
305     if(unlikely(index > ptr->max_num)) {
306         print_err("Invalid index - %d", index);
307         return (NULL);
308         }
309
310     if(index < 0) {
311         print_dbg("No section ID in the list - %d", section_id);
312         return (NULL);
313         }
314
315     return (xran_get_section_info(ptr, index));
316 #else
317     index = *next;
318     if(*next < ptr->cur_index) {
319         (*next)++;
320         return (xran_get_section_info(ptr, index));
321         }
322     else 
323         print_dbg("No more sections in the list");
324
325     return (NULL);
326 #endif
327 }
328
329 int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id)
330 {
331   int i, index;
332   struct xran_sectioninfo_db *ptr;
333
334
335     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
336     if(unlikely(ptr == NULL))
337         return (-1);
338
339     return (ptr->cur_index);
340 }
341
342 int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id)
343 {
344   struct xran_sectioninfo_db *ptr;
345
346     ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id);
347     if(unlikely(ptr == NULL)) {
348         return (-XRAN_ERRCODE_INVALIDPARAM);
349         }
350
351     ptr->cur_index = 0;
352 #if defined(XRAN_CP_USES_HASHTABLE)
353     xran_section_reset_hash(ptr->hash);
354 #endif
355
356     return (XRAN_ERRCODE_OK);
357 }
358
359 int xran_dump_sectiondb(void)
360 {
361     // TODO:
362     return (0);
363 }
364
365
366 // Cyclic Prefix Length 5.4.4.14
367 // CP_length = cpLength * Ts * 2^u,  Ts = 1/30.72MHz, if u is N/A, it shall be zero
368 #define CPLEN_TS           (30720000)
369 inline uint16_t xran_get_cplength(int cpLength, int uval)    // uval = -1 for N/A
370 {
371     return ((cpLength * ((uval<0)?0:(2<<uval))) / (CPLEN_TS));
372 }
373
374 // Frequency offset 5.4.5.11
375 // frequency_offset = freqOffset * SCS * 0.5
376 inline int32_t xran_get_freqoffset(int freqOffset, int scs)
377 {
378     return ((freqOffset * scs)>>1);
379 }
380
381
382 /**
383  * @brief Fill the section body of type 0 in C-Plane packet
384  *
385  * @param section
386  *  A pointer to the section in the packet buffer
387  * @param params
388  *  A porinter to the information to generate a C-Plane packet
389  * @return
390  *  0 on success; non zero on failure
391  */
392 static int xran_prepare_section0(
393                 struct xran_cp_radioapp_section0 *section,
394                 struct xran_section_gen_info *params)
395 {
396 #if (XRAN_STRICT_PARM_CHECK)
397     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
398         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
399         return (-XRAN_ERRCODE_INVALIDPARAM);
400         }
401 #endif
402
403     section->hdr.sectionId  = params->info.id;
404     section->hdr.rb         = params->info.rb;
405     section->hdr.symInc     = params->info.symInc;
406     section->hdr.startPrbc  = params->info.startPrbc;
407     section->hdr.numPrbc    = params->info.numPrbc;
408
409     section->hdr.u.s0.reMask    = params->info.reMask;
410     section->hdr.u.s0.numSymbol = params->info.numSymbol;
411     section->hdr.u.s0.reserved  = 0;
412
413     // for network byte order
414     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
415
416     return (XRAN_ERRCODE_OK);
417 }
418 /**
419  * @brief Fill the section header of type 0 in C-Plane packet
420  *
421  * @param s0hdr
422  *  A pointer to the section header in the packet buffer
423  * @param params
424  *  A porinter to the information to generate a C-Plane packet
425  * @return
426  *  0 on success; non zero on failure
427  */
428 static int xran_prepare_section0_hdr(
429                 struct xran_cp_radioapp_section0_header *s0hdr,
430                 struct xran_cp_gen_params *params)
431
432 {
433     s0hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
434     s0hdr->frameStructure.fftSize   = params->hdr.fftSize;
435     s0hdr->frameStructure.uScs      = params->hdr.scs;
436     s0hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
437     s0hdr->reserved                 = 0;
438
439     return (XRAN_ERRCODE_OK);
440 }
441
442 /**
443  * @brief Fill the section body of type 1 in C-Plane packet
444  *  Extension is not supported.
445  *
446  * @param section
447  *  A pointer to the section header in the packet buffer
448  * @param params
449  *  A porinter to the information to generate a C-Plane packet
450  * @return
451  *  0 on success; non zero on failure
452  */
453 static int xran_prepare_section1(
454                 struct xran_cp_radioapp_section1 *section,
455                 struct xran_section_gen_info *params)
456 {
457 #if (XRAN_STRICT_PARM_CHECK)
458     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
459         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
460         return (-XRAN_ERRCODE_INVALIDPARAM);
461         }
462 #endif
463
464     section->hdr.sectionId      = params->info.id;
465     section->hdr.rb             = params->info.rb;
466     section->hdr.symInc         = params->info.symInc;
467     section->hdr.startPrbc      = params->info.startPrbc;
468     section->hdr.numPrbc        = params->info.numPrbc;
469
470     section->hdr.u.s1.reMask    = params->info.reMask;
471     section->hdr.u.s1.numSymbol = params->info.numSymbol;
472     section->hdr.u.s1.beamId    = params->info.beamId;
473
474     if(params->info.ef) {
475         // TODO: need to handle extension
476         print_err("Extension is not supported!");
477         section->hdr.u.s1.ef         = 0;
478 //        section->hdr.u.s1.ef         = params->info.ef;
479         }
480     else
481         section->hdr.u.s1.ef         = 0;
482
483     // for network byte order
484     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
485
486     return (XRAN_ERRCODE_OK);
487 }
488 /**
489  * @brief Fill the section header of type 1 in C-Plane packet
490  *
491  * @param s1hdr
492  *  A pointer to the section header in the packet buffer
493  * @param params
494  *  A porinter to the information to generate a C-Plane packet
495  * @return
496  *  0 on success; non zero on failure
497  */
498 static int xran_prepare_section1_hdr(
499                 struct xran_cp_radioapp_section1_header *s1hdr,
500                 struct xran_cp_gen_params *params)
501 {
502     s1hdr->udComp.udIqWidth         = params->hdr.iqWidth;
503     s1hdr->udComp.udCompMeth        = params->hdr.compMeth;
504     s1hdr->reserved                 = 0;
505
506     return (XRAN_ERRCODE_OK);
507 }
508
509 /**
510  * @brief Fill the section body of type 3 in C-Plane packet
511  *  Extension is not supported.
512  *
513  * @param section
514  *  A pointer to the section header in the packet buffer
515  * @param params
516  *  A porinter to the information to generate a C-Plane packet
517  * @return
518  *  0 on success; non zero on failure
519  */
520 static int xran_prepare_section3(
521                 struct xran_cp_radioapp_section3 *section,
522                 struct xran_section_gen_info *params)
523 {
524 #if (XRAN_STRICT_PARM_CHECK)
525     if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) {
526         print_err("Invalid number of Symbols - %d", params->info.numSymbol);
527         return (-XRAN_ERRCODE_INVALIDPARAM);
528         }
529 #endif
530
531     section->hdr.sectionId      = params->info.id;
532     section->hdr.rb             = params->info.rb;
533     section->hdr.symInc         = params->info.symInc;
534     section->hdr.startPrbc      = params->info.startPrbc;
535     section->hdr.numPrbc        = params->info.numPrbc;
536
537     section->hdr.u.s3.reMask    = params->info.reMask;
538     section->hdr.u.s3.numSymbol = params->info.numSymbol;
539     section->hdr.u.s3.beamId    = params->info.beamId;
540
541     section->freqOffset         = rte_cpu_to_be_32(params->info.freqOffset)>>8;
542     section->reserved           = 0;
543
544     if(params->info.ef) {
545         // TODO: need to handle extension
546         print_err("Extension is not supported!");
547         section->hdr.u.s3.ef         = 0;
548 //        section->hdr.u.s3.ef         = params->info.ef;
549         }
550     else
551         section->hdr.u.s3.ef         = 0;
552
553     // for network byte order (header, 8 bytes)
554     *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section));
555
556     return (XRAN_ERRCODE_OK);
557 }
558 /**
559  * @brief Fill the section header of type 3 in C-Plane packet
560  *
561  * @param s3hdr
562  *  A pointer to the section header in the packet buffer
563  * @param params
564  *  A porinter to the information to generate a C-Plane packet
565  * @return
566  *  0 on success; non zero on failure
567  */
568 static int xran_prepare_section3_hdr(
569                 struct xran_cp_radioapp_section3_header *s3hdr,
570                 struct xran_cp_gen_params *params)
571
572 {
573     s3hdr->timeOffset               = rte_cpu_to_be_16(params->hdr.timeOffset);
574     s3hdr->frameStructure.fftSize   = params->hdr.fftSize;
575     s3hdr->frameStructure.uScs      = params->hdr.scs;
576     s3hdr->cpLength                 = rte_cpu_to_be_16(params->hdr.cpLength);
577     s3hdr->udComp.udIqWidth         = params->hdr.iqWidth;
578     s3hdr->udComp.udCompMeth        = params->hdr.compMeth;
579
580     return (XRAN_ERRCODE_OK);
581 }
582
583 /**
584  * @brief add sections to C-Plane packet
585  *  Section type 1 and 3 are supported.
586  *
587  * @param mbuf
588  *  A pointer to the packet buffer
589  * @param params
590  *  A porinter to the information to generate a C-Plane packet
591  * @return
592  *  0 on success; non zero on failure
593  */
594 int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
595 {
596   int i, ret;
597   uint32_t totalen;
598   void *section;
599   int section_size;
600   int (*xran_prepare_section_func)(void *section, void *params);
601
602
603     totalen = 0;
604     switch(params->sectionType) {
605         case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */
606             section_size                = sizeof(struct xran_cp_radioapp_section0);
607             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section0;
608             break;
609
610         case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */
611             section_size                = sizeof(struct xran_cp_radioapp_section1);
612             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section1;
613             break;
614
615         case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */
616             section_size                = sizeof(struct xran_cp_radioapp_section3);
617             xran_prepare_section_func   = (int (*)(void *, void *))xran_prepare_section3;
618             break;
619
620         case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */
621         case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */
622         case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */
623         default:
624             section_size                = 0;
625             xran_prepare_section_func   = NULL;
626             print_err("Section Type %d is not supported!", params->sectionType);
627             return (-XRAN_ERRCODE_INVALIDPARAM);
628         }
629
630     if(unlikely(xran_prepare_section_func == NULL)) {
631        print_err("Section Type %d is not supported!", params->sectionType);
632        return (-XRAN_ERRCODE_INVALIDPARAM);
633        }
634
635     for(i=0; i<params->numSections; i++) {
636         section = rte_pktmbuf_append(mbuf, section_size);
637         if(section == NULL) {
638             print_err("Fail to allocate the space for section[%d]!", i);
639             return (-XRAN_ERRCODE_OUTOFMEMORY);
640             }
641
642         if(unlikely(xran_prepare_section_func((void *)section,
643                             (void *)&params->sections[i]) < 0)) {
644             return (-XRAN_ERRCODE_INVALIDPARAM);
645             }
646
647         totalen += section_size;
648         }
649
650     return (totalen);
651 }
652
653 /**
654  * @brief fill the information of a radio application header in a C-Plane packet
655  *
656  * @param apphdr
657  *  A pointer to the application header in the packet buffer
658  * @param params
659  *  A porinter to the information to generate a C-Plane packet
660  * @return
661  *  0 on success; non zero on failure
662  */
663 static inline int xran_prepare_radioapp_common_header(
664                 struct xran_cp_radioapp_common_header *apphdr,
665                 struct xran_cp_gen_params *params)
666 {
667
668 #if (XRAN_STRICT_PARM_CHECK)
669     if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) {
670         print_err("Invalid direction!");
671         return (-XRAN_ERRCODE_INVALIDPARAM);
672         }
673     if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) {
674         print_err("Invalid Slot ID!");
675         return (-XRAN_ERRCODE_INVALIDPARAM);
676         }
677     if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) {
678         print_err("Invalid Symbol ID!");
679         return (-XRAN_ERRCODE_INVALIDPARAM);
680         }
681 #endif
682
683     apphdr->dataDirection   = params->dir;
684     apphdr->payloadVer      = XRAN_PAYLOAD_VER;
685     apphdr->filterIndex     = params->hdr.filterIdx;
686     apphdr->frameId         = params->hdr.frameId;
687     apphdr->subframeId      = params->hdr.subframeId;
688     apphdr->slotId          = params->hdr.slotId;
689     apphdr->startSymbolId   = params->hdr.startSymId;
690     apphdr->numOfSections   = params->numSections;
691     apphdr->sectionType     = params->sectionType;
692
693     // radio app header has common parts of 4bytes for all section types
694     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
695
696     return (XRAN_ERRCODE_OK);
697 }
698
699 /**
700  * @brief add a radio application header in a C-Plane packet
701  *
702  * @param mbuf
703  *  A pointer to the packet buffer
704  * @param params
705  *  A porinter to the information to generate a C-Plane packet
706  * @return
707  *  0 on success; non zero on failure
708  */
709 int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params)
710 {
711   int ret;
712   uint32_t totalen;
713   struct xran_cp_radioapp_common_header *apphdr;
714   int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params);
715
716
717 #if (XRAN_STRICT_PARM_CHECK)
718     if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) {
719         print_err("Invalid Section Type - %d", params->sectionType);
720         return (-XRAN_ERRCODE_INVALIDPARAM);
721         }
722 #endif
723
724     switch(params->sectionType) {
725         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
726             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr;
727             totalen = sizeof(struct xran_cp_radioapp_section0_header);
728             break;
729
730         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
731             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr;
732             totalen = sizeof(struct xran_cp_radioapp_section1_header);
733             break;
734
735         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
736             xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr;
737             totalen = sizeof(struct xran_cp_radioapp_section3_header);
738             break;
739
740         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
741         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
742         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
743         default:
744             print_err("Section Type %d is not supported!", params->sectionType);
745             xran_prepare_radioapp_section_hdr_func = NULL;
746             totalen = 0;
747             return (-XRAN_ERRCODE_INVALIDPARAM);
748         }
749
750     apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen);
751     if(unlikely(apphdr == NULL)) {
752         print_err("Fail to reserve the space for radio application header!");
753         return (-XRAN_ERRCODE_OUTOFMEMORY);
754         }
755
756     ret = xran_prepare_radioapp_common_header(apphdr, params);
757     if(unlikely(ret < 0)) {
758         return (ret);
759         }
760
761     if(likely(xran_prepare_radioapp_section_hdr_func)) {
762         xran_prepare_radioapp_section_hdr_func(apphdr, params);
763         }
764     else {
765         print_err("xran_prepare_radioapp_section_hdr_func is NULL!");
766         return (-XRAN_ERRCODE_INVALIDPARAM);
767         }
768
769     return (totalen);
770 }
771
772 /**
773  * @brief Create a C-Plane packet
774  *  Transport layer fragmentation is not supported.
775  *
776  * @ingroup xran_cp_pkt
777  *
778  * @param mbuf
779  *  A pointer to the packet buffer
780  * @param params
781  *  A porinter to the information to generate a C-Plane packet
782  * @param CC_ID
783  *  Component Carrier ID for this C-Plane message
784  * @param Ant_ID
785  *  Antenna ID(RU Port ID) for this C-Plane message
786  * @param seq_id
787  *  Sequence ID for this C-Plane message
788  * @return
789  *  0 on success; non zero on failure
790  */
791 int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf,
792                         struct xran_cp_gen_params *params,
793                         uint8_t CC_ID, uint8_t Ant_ID,
794                         uint8_t seq_id)
795 {
796   int ret;
797   uint32_t payloadlen;
798   struct xran_ecpri_hdr *ecpri_hdr;
799
800
801     ecpri_hdr = (struct xran_ecpri_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr));
802     if(unlikely(ecpri_hdr == NULL)) {
803         print_err("Fail to allocate the space for eCPRI hedaer!");
804         return (-XRAN_ERRCODE_OUTOFMEMORY);
805         }
806
807     ecpri_hdr->ecpri_ver            = XRAN_ECPRI_VER;
808     ecpri_hdr->ecpri_resv           = 0;     // should be zero
809     ecpri_hdr->ecpri_concat         = 0;
810     ecpri_hdr->ecpri_mesg_type      = ECPRI_RT_CONTROL_DATA;
811     ecpri_hdr->ecpri_xtc_id         = xran_compose_cid(0, 0, CC_ID, Ant_ID);
812     ecpri_hdr->ecpri_seq_id.seq_id  = seq_id;
813
814     /* TODO: Transport layer fragmentation is not supported */
815     ecpri_hdr->ecpri_seq_id.sub_seq_id  = 0;
816     ecpri_hdr->ecpri_seq_id.e_bit       = 1;
817
818     payloadlen = 0;
819
820     ret = xran_append_radioapp_header(mbuf, params);
821     if(ret < 0) {
822         return (ret);
823         }
824     payloadlen += ret;
825
826     ret = xran_append_control_section(mbuf, params);
827     if(ret < 0) {
828         return (ret);
829         }
830     payloadlen += ret;
831
832 //    printf("Total Payload length = %d\n", payloadlen);
833     ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(payloadlen);
834
835     return (XRAN_ERRCODE_OK);
836 }
837
838 ///////////////////////////////////////
839 // for Debug
840 int xran_parse_cp_pkt(struct rte_mbuf *mbuf, struct xran_cp_gen_params *result)
841 {
842   struct xran_ecpri_hdr *ecpri_hdr;
843   struct xran_cp_radioapp_common_header *apphdr;
844   int i, ret;
845   int extlen;
846
847
848     ret = 0;
849     ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *);
850     if(ecpri_hdr == NULL) {
851         print_err("Invalid packet - eCPRI hedaer!");
852         return (-XRAN_ERRCODE_INVALIDPACKET);
853         }
854
855     /* Process eCPRI header. */
856     if(ecpri_hdr->ecpri_ver != XRAN_ECPRI_VER) {
857         print_err("Invalid eCPRI version - %d", ecpri_hdr->ecpri_ver);
858         ret = -XRAN_ERRCODE_INVALIDPACKET;
859         }
860
861     if(ecpri_hdr->ecpri_resv != 0) {
862         print_err("Invalid reserved field - %d", ecpri_hdr->ecpri_resv);
863         ret = -XRAN_ERRCODE_INVALIDPACKET;
864         }
865
866     if(ecpri_hdr->ecpri_mesg_type != ECPRI_RT_CONTROL_DATA) {
867         print_err("Not C-Plane Message - %d", ecpri_hdr->ecpri_mesg_type);
868         ret = -XRAN_ERRCODE_INVALIDPACKET;
869         }
870 #if 0
871     printf("[CPlane] [%04X:%03d-%3d-%d] len=%5d\n",
872             rte_be_to_cpu_16(ecpri_hdr->ecpri_xtc_id),
873             ecpri_hdr->ecpri_seq_id.seq_id, ecpri_hdr->ecpri_seq_id.sub_seq_id,
874             ecpri_hdr->ecpri_seq_id.e_bit,
875             rte_be_to_cpu_16(ecpri_hdr->ecpri_payl_size));
876 #endif
877
878     /* Process radio header. */
879     apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr));
880     if(apphdr == NULL) {
881         print_err("Invalid packet - radio app hedaer!");
882         return (-XRAN_ERRCODE_INVALIDPACKET);
883         }
884
885     *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr));
886
887     if(apphdr->payloadVer != XRAN_PAYLOAD_VER) {
888         print_err("Invalid Payload version - %d", apphdr->payloadVer);
889         ret = -XRAN_ERRCODE_INVALIDPACKET;
890         }
891
892     result->dir             = apphdr->dataDirection;
893     result->hdr.filterIdx   = apphdr->filterIndex;
894     result->hdr.frameId     = apphdr->frameId;
895     result->hdr.subframeId  = apphdr->subframeId;
896     result->hdr.slotId      = apphdr->slotId;
897     result->hdr.startSymId  = apphdr->startSymbolId;
898     result->sectionType     = apphdr->sectionType;
899     result->numSections     = apphdr->numOfSections;
900
901     switch(apphdr->sectionType) {
902         case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted
903             {
904             struct xran_cp_radioapp_section0_header *hdr;
905             struct xran_cp_radioapp_section0 *section;
906
907                 hdr = (struct xran_cp_radioapp_section0_header*)apphdr;
908
909                 result->hdr.fftSize     = rte_be_to_cpu_16(hdr->timeOffset);
910                 result->hdr.scs         = hdr->frameStructure.fftSize;
911                 result->hdr.timeOffset  = hdr->frameStructure.uScs;
912                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
913                 //hdr->reserved;    /* should be zero */
914                 
915                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header));
916                 if(section == NULL) {
917                     print_err("Invalid packet 0 - radio app hedaer!");
918                     return (-XRAN_ERRCODE_INVALIDPACKET);
919                     }
920                 for(i=0; i<result->numSections; i++) {
921                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
922
923                     result->sections[i].info.type       = apphdr->sectionType;
924                     result->sections[i].info.id         = section->hdr.sectionId;
925                     result->sections[i].info.rb         = section->hdr.rb;
926                     result->sections[i].info.symInc     = section->hdr.symInc;
927                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
928                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
929                     result->sections[i].info.numSymbol  = section->hdr.u.s0.numSymbol;
930                     result->sections[i].info.reMask     = section->hdr.u.s0.reMask;
931                     //section->hdr.u.s0.reserved;   /* should be zero */
932
933                     section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0));
934                     if(section == NULL) {
935                         print_err("Invalid packet 0 - number of section [%d:%d]!",
936                                     result->numSections, i);
937                         result->numSections = i;
938                         ret = (-XRAN_ERRCODE_INVALIDPACKET);
939                         break;
940                         }
941                     }
942             }
943             break;
944
945         case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels
946             {
947             struct xran_cp_radioapp_section1_header *hdr;
948             struct xran_cp_radioapp_section1 *section;
949
950                 hdr = (struct xran_cp_radioapp_section1_header*)apphdr;
951
952                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
953                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
954
955                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header));
956                 if(section == NULL) {
957                     print_err("Invalid packet 1 - radio app hedaer!");
958                     return (-XRAN_ERRCODE_INVALIDPACKET);
959                     }
960
961                 for(i=0; i<result->numSections; i++) {
962                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
963
964                     result->sections[i].info.type       = apphdr->sectionType;
965                     result->sections[i].info.id         = section->hdr.sectionId;
966                     result->sections[i].info.rb         = section->hdr.rb;
967                     result->sections[i].info.symInc     = section->hdr.symInc;
968                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
969                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
970                     result->sections[i].info.numSymbol  = section->hdr.u.s1.numSymbol;
971                     result->sections[i].info.reMask     = section->hdr.u.s1.reMask;
972                     result->sections[i].info.beamId     = section->hdr.u.s1.beamId;
973                     result->sections[i].info.ef         = section->hdr.u.s1.ef;
974
975                     if(section->hdr.u.s1.ef) {
976                         // TODO: handle section extension
977                         extlen = 0;
978                         }
979                     else extlen = 0;
980
981                     section = (void *)rte_pktmbuf_adj(mbuf,
982                                     sizeof(struct xran_cp_radioapp_section1)+extlen);
983                     if(section == NULL) {
984                         print_err("Invalid packet 1 - number of section [%d:%d]!",
985                                     result->numSections, i);
986                         result->numSections = i;
987                         ret = (-XRAN_ERRCODE_INVALIDPACKET);
988                         break;
989                         }
990                     }
991             }
992             break;
993
994         case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels
995             {
996             struct xran_cp_radioapp_section3_header *hdr;
997             struct xran_cp_radioapp_section3 *section;
998
999                 hdr = (struct xran_cp_radioapp_section3_header*)apphdr;
1000
1001                 result->hdr.timeOffset  = rte_be_to_cpu_16(hdr->timeOffset);
1002                 result->hdr.scs         = hdr->frameStructure.uScs;
1003                 result->hdr.fftSize     = hdr->frameStructure.fftSize;
1004                 result->hdr.cpLength    = rte_be_to_cpu_16(hdr->cpLength);
1005                 result->hdr.iqWidth     = hdr->udComp.udIqWidth;
1006                 result->hdr.compMeth    = hdr->udComp.udCompMeth;
1007
1008                 section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header));
1009                 if(section == NULL) {
1010                     print_err("Invalid packet 3 - radio app hedaer!");
1011                     return (-XRAN_ERRCODE_INVALIDPACKET);
1012                     }
1013
1014                 for(i=0; i<result->numSections; i++) {
1015                     *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section));
1016
1017                     result->sections[i].info.type       = apphdr->sectionType;
1018                     result->sections[i].info.id         = section->hdr.sectionId;
1019                     result->sections[i].info.rb         = section->hdr.rb;
1020                     result->sections[i].info.symInc     = section->hdr.symInc;
1021                     result->sections[i].info.startPrbc  = section->hdr.startPrbc;
1022                     result->sections[i].info.numPrbc    = section->hdr.numPrbc,
1023                     result->sections[i].info.numSymbol  = section->hdr.u.s3.numSymbol;
1024                     result->sections[i].info.reMask     = section->hdr.u.s3.reMask;
1025                     result->sections[i].info.beamId     = section->hdr.u.s3.beamId;
1026                     result->sections[i].info.ef         = section->hdr.u.s3.ef;
1027                     result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8;
1028
1029                     if(section->reserved) {
1030                         print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved);
1031                         ret = -XRAN_ERRCODE_INVALIDPACKET;
1032                         }
1033
1034                     if(section->hdr.u.s3.ef) {
1035                         // TODO: handle section extension
1036                         extlen = 0;
1037                         }
1038                     else extlen = 0;
1039
1040                     section = (void *)rte_pktmbuf_adj(mbuf,
1041                                     sizeof(struct xran_cp_radioapp_section3)+extlen);
1042                     if(section == NULL) {
1043                         print_err("Invalid packet 3 - number of section [%d:%d]!",
1044                                     result->numSections, i);
1045                         result->numSections = i;
1046                         ret = (-XRAN_ERRCODE_INVALIDPACKET);
1047                         break;
1048                         }
1049                     }
1050             }
1051             break;
1052
1053         case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported
1054         case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported
1055         case XRAN_CP_SECTIONTYPE_7: // LAA, not supported
1056         default:
1057             ret = -XRAN_ERRCODE_INVALIDPARAM;
1058             print_err("Non-supported Section Type - %d", apphdr->sectionType);
1059         }
1060
1061 #if 0
1062     printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n",
1063             result->dir?"DL":"UL",
1064             result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId,
1065             result->sectionType, result->numSections,
1066             result->hdr.startSymId,
1067             result->hdr.filterIdx,
1068             result->hdr.iqWidth, result->hdr.compMeth);
1069
1070     for(i=0; i<result->numSections; i++) {
1071         printf("  >> %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02X numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n",
1072             i, result->sections[i].info.id,
1073             result->sections[i].info.rb,
1074             result->sections[i].info.symInc, result->sections[i].info.numSymbol,
1075             result->sections[i].info.startPrbc, result->sections[i].info.numPrbc,
1076             result->sections[i].info.reMask,
1077             result->sections[i].info.beamId,
1078             result->sections[i].info.freqOffset,
1079             result->sections[i].info.ef);
1080 //                    result->sections[i].info.type
1081         }
1082 #endif
1083
1084     return(ret);
1085 }
1086