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