Update to odulow per maintenance bronze
[o-du/phy.git] / fhi_lib / lib / src / xran_common.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief XRAN layer common functionality for both O-DU and O-RU as well as C-plane and
21  *    U-plane
22  * @file xran_common.c
23  * @ingroup group_source_xran
24  * @author Intel Corporation
25  **/
26
27 #include <assert.h>
28 #include <err.h>
29 #include <arpa/inet.h>
30 #include <sys/time.h>
31 #include <time.h>
32
33 #include "xran_common.h"
34 #include "ethdi.h"
35 #include "xran_pkt.h"
36 #include "xran_pkt_up.h"
37 #include "xran_up_api.h"
38 #include "xran_lib_mlog_tasks_id.h"
39
40 #include "../src/xran_printf.h"
41 #include <rte_mbuf.h>
42 #include "xran_mlog_lnx.h"
43
44 static struct timespec sleeptime = {.tv_nsec = 1E3 }; /* 1 us */
45
46 #define MBUFS_CNT 16
47
48 extern long interval_us;
49
50 extern int xran_process_rx_sym(void *arg,
51                         struct rte_mbuf *mbuf,
52                         void *iq_data_start,
53                         uint16_t size,
54                         uint8_t CC_ID,
55                         uint8_t Ant_ID,
56                         uint8_t frame_id,
57                         uint8_t subframe_id,
58                         uint8_t slot_id,
59                         uint8_t symb_id,
60                         uint16_t num_prbu,
61                         uint16_t start_prbu,
62                         uint16_t sym_inc,
63                         uint16_t rb,
64                         uint16_t sect_id,
65                         uint32_t *mb_free);
66
67
68 extern int xran_process_prach_sym(void *arg,
69                         struct rte_mbuf *mbuf,
70                         void *iq_data_start,
71                         uint16_t size,
72                         uint8_t CC_ID,
73                         uint8_t Ant_ID,
74                         uint8_t frame_id,
75                         uint8_t subframe_id,
76                         uint8_t slot_id,
77                         uint8_t symb_id,
78                         uint16_t num_prbu,
79                         uint16_t start_prbu,
80                         uint16_t sym_inc,
81                         uint16_t rb,
82                         uint16_t sect_id,
83                         uint32_t *mb_free);
84
85 extern int32_t xran_process_srs_sym(void *arg,
86                         struct rte_mbuf *mbuf,
87                         void *iq_data_start,
88                         uint16_t size,
89                         uint8_t CC_ID,
90                         uint8_t Ant_ID,
91                         uint8_t frame_id,
92                         uint8_t subframe_id,
93                         uint8_t slot_id,
94                         uint8_t symb_id,
95                         uint16_t num_prbu,
96                         uint16_t start_prbu,
97                         uint16_t sym_inc,
98                         uint16_t rb,
99                         uint16_t sect_id,
100                         uint32_t *mb_free);
101
102 extern int32_t xran_pkt_validate(void *arg,
103                         struct rte_mbuf *mbuf,
104                         void *iq_data_start,
105                         uint16_t size,
106                         uint8_t CC_ID,
107                         uint8_t Ant_ID,
108                         uint8_t frame_id,
109                         uint8_t subframe_id,
110                         uint8_t slot_id,
111                         uint8_t symb_id,
112                         struct ecpri_seq_id *seq_id,
113                         uint16_t num_prbu,
114                         uint16_t start_prbu,
115                         uint16_t sym_inc,
116                         uint16_t rb,
117                         uint16_t sect_id);
118
119
120 struct cb_elem_entry *xran_create_cb(XranSymCallbackFn cb_fn, void *cb_data)
121 {
122         struct cb_elem_entry * cb_elm = (struct cb_elem_entry *)malloc(sizeof(struct cb_elem_entry));
123         if(cb_elm){
124             cb_elm->pSymCallback    = cb_fn;
125             cb_elm->pSymCallbackTag = cb_data;
126         }
127
128         return cb_elm;
129 }
130
131 int xran_destroy_cb(struct cb_elem_entry * cb_elm)
132 {
133     if(cb_elm)
134         free(cb_elm);
135     return 0;
136 }
137
138 int process_mbuf(struct rte_mbuf *pkt)
139 {
140     void *iq_samp_buf;
141     struct ecpri_seq_id seq;
142     static int symbol_total_bytes = 0;
143     int num_bytes = 0;
144     struct xran_device_ctx * p_x_ctx = xran_dev_get_ctx();
145     struct xran_common_counters *pCnt = &p_x_ctx->fh_counters;
146
147     uint8_t CC_ID = 0;
148     uint8_t Ant_ID = 0;
149     uint8_t frame_id = 0;
150     uint8_t subframe_id = 0;
151     uint8_t slot_id = 0;
152     uint8_t symb_id = 0;
153
154     uint16_t num_prbu;
155     uint16_t start_prbu;
156     uint16_t sym_inc;
157     uint16_t rb;
158     uint16_t sect_id;
159
160     uint8_t compMeth = 0;
161     uint8_t iqWidth = 0;
162
163     void *pHandle = NULL;
164     int ret = MBUF_FREE;
165     uint32_t mb_free = 0;
166     int32_t valid_res = 0;
167     int expect_comp  = (p_x_ctx->fh_cfg.ru_conf.compMeth != XRAN_COMPMETHOD_NONE);
168
169
170     if(p_x_ctx->xran2phy_mem_ready == 0)
171         return MBUF_FREE;
172
173     num_bytes = xran_extract_iq_samples(pkt,
174                                         &iq_samp_buf,
175                                         &CC_ID,
176                                         &Ant_ID,
177                                         &frame_id,
178                                         &subframe_id,
179                                         &slot_id,
180                                         &symb_id,
181                                         &seq,
182                                         &num_prbu,
183                                         &start_prbu,
184                                         &sym_inc,
185                                         &rb,
186                                         &sect_id,
187                                         expect_comp,
188                                         &compMeth,
189                                         &iqWidth);
190     if (num_bytes <= 0){
191         print_err("num_bytes is wrong [%d]\n", num_bytes);
192         return MBUF_FREE;
193     }
194
195     valid_res = xran_pkt_validate(NULL,
196                                 pkt,
197                                 iq_samp_buf,
198                                 num_bytes,
199                                 CC_ID,
200                                 Ant_ID,
201                                 frame_id,
202                                 subframe_id,
203                                 slot_id,
204                                 symb_id,
205                                 &seq,
206                                 num_prbu,
207                                 start_prbu,
208                                 sym_inc,
209                                 rb,
210                                 sect_id);
211
212     if(valid_res != 0) {
213         print_dbg("valid_res is wrong [%d] ant %u (%u : %u : %u : %u) seq %u num_bytes %d\n", valid_res, Ant_ID, frame_id, subframe_id, slot_id, symb_id, seq.seq_id, num_bytes);
214         return MBUF_FREE;
215     }
216
217     if (Ant_ID >= p_x_ctx->srs_cfg.eAxC_offset && p_x_ctx->fh_init.srsEnable) {
218         /* SRS packet has ruportid = 2*num_eAxc + ant_id */
219         Ant_ID -= p_x_ctx->srs_cfg.eAxC_offset;
220         symbol_total_bytes += num_bytes;
221
222         if (seq.e_bit == 1) {
223             print_dbg("SRS receiving symbol %d, size=%d bytes\n",
224                 symb_id, symbol_total_bytes);
225
226             if (symbol_total_bytes) {
227                int16_t res = xran_process_srs_sym(NULL,
228                                 pkt,
229                                 iq_samp_buf,
230                                 num_bytes,
231                                 CC_ID,
232                                 Ant_ID,
233                                 frame_id,
234                                 subframe_id,
235                                 slot_id,
236                                 symb_id,
237                                 num_prbu,
238                                 start_prbu,
239                                 sym_inc,
240                                 rb,
241                                 sect_id,
242                                 &mb_free);
243
244                 if(res == symbol_total_bytes) {
245                     ret = mb_free;
246                 } else {
247                     print_err("res != symbol_total_bytes\n");
248                 }
249                 pCnt->rx_srs_packets++;
250             }
251             symbol_total_bytes = 0;
252         }
253         else {
254             print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
255         }
256
257     } else if (Ant_ID >= p_x_ctx->PrachCPConfig.eAxC_offset && p_x_ctx->fh_init.prachEnable) {
258         /* PRACH packet has ruportid = num_eAxc + ant_id */
259         Ant_ID -= p_x_ctx->PrachCPConfig.eAxC_offset;
260         symbol_total_bytes += num_bytes;
261         if (seq.e_bit == 1) {
262             print_dbg("Completed receiving PRACH symbol %d, size=%d bytes\n",
263                 symb_id, num_bytes);
264
265             if (symbol_total_bytes) {
266                 int16_t res =  xran_process_prach_sym(NULL,
267                                                       pkt,
268                                                       iq_samp_buf,
269                                                       num_bytes,
270                                                       CC_ID,
271                                                       Ant_ID,
272                                                       frame_id,
273                                                       subframe_id,
274                                                       slot_id,
275                                                       symb_id,
276                                                       num_prbu,
277                                                       start_prbu,
278                                                       sym_inc,
279                                                       rb,
280                                                       sect_id,
281                                                       &mb_free);
282                 if(res == symbol_total_bytes) {
283                     ret = mb_free;
284                 } else {
285                     print_err("res != symbol_total_bytes\n");
286                 }
287                 pCnt->rx_prach_packets[Ant_ID]++;
288             }
289             symbol_total_bytes = 0;
290         } else {
291             print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
292         }
293
294     } else { /* PUSCH */
295         symbol_total_bytes += num_bytes;
296
297         if (seq.e_bit == 1) {
298             print_dbg("Completed receiving symbol %d, size=%d bytes\n",
299                 symb_id, symbol_total_bytes);
300
301             if (symbol_total_bytes) {
302                 int res = xran_process_rx_sym(NULL,
303                                 pkt,
304                                 iq_samp_buf,
305                                 symbol_total_bytes,
306                                 CC_ID,
307                                 Ant_ID,
308                                 frame_id,
309                                 subframe_id,
310                                 slot_id,
311                                 symb_id,
312                                 num_prbu,
313                                 start_prbu,
314                                 sym_inc,
315                                 rb,
316                                 sect_id,
317                                 &mb_free);
318                 if(res == symbol_total_bytes) {
319                     ret = mb_free;
320                 } else {
321                     print_err("res != symbol_total_bytes\n");
322                 }
323                 pCnt->rx_pusch_packets[Ant_ID]++;
324             }
325             symbol_total_bytes = 0;
326         } else {
327             print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
328         }
329     }
330
331     return ret;
332 }
333
334 static int set_iq_bit_width(uint8_t iq_bit_width, struct data_section_compression_hdr *compr_hdr)
335 {
336     if (iq_bit_width == MAX_IQ_BIT_WIDTH)
337         compr_hdr->ud_comp_hdr.ud_iq_width = (uint8_t) 0;
338     else
339         compr_hdr->ud_comp_hdr.ud_iq_width = iq_bit_width;
340
341     return  0;
342
343 }
344
345 /* Send a single 5G symbol over multiple packets */
346 int32_t prepare_symbol_ex(enum xran_pkt_dir direction,
347                 uint16_t section_id,
348                 struct rte_mbuf *mb,
349                 struct rb_map *data,
350                 uint8_t     compMeth,
351                 uint8_t     iqWidth,
352                 const enum xran_input_byte_order iq_buf_byte_order,
353                 uint8_t frame_id,
354                 uint8_t subframe_id,
355                 uint8_t slot_id,
356                 uint8_t symbol_no,
357                 int prb_start,
358                 int prb_num,
359                 uint8_t CC_ID,
360                 uint8_t RU_Port_ID,
361                 uint8_t seq_id,
362                 uint32_t do_copy)
363 {
364     int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
365
366     n_bytes  =   ((iqWidth == 0) || (iqWidth == 16)) ? n_bytes : ((3 * iqWidth + 1 ) * prb_num);
367
368     int32_t prep_bytes;
369
370     int16_t nPktSize = sizeof(struct rte_ether_hdr) + sizeof(struct xran_ecpri_hdr) +
371             sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes;
372     uint32_t off;
373     struct xran_up_pkt_gen_params xp = { 0 };
374
375     if(compMeth != XRAN_COMPMETHOD_NONE)
376         nPktSize += sizeof(struct data_section_compression_hdr);
377
378     n_bytes = RTE_MIN(n_bytes, XRAN_MAX_MBUF_LEN);
379
380     /* radio app header */
381     xp.app_params.data_direction = direction;
382     xp.app_params.payl_ver       = 1;
383     xp.app_params.filter_id      = 0;
384     xp.app_params.frame_id       = frame_id;
385     xp.app_params.sf_slot_sym.subframe_id    = subframe_id;
386     xp.app_params.sf_slot_sym.slot_id        = xran_slotid_convert(slot_id, 0);
387     xp.app_params.sf_slot_sym.symb_id        = symbol_no;
388
389     /* convert to network byte order */
390     xp.app_params.sf_slot_sym.value = rte_cpu_to_be_16(xp.app_params.sf_slot_sym.value);
391
392     xp.sec_hdr.fields.sect_id    = section_id;
393     xp.sec_hdr.fields.num_prbu   = (uint8_t)prb_num;
394     xp.sec_hdr.fields.start_prbu = (uint8_t)prb_start;
395     xp.sec_hdr.fields.sym_inc    = 0;
396     xp.sec_hdr.fields.rb         = 0;
397 #ifdef FCN_ADAPT
398     xp.sec_hdr.udCompHdr         = 0;
399     xp.sec_hdr.reserved          = 0;
400 #endif
401
402     /* compression */
403     xp.compr_hdr_param.ud_comp_hdr.ud_comp_meth = compMeth;
404     xp.compr_hdr_param.ud_comp_hdr.ud_iq_width  = iqWidth;
405     xp.compr_hdr_param.rsrvd                    = 0;
406
407     /* network byte order */
408     xp.sec_hdr.fields.all_bits  = rte_cpu_to_be_32(xp.sec_hdr.fields.all_bits);
409
410     if (mb == NULL){
411         MLogPrint(NULL);
412         errx(1, "out of mbufs after %d packets", 1);
413     }
414
415     prep_bytes = xran_prepare_iq_symbol_portion(mb,
416                                                   data,
417                                                   iq_buf_byte_order,
418                                                   n_bytes,
419                                                   &xp,
420                                                   CC_ID,
421                                                   RU_Port_ID,
422                                                   seq_id,
423                                                   do_copy);
424     if (prep_bytes <= 0)
425         errx(1, "failed preparing symbol");
426
427     rte_pktmbuf_pkt_len(mb)  = nPktSize;
428     rte_pktmbuf_data_len(mb) = nPktSize;
429
430 #ifdef DEBUG
431     printf("Symbol %2d prep_bytes (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
432 #endif
433
434     return prep_bytes;
435 }
436
437 /* Send a single 5G symbol over multiple packets */
438 int send_symbol_ex(enum xran_pkt_dir direction,
439                 uint16_t section_id,
440                 struct rte_mbuf *mb,
441                 struct rb_map *data,
442                 const enum xran_input_byte_order iq_buf_byte_order,
443                 uint8_t frame_id,
444                 uint8_t subframe_id,
445                 uint8_t slot_id,
446                 uint8_t symbol_no,
447                 int prb_start,
448                 int prb_num,
449                 uint8_t CC_ID,
450                 uint8_t RU_Port_ID,
451                 uint8_t seq_id)
452 {
453     uint32_t do_copy = 0;
454     int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
455     struct xran_device_ctx *p_x_ctx = xran_dev_get_ctx();
456     struct xran_common_counters *pCnt = &p_x_ctx->fh_counters;
457
458
459     if (mb == NULL){
460         char * pChar = NULL;
461         mb = xran_ethdi_mbuf_alloc(); /* will be freede by ETH */
462         if(mb ==  NULL){
463             MLogPrint(NULL);
464             errx(1, "out of mbufs after %d packets", 1);
465         }
466         pChar = rte_pktmbuf_append(mb, sizeof(struct xran_ecpri_hdr)+ sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes);
467         if(pChar == NULL){
468                 MLogPrint(NULL);
469                 errx(1, "incorrect mbuf size %d packets", 1);
470         }
471         pChar = rte_pktmbuf_prepend(mb, sizeof(struct rte_ether_hdr));
472         if(pChar == NULL){
473                 MLogPrint(NULL);
474                 errx(1, "incorrect mbuf size %d packets", 1);
475         }
476         do_copy = 1; /* new mbuf hence copy of IQs  */
477     }else {
478         rte_pktmbuf_refcnt_update(mb, 1); /* make sure eth won't free our mbuf */
479     }
480
481     int32_t sent = prepare_symbol_ex(direction,
482                          section_id,
483                          mb,
484                          data,
485                          0,
486                          16,
487                          iq_buf_byte_order,
488                          frame_id,
489                          subframe_id,
490                          slot_id,
491                          symbol_no,
492                          prb_start,
493                          prb_num,
494                          CC_ID,
495                          RU_Port_ID,
496                          seq_id,
497                          do_copy);
498
499     if(sent){
500         pCnt->tx_counter++;
501         pCnt->tx_bytes_counter += rte_pktmbuf_pkt_len(mb);
502         p_x_ctx->send_upmbuf2ring(mb, ETHER_TYPE_ECPRI, xran_map_ecpriPcid_to_vf(direction, CC_ID, RU_Port_ID));
503     } else {
504
505     }
506
507 #ifdef DEBUG
508     printf("Symbol %2d sent (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
509 #endif
510
511     return sent;
512 }
513
514 int send_cpmsg(void *pHandle, struct rte_mbuf *mbuf,struct xran_cp_gen_params *params,
515                 struct xran_section_gen_info *sect_geninfo, uint8_t cc_id, uint8_t ru_port_id, uint8_t seq_id)
516 {
517     int ret = 0, nsection, i;
518     uint8_t subframe_id = params->hdr.subframeId;
519     uint8_t slot_id = params->hdr.slotId;
520     uint8_t dir = params->dir;
521     struct xran_device_ctx *p_x_ctx = xran_dev_get_ctx();
522     struct xran_common_counters *pCnt = &p_x_ctx->fh_counters;
523
524     nsection = params->numSections;
525
526     /* add in the ethernet header */
527     struct rte_ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
528
529     pCnt->tx_counter++;
530     pCnt->tx_bytes_counter += rte_pktmbuf_pkt_len(mbuf);
531     p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, xran_map_ecpriRtcid_to_vf(dir, cc_id, ru_port_id));
532     for(i=0; i<nsection; i++)
533         xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id,
534                 (slot_id + subframe_id*SLOTNUM_PER_SUBFRAME)%XRAN_MAX_SECTIONDB_CTX,
535                 &sect_geninfo[i].info);
536
537     return (ret);
538 }
539
540 int generate_cpmsg_dlul(void *pHandle, struct xran_cp_gen_params *params, struct xran_section_gen_info *sect_geninfo, struct rte_mbuf *mbuf,
541     enum xran_pkt_dir dir, uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
542     uint8_t startsym, uint8_t numsym, uint16_t prb_start, uint16_t prb_num,int16_t iq_buffer_offset, int16_t iq_buffer_len,
543     uint16_t beam_id, uint8_t cc_id, uint8_t ru_port_id, uint8_t comp_method, uint8_t iqWidth,  uint8_t seq_id, uint8_t symInc)
544 {
545     int ret = 0, nsection, loc_sym;
546
547
548     params->dir                  = dir;
549     params->sectionType          = XRAN_CP_SECTIONTYPE_1;        // Most DL/UL Radio Channels
550     params->hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;
551     params->hdr.frameId          = frame_id;
552     params->hdr.subframeId       = subframe_id;
553     params->hdr.slotId           = slot_id;
554     params->hdr.startSymId       = startsym;                     // start Symbol ID
555     params->hdr.iqWidth          = iqWidth;
556     params->hdr.compMeth         = comp_method;
557
558     nsection = 0;
559     sect_geninfo[nsection].info.type        = params->sectionType;       // for database
560     sect_geninfo[nsection].info.startSymId  = params->hdr.startSymId;    // for database
561     sect_geninfo[nsection].info.iqWidth     = params->hdr.iqWidth;       // for database
562     sect_geninfo[nsection].info.compMeth    = params->hdr.compMeth;      // for database
563     sect_geninfo[nsection].info.id          = xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id);
564     sect_geninfo[nsection].info.rb          = XRAN_RBIND_EVERY;
565     sect_geninfo[nsection].info.symInc      = symInc;
566     sect_geninfo[nsection].info.startPrbc   = prb_start;
567     sect_geninfo[nsection].info.numPrbc     = prb_num;
568     sect_geninfo[nsection].info.numSymbol   = numsym;
569     sect_geninfo[nsection].info.reMask      = 0xfff;
570     sect_geninfo[nsection].info.beamId      = beam_id;
571
572     for (loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) {
573         sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_offset = iq_buffer_offset;
574         sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_len    = iq_buffer_len;
575     }
576
577     sect_geninfo[nsection].info.ef          = 0;
578     sect_geninfo[nsection].exDataSize       = 0;
579 //    sect_geninfo[nsection].exData           = NULL;
580     nsection++;
581
582     params->numSections          = nsection;
583     params->sections             = sect_geninfo;
584
585     if(unlikely(mbuf == NULL)) {
586         print_err("Alloc fail!\n");
587         return (-1);
588     }
589
590     ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, ru_port_id, seq_id);
591     if(ret < 0){
592         print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
593                     frame_id, subframe_id, slot_id, dir);
594         rte_pktmbuf_free(mbuf);
595     }
596
597     return (ret);
598 }
599
600 int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struct xran_section_gen_info *sect_geninfo, struct rte_mbuf *mbuf, struct xran_device_ctx *pxran_lib_ctx,
601                 uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
602                 uint16_t beam_id, uint8_t cc_id, uint8_t prach_port_id, uint8_t seq_id)
603 {
604     int nsection, ret;
605     struct xran_prach_cp_config  *pPrachCPConfig = &(pxran_lib_ctx->PrachCPConfig);
606     uint16_t timeOffset;
607     uint16_t nNumerology = pxran_lib_ctx->fh_cfg.frame_conf.nNumerology;
608
609     if(unlikely(mbuf == NULL)) {
610         print_err("Alloc fail!\n");
611         return (-1);
612     }
613 #if 0
614     printf("%d:%d:%d:%d - filter=%d, startSym=%d[%d:%d], numSym=%d, occasions=%d, freqOff=%d\n",
615                 frame_id, subframe_id, slot_id, prach_port_id,
616                 pPrachCPConfig->filterIdx,
617                 pPrachCPConfig->startSymId,
618                 pPrachCPConfig->startPrbc,
619                 pPrachCPConfig->numPrbc,
620                 pPrachCPConfig->numSymbol,
621                 pPrachCPConfig->occassionsInPrachSlot,
622                 pPrachCPConfig->freqOffset);
623 #endif
624     timeOffset = pPrachCPConfig->timeOffset; //this is the CP value per 38.211 tab 6.3.3.1-1&2
625     timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu
626     if (pPrachCPConfig->startSymId > 0)
627     {
628         timeOffset += (pPrachCPConfig->startSymId * 2048) >> nNumerology;
629         if ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME >> 1)))
630             timeOffset += 16;
631     }
632     params->dir                  = XRAN_DIR_UL;
633     params->sectionType          = XRAN_CP_SECTIONTYPE_3;
634     params->hdr.filterIdx        = pPrachCPConfig->filterIdx;
635     params->hdr.frameId          = frame_id;
636     params->hdr.subframeId       = subframe_id;
637     params->hdr.slotId           = slot_id;
638     params->hdr.startSymId       = pPrachCPConfig->startSymId;
639     params->hdr.iqWidth          = xran_get_conf_iqwidth(pHandle);
640     params->hdr.compMeth         = xran_get_conf_compmethod(pHandle);
641         /* use timeOffset field for the CP length value for prach sequence */
642     params->hdr.timeOffset       = timeOffset;
643     params->hdr.fftSize          = xran_get_conf_fftsize(pHandle);
644     params->hdr.scs              = xran_get_conf_prach_scs(pHandle);
645     params->hdr.cpLength         = 0;
646
647     nsection = 0;
648     sect_geninfo[nsection].info.type        = params->sectionType;       // for database
649     sect_geninfo[nsection].info.startSymId  = params->hdr.startSymId;    // for database
650     sect_geninfo[nsection].info.iqWidth     = params->hdr.iqWidth;       // for database
651     sect_geninfo[nsection].info.compMeth    = params->hdr.compMeth;      // for database
652     sect_geninfo[nsection].info.id          = xran_alloc_sectionid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);
653     sect_geninfo[nsection].info.rb          = XRAN_RBIND_EVERY;
654     sect_geninfo[nsection].info.symInc      = XRAN_SYMBOLNUMBER_NOTINC;
655     sect_geninfo[nsection].info.startPrbc   = pPrachCPConfig->startPrbc;
656     sect_geninfo[nsection].info.numPrbc     = pPrachCPConfig->numPrbc,
657     sect_geninfo[nsection].info.numSymbol   = pPrachCPConfig->numSymbol*pPrachCPConfig->occassionsInPrachSlot;
658     sect_geninfo[nsection].info.reMask      = 0xfff;
659     sect_geninfo[nsection].info.beamId      = beam_id;
660     sect_geninfo[nsection].info.freqOffset  = pPrachCPConfig->freqOffset;
661
662     pxran_lib_ctx->prach_last_symbol[cc_id] = sect_geninfo[nsection].info.startSymId + sect_geninfo[nsection].info.numSymbol - 1;
663
664     sect_geninfo[nsection].info.ef          = 0;
665     sect_geninfo[nsection].exDataSize       = 0;
666 //    sect_geninfo[nsection].exData           = NULL;
667     nsection++;
668
669     params->numSections          = nsection;
670     params->sections             = sect_geninfo;
671
672     ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, prach_port_id, seq_id);
673     if(ret < 0){
674         print_err("Fail to build prach control packet - [%d:%d:%d]\n", frame_id, subframe_id, slot_id);
675         rte_pktmbuf_free(mbuf);
676     }
677     return ret;
678 }
679
680
681 int process_ring(struct rte_ring *r)
682 {
683     assert(r);
684
685     struct rte_mbuf *mbufs[MBUFS_CNT];
686     int i;
687     uint32_t remaining;
688     uint64_t t1;
689     const uint16_t dequeued = rte_ring_dequeue_burst(r, (void **)mbufs,
690         RTE_DIM(mbufs), &remaining);
691
692     if (!dequeued)
693         return 0;
694
695     t1 = MLogTick();
696     for (i = 0; i < dequeued; ++i) {
697         if (xran_ethdi_filter_packet(mbufs[i], 0) == MBUF_FREE)
698             rte_pktmbuf_free(mbufs[i]);
699     }
700     MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick());
701
702     return remaining;
703 }
704
705 int32_t ring_processing_func(void)
706 {
707     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
708     struct xran_device_ctx *const pxran_lib_ctx = xran_dev_get_ctx();
709     int16_t retPoll = 0;
710     int32_t i;
711     uint64_t t1, t2;
712
713     rte_timer_manage();
714
715     if (pxran_lib_ctx->bbdev_dec) {
716         t1 = MLogTick();
717         retPoll = pxran_lib_ctx->bbdev_dec();
718         if (retPoll != -1)
719         {
720             t2 = MLogTick();
721             MLogTask(PID_XRAN_BBDEV_UL_POLL + retPoll, t1, t2);
722         }
723     }
724
725     if (pxran_lib_ctx->bbdev_enc) {
726         t1 = MLogTick();
727         retPoll = pxran_lib_ctx->bbdev_enc();
728         if (retPoll != -1)
729         {
730             t2 = MLogTick();
731             MLogTask(PID_XRAN_BBDEV_DL_POLL + retPoll, t1, t2);
732         }
733     }
734
735     /* UP first */
736
737     for (i = 0; i < ctx->io_cfg.num_vfs && i < (XRAN_VF_MAX - 1); i = i+2){
738         if (process_ring(ctx->rx_ring[i]))
739             return 0;
740
741         /* CP next */
742         if(ctx->io_cfg.id == O_RU) /* process CP only on O-RU */
743             if (process_ring(ctx->rx_ring[i+1]))
744                 return 0;
745     }
746
747     if (XRAN_STOPPED == xran_if_current_state)
748         return -1;
749
750     return 0;
751 }
752
753 int ring_processing_thread(void *args)
754 {
755     struct sched_param sched_param;
756     struct xran_device_ctx *const p_xran_dev_ctx = xran_dev_get_ctx();
757     int res = 0;
758
759     memset(&sched_param, 0, sizeof(struct sched_param));
760
761     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());
762     sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;
763     if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param))){
764         printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);
765     }
766
767     for (;;){
768         if(ring_processing_func() != 0)
769             break;
770
771         /* work around for some kernel */
772         if(p_xran_dev_ctx->fh_init.io_cfg.io_sleep)
773             nanosleep(&sleeptime,NULL);
774     }
775
776     puts("Pkt processing thread finished.");
777     return 0;
778 }
779