* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / lib / src / xran_cp_proc.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 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 C plane processing functionality and helper functions
21  * @file xran_cp_proc.c
22  * @ingroup group_source_xran
23  * @author Intel Corporation
24  **/
25
26 #define _GNU_SOURCE
27 #include <sched.h>
28 #include <assert.h>
29 #include <err.h>
30 #include <libgen.h>
31 #include <sys/time.h>
32 #include <sys/queue.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <stdio.h>
36 #include <pthread.h>
37 #include <malloc.h>
38 #include <immintrin.h>
39
40 #include <rte_common.h>
41 #include <rte_eal.h>
42 #include <rte_errno.h>
43 #include <rte_lcore.h>
44 #include <rte_cycles.h>
45 #include <rte_memory.h>
46 #include <rte_memzone.h>
47 #include <rte_mbuf.h>
48 #include <rte_ring.h>
49 #include <rte_malloc.h>
50
51 #include "xran_fh_o_du.h"
52
53 #include "ethdi.h"
54 #include "xran_pkt.h"
55 #include "xran_up_api.h"
56 #include "xran_cp_api.h"
57 #include "xran_sync_api.h"
58 #include "xran_lib_mlog_tasks_id.h"
59 #include "xran_timer.h"
60 #include "xran_common.h"
61 #include "xran_dev.h"
62 #include "xran_frame_struct.h"
63 #include "xran_printf.h"
64 #include "xran_cp_proc.h"
65 #include "xran_tx_proc.h"
66
67 #include "xran_mlog_lnx.h"
68
69 uint8_t xran_cp_seq_id_num[XRAN_PORTS_NUM][XRAN_MAX_CELLS_PER_PORT][XRAN_DIR_MAX][XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR]; /* XRAN_MAX_ANTENNA_NR * 2 for PUSCH and PRACH */
70 uint8_t xran_updl_seq_id_num[XRAN_PORTS_NUM][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR];
71 uint8_t xran_upul_seq_id_num[XRAN_PORTS_NUM][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR]; /**< PUSCH, PRACH, SRS for Cat B */
72 uint8_t xran_section_id_curslot[XRAN_PORTS_NUM][XRAN_DIR_MAX][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2+ XRAN_MAX_ANT_ARRAY_ELM_NR];
73 uint16_t xran_section_id[XRAN_PORTS_NUM][XRAN_DIR_MAX][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2+ XRAN_MAX_ANT_ARRAY_ELM_NR];
74
75 struct xran_recv_packet_info parse_recv[XRAN_PORTS_NUM];
76
77 //////////////////////////////////////////
78 // For RU emulation
79 struct xran_section_recv_info *recvSections[XRAN_PORTS_NUM] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
80 struct xran_cp_recv_params recvCpInfo[XRAN_PORTS_NUM];
81
82 extern int32_t first_call;
83
84 static void
85 extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)
86 {
87     /*long t1 = MLogTick();
88     MLogTask(77777, t1, t1+100);*/
89 }
90
91 int32_t
92 xran_init_sectionid(void *pHandle)
93 {
94     int cell, ant, dir;
95     struct xran_device_ctx* p_dev = NULL;
96     uint8_t xran_port_id = 0;
97
98     if(pHandle) {
99         p_dev = (struct xran_device_ctx* )pHandle;
100         xran_port_id = p_dev->xran_port_id;
101     } else {
102         print_err("Invalid pHandle - %p", pHandle);
103         return (-1);
104     }
105
106     for (dir = 0; dir < XRAN_DIR_MAX; dir++){
107         for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {
108             for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) {
109                 xran_section_id[xran_port_id][dir][cell][ant] = 0;
110                 xran_section_id_curslot[xran_port_id][dir][cell][ant] = 255;
111             }
112         }
113     }
114
115     return (0);
116 }
117
118 int32_t
119 xran_init_seqid(void *pHandle)
120 {
121     int cell, dir, ant;
122     int8_t xran_port = 0;
123     if((xran_port =  xran_dev_ctx_get_port_id(pHandle)) < 0 ){
124         print_err("Invalid pHandle - %p", pHandle);
125         return (0);
126     }
127
128
129     for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {
130         for(dir=0; dir < XRAN_DIR_MAX; dir++) {
131             for(ant=0; ant < XRAN_MAX_ANTENNA_NR * 2; ant++)
132                 xran_cp_seq_id_num[xran_port][cell][dir][ant] = 0;
133             }
134         for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++)
135                 xran_updl_seq_id_num[xran_port][cell][ant] = 0;
136         for(ant=0; ant < XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR; ant++)
137                 xran_upul_seq_id_num[xran_port][cell][ant] = 0;
138         }
139
140     return (0);
141 }
142
143 int32_t
144 process_cplane(struct rte_mbuf *pkt, void* handle)
145 {
146     uint32_t mb_free = MBUF_FREE;
147     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)handle;
148
149     if(p_xran_dev_ctx && xran_if_current_state == XRAN_RUNNING) {
150         if(xran_dev_get_ctx_by_id(0)->fh_cfg.debugStop) /* check CP with standard tests only */
151             xran_parse_cp_pkt(pkt, &recvCpInfo[p_xran_dev_ctx->xran_port_id], &parse_recv[p_xran_dev_ctx->xran_port_id],(void*)p_xran_dev_ctx, &mb_free);
152     }
153     return (mb_free);
154 }
155
156 int32_t
157 xran_check_symbolrange(int symbol_type, uint32_t PortId, int cc_id, int tti,
158                         int start_sym, int numsym_in, int *numsym_out)
159 {
160     int i;
161     int first_pos, last_pos;
162     int start_pos, end_pos;
163
164     first_pos = last_pos = -1;
165
166     /* Find first symbol which is same with given symbol type */
167     for(i=0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++)
168         if(xran_fs_get_symbol_type(PortId, cc_id, tti, i) == symbol_type) {
169             first_pos = i; break;
170             }
171
172     if(first_pos < 0) {
173 //        for(i=0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++)
174 //            printf("symbol_type %d - %d:%d\n", symbol_type, i, xran_fs_get_symbol_type(cc_id, tti, i));
175         *numsym_out = 0;
176         return (first_pos);
177         }
178
179     /* Find the rest of consecutive symbols which are same with given symbol type */
180     for( ; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++)
181         if(xran_fs_get_symbol_type(PortId, cc_id, tti, i) != symbol_type)
182             break;
183     last_pos = i;
184
185     start_pos = (first_pos > start_sym) ?  first_pos : start_sym;
186     end_pos = ((start_sym + numsym_in) > last_pos) ? last_pos : (start_sym + numsym_in);
187     *numsym_out = end_pos - start_pos;
188
189     return (start_pos);
190 }
191
192 struct rte_mbuf *
193 xran_attach_cp_ext_buf(uint16_t vf_id, int8_t* p_ext_buff_start/*ext_start*/, int8_t* p_ext_buff/*ext-section*/, uint16_t ext_buff_len,
194                 struct rte_mbuf_ext_shared_info * p_share_data)
195 {
196     struct rte_mbuf *mb_oran_hdr_ext = NULL;
197     //struct rte_mbuf *tmp             = NULL;
198     int8_t          *ext_buff        = NULL;
199     rte_iova_t ext_buff_iova         = 0;
200
201     ext_buff  = p_ext_buff - (RTE_PKTMBUF_HEADROOM +
202                 sizeof(struct xran_ecpri_hdr) +
203                 sizeof(struct xran_cp_radioapp_section1_header));
204
205     ext_buff_len += (RTE_PKTMBUF_HEADROOM +
206                 sizeof(struct xran_ecpri_hdr) +
207                 sizeof(struct xran_cp_radioapp_section1_header) + 18);
208
209 //    mb_oran_hdr_ext =  rte_pktmbuf_alloc(_eth_mbuf_pool_small);
210     mb_oran_hdr_ext = xran_ethdi_mbuf_indir_alloc();
211
212     if (unlikely (( mb_oran_hdr_ext) == NULL)) {
213         rte_panic("Failed rte_pktmbuf_alloc\n");
214     }
215
216     p_share_data->free_cb = extbuf_free_callback;
217     p_share_data->fcb_opaque = NULL;
218     rte_mbuf_ext_refcnt_set(p_share_data, 1);
219
220     ext_buff_iova = rte_malloc_virt2iova(p_ext_buff_start);
221     if (unlikely (( ext_buff_iova) == 0)) {
222         rte_panic("Failed rte_mem_virt2iova \n");
223     }
224
225     if (unlikely (( (rte_iova_t)ext_buff_iova) == RTE_BAD_IOVA)) {
226         rte_panic("Failed rte_mem_virt2iova RTE_BAD_IOVA \n");
227     }
228
229     rte_pktmbuf_attach_extbuf(mb_oran_hdr_ext,
230                               ext_buff,
231                               ext_buff_iova + RTE_PTR_DIFF(ext_buff , p_ext_buff_start),
232                               ext_buff_len,
233                               p_share_data);
234
235     rte_pktmbuf_reset_headroom(mb_oran_hdr_ext);
236
237     return mb_oran_hdr_ext;
238 }
239
240 /* TO DO: __thread is slow. We should allocate global 2D array and index it using current core index
241  * for better performance.
242  */
243 __thread struct xran_section_gen_info sect_geninfo[XRAN_MAX_SECTIONS_PER_SLOT];
244
245 int32_t
246 xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int tti, int cc_id,
247         struct xran_prb_map *prbMap, struct xran_prb_elm_proc_info_t *prbElmProcInfo, enum xran_category category,  uint8_t ctx_id)
248 {
249     int32_t ret = 0;
250     struct xran_device_ctx *p_x_ctx   = (struct xran_device_ctx *)pHandle;
251     struct xran_common_counters *pCnt = &p_x_ctx->fh_counters;
252     struct xran_cp_gen_params params;
253     struct rte_mbuf *mbuf;
254     uint32_t interval = p_x_ctx->interval_us_local;
255     uint8_t PortId = p_x_ctx->xran_port_id;
256     int16_t numCPSections=0, ext_offset=0, start_sect_id=0;
257
258     uint32_t i, j, loc_sym,idx;
259     uint32_t nsection = 0;
260     struct xran_prb_elm *pPrbMapElem = NULL;
261     // struct xran_prb_elm *pPrbMapElemPrev = NULL;
262     uint32_t slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME(interval));
263     uint32_t subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME(interval),  SUBFRAMES_PER_SYSTEMFRAME);
264     uint32_t frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME(interval));
265
266     uint8_t seq_id = 0;
267     uint16_t vf_id = 0 , curr_sec_id = 0 , prb_per_section, start_Prb;
268     int32_t startSym = 0, numSyms = 0;
269
270     int next=0;
271     struct xran_sectionext1_info ext1;
272     struct xran_sectionext4_info ext4 = {0};
273     struct xran_sectionext9_info ext9;
274     struct xran_sectionext11_info ext11;
275
276     frame_id = (frame_id & 0xff); /* ORAN frameId, 8 bits, [0, 255] */
277
278     if(unlikely((category != XRAN_CATEGORY_A) && (category != XRAN_CATEGORY_B)))
279     {
280         print_err("Unsupported Category %d\n", category);
281         return (-1);
282     }
283
284     /* Generate a C-Plane message per each section,
285      * not a C-Plane message with multi sections */
286     if(0 == p_x_ctx->RunSlotPrbMapBySymbolEnable)
287     {
288     if(prbMap) {
289
290             nsection = prbMap->nPrbElm;
291             i=0;
292             if(XRAN_DIR_DL == dir)
293             {
294                 if(0 == p_x_ctx->numSymsForDlCP)
295                 {
296                     print_dbg("No symbol available for DL CP transmission\n");
297                     return (-1);
298                 }
299
300                 if(prbMap->nPrbElm == prbElmProcInfo->nPrbElmProcessed && 0 != prbElmProcInfo->numSymsRemaining)
301                 {
302                     prbElmProcInfo->numSymsRemaining--;
303                     print_dbg("All sections already processed\n");
304                     return (-1);
305                 }
306
307                 if(0== prbElmProcInfo->numSymsRemaining)
308                 { /* new slot */
309                     prbElmProcInfo->numSymsRemaining = p_x_ctx->numSymsForDlCP;
310                     prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm/p_x_ctx->numSymsForDlCP;
311                     prbElmProcInfo->nPrbElmProcessed = 0;
312                 }
313
314                 if(1 == prbElmProcInfo->numSymsRemaining)
315                 {/* last symbol:: send all remaining */
316         nsection = prbMap->nPrbElm;
317                 }
318                 else
319                 {
320                     if(0 == prbElmProcInfo->nPrbElmPerSym)
321                         nsection=prbElmProcInfo->nPrbElmProcessed + 1;
322                     else
323                         nsection = prbElmProcInfo->nPrbElmProcessed + prbElmProcInfo->nPrbElmPerSym;
324                 }
325
326                 i=prbElmProcInfo->nPrbElmProcessed;
327                 prbElmProcInfo->numSymsRemaining--;
328
329             } //dir = DL
330             else
331             {
332                 nsection = prbMap->nPrbElm;
333                 i=0;
334             } //dir = UL
335
336         pPrbMapElem = &prbMap->prbMap[0];
337         }
338         else
339         {
340         print_err("prbMap is NULL\n");
341         return (-1);
342     }
343
344
345         curr_sec_id = 0;
346         if(pPrbMapElem->bf_weight.extType == 1)
347         {
348             for(j=0;j<i;j++)
349                 curr_sec_id += prbMap->prbMap[j].bf_weight.numSetBFWs;
350         }
351         else
352             curr_sec_id = i;
353
354         // start_id=curr_sec_id;
355         uint8_t generateCpPkt=0;
356         uint8_t replacePrbStartNSize=0; /* In case of application fragmentation, we send 1 cplane packets for multiple
357                                            uplane packets i.e. 1 cp packet for multiple PRBs. This flag is used to
358                                            achieve that by setting different values for cp packet preparation and for
359                                            cp-up database update */
360
361     /* Generate a C-Plane message per each section,
362      * not a C-Plane message with multi sections */
363         for (; i < nsection; i++) {
364         int startSym, numSyms;
365
366         pPrbMapElem                 = &prbMap->prbMap[i];
367             prb_per_section = pPrbMapElem->bf_weight.numBundPrb;
368             start_Prb       = pPrbMapElem->nRBStart;
369
370             if((pPrbMapElem->bf_weight.extType == 1) &&
371                     (((i+1)<nsection && prbMap->prbMap[i+1].IsNewSect==1) ||
372                     (i+1) == nsection))
373             { /*ext1*/
374                 generateCpPkt=1;
375             }
376             else if(pPrbMapElem->IsNewSect)
377                 generateCpPkt=1;
378             else
379                 generateCpPkt=0;
380
381
382        /* For Special Subframe,
383         * Check validity of given symbol range with slot configuration
384         * and adjust symbol range accordingly. */
385         if(xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_FDD) != 1
386                 && xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_SP) == 1)
387             {
388             /* This function cannot handle two or more groups of consecutive same type of symbol.
389                 * If there are two or more, then it might cause an error */
390             startSym = xran_check_symbolrange(
391                                 ((dir==XRAN_DIR_DL)?XRAN_SYMBOL_TYPE_DL:XRAN_SYMBOL_TYPE_UL),
392                                 PortId, cc_id, tti,
393                                 pPrbMapElem->nStartSymb,
394                                 pPrbMapElem->numSymb, &numSyms);
395                 if(startSym < 0 || numSyms == 0)
396                 {
397                 /* if start symbol is not valid, then skip this section */
398                 print_err("Skip section %d due to invalid symbol range - [%d:%d], [%d:%d]",
399                             i,
400                             pPrbMapElem->nStartSymb, pPrbMapElem->numSymb,
401                             startSym, numSyms);
402                 continue;
403             }
404             }
405             else
406             {
407             startSym    = pPrbMapElem->nStartSymb;
408             numSyms     = pPrbMapElem->numSymb;
409         }
410
411         vf_id  = xran_map_ecpriRtcid_to_vf(p_x_ctx, dir, cc_id, ru_port_id);
412         params.dir                  = dir;
413         params.sectionType          = XRAN_CP_SECTIONTYPE_1;
414         params.hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;
415         params.hdr.frameId          = frame_id;
416         params.hdr.subframeId       = subframe_id;
417         params.hdr.slotId           = slot_id;
418         params.hdr.startSymId       = startSym;
419         params.hdr.iqWidth          = pPrbMapElem->iqWidth;
420         params.hdr.compMeth         = pPrbMapElem->compMethod;
421
422         print_dbg("cp[%d:%d:%d] ru_port_id %d dir=%d\n",
423                                frame_id, subframe_id, slot_id, ru_port_id, dir);
424
425             if(pPrbMapElem->bf_weight.extType == 1)
426             {
427                 /* Send multiple CP sections per prbElement for ext-1 */
428                 numCPSections   = pPrbMapElem->bf_weight.numSetBFWs;
429             }
430             else
431             {
432                 numCPSections   = 1;
433                 replacePrbStartNSize = 1;   /* in case of no app fragmentation, UP_nRBSize will be same as nRBSize. So,
434                                                 always replacing the elements when ext1 is not in use */
435             }
436
437             /** Prepare section info for multiple sections in a PRB element */
438             for(idx=0; idx < numCPSections; idx++) {
439
440                 sect_geninfo[curr_sec_id].exDataSize=0;
441                 sect_geninfo[curr_sec_id].info = xran_cp_get_section_info_ptr(pHandle, dir, cc_id, ru_port_id, ctx_id);
442                 if(unlikely(sect_geninfo[curr_sec_id].info == NULL))
443                 {
444                     rte_panic("xran_cp_get_section_info_ptr failed\n");
445                     }
446
447                 struct xran_section_info *info = sect_geninfo[curr_sec_id].info;
448                 info->prbElemBegin  = (idx == 0 ) ?  1 : 0;
449                 info->prbElemEnd    = (idx + 1 == numCPSections) ?  1 : 0;
450                 info->ef            = 0;
451                 info->freqOffset    = 0;
452                 info->ueId          = 0;
453                 info->regFactor     = 0;
454
455                 if((idx+1)*prb_per_section > pPrbMapElem->nRBSize){
456                     prb_per_section = pPrbMapElem->nRBSize - idx*prb_per_section;
457                 }
458
459                 if(numCPSections == 1)
460                 {
461                     info->startPrbc = pPrbMapElem->nRBStart;
462                     info->numPrbc   = pPrbMapElem->nRBSize;
463                 }
464                 else
465                 {
466                     info->startPrbc = start_Prb;
467                     info->numPrbc   = prb_per_section;
468                     start_Prb       += prb_per_section;
469             }
470
471                 info->type        = params.sectionType;
472                 info->startSymId  = params.hdr.startSymId;
473                 info->iqWidth     = params.hdr.iqWidth;
474                 info->compMeth    = params.hdr.compMeth;
475                 info->id          = curr_sec_id;
476
477                 if(info->prbElemBegin && pPrbMapElem->IsNewSect==1)
478                 {
479                     start_sect_id = info->id;
480         }
481
482                 if(unlikely(info->id > XRAN_MAX_SECTIONS_PER_SLOT))
483                     print_err("sectinfo->id %d\n", info->id);
484
485                 info->rb          = XRAN_RBIND_EVERY;
486                 info->numSymbol   = numSyms;
487                 info->reMask      = 0xfff;
488                 info->beamId      = pPrbMapElem->nBeamIndex;
489                 info->symInc      = XRAN_SYMBOLNUMBER_NOTINC;
490
491                 for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
492                 {
493                     struct xran_section_desc *p_sec_desc =  &pPrbMapElem->sec_desc[loc_sym][0];
494
495                     if(p_sec_desc)
496                     {
497                         info->sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;
498                         info->sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;
499
500                         p_sec_desc->section_id   = info->id;
501             }
502                     else
503                     {
504                         print_err("section desc is NULL\n");
505         }
506
507                 } /* for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) */
508
509         /* Add extentions if required */
510                 if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
511                 {
512                     if(pPrbMapElem->bf_weight.extType == 1) /* Prepare section data for ext-1 */
513                     {
514         next = 0;
515                         sect_geninfo[curr_sec_id].exDataSize  = 0;
516
517                         memset(&ext1, 0, sizeof (struct xran_sectionext1_info));
518                         ext1.bfwNumber      = pPrbMapElem->bf_weight.nAntElmTRx;
519                         ext1.bfwIqWidth     = pPrbMapElem->iqWidth;
520                         ext1.bfwCompMeth    = pPrbMapElem->compMethod;
521                         /* ext-1 buffer contains CP sections */
522                         ext1.bfwIQ_sz       = ONE_EXT_LEN(pPrbMapElem); //76
523
524                         ext_offset          = (idx*ONE_CPSEC_EXT_LEN(pPrbMapElem)) + sizeof(struct xran_cp_radioapp_section1);
525                         ext1.p_bfwIQ        = (int8_t*)(pPrbMapElem->bf_weight.p_ext_section + ext_offset);
526
527                         sect_geninfo[curr_sec_id].exData[next].type   = XRAN_CP_SECTIONEXTCMD_1;
528                         sect_geninfo[curr_sec_id].exData[next].len    = sizeof(ext1);
529                         sect_geninfo[curr_sec_id].exData[next].data   = &ext1;
530
531                         info->ef = 1;
532                         sect_geninfo[curr_sec_id].exDataSize++;
533                         next++;
534                     }
535                     else
536                     {
537                         /*ext-11*/
538                     }
539
540                 } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
541
542                 curr_sec_id++;
543             } /* for(idx=0; idx < numCPSections;idx++) */
544
545             if (dir==XRAN_DIR_UL || generateCpPkt) //only send actual new CP section
546             {
547         /* Extension 4 for modulation compression */
548                 if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
549                 {
550             mbuf = xran_ethdi_mbuf_alloc();
551
552             ext4.csf                            = 0;  //no shift for now only
553             ext4.modCompScaler                  = pPrbMapElem->ScaleFactor;
554                     /* TO DO: Should this be the current section id? */
555             sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_4;
556             sect_geninfo[0].exData[next].len    = sizeof(ext4);
557             sect_geninfo[0].exData[next].data   = &ext4;
558
559                     sect_geninfo[0].info->ef             = 1;
560             sect_geninfo[0].exDataSize++;
561             next++;
562         }
563
564         /* Extension 1 or 11 for Beam forming weights */
565                 /* add section extention for BF Weights if update is needed */
566                 if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
567                 {
568                     if(pPrbMapElem->bf_weight.extType == 1) /* Using Extension 1 */
569                     {
570                         //TODO: Should this change ?
571                         struct rte_mbuf_ext_shared_info * p_share_data =
572                         &p_x_ctx->cp_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info->id];
573
574                         if(pPrbMapElem->bf_weight.p_ext_start)
575                         {
576                     /* use buffer with BF Weights for mbuf */
577                     mbuf = xran_attach_cp_ext_buf(vf_id, pPrbMapElem->bf_weight.p_ext_start,
578                                                 pPrbMapElem->bf_weight.p_ext_section,
579                                                 pPrbMapElem->bf_weight.ext_section_sz, p_share_data);
580                         }
581                         else
582                         {
583                     print_err("p %d cc %d dir %d Alloc fail!\n", PortId, cc_id, dir);
584                             ret=-1;
585                             goto _create_and_send_section_error;
586                 }
587                     } /* if(pPrbMapElem->bf_weight.extType == 1) */
588                     else
589                     {
590                 /* Using Extension 11 */
591                 struct rte_mbuf_ext_shared_info *shared_info;
592                         next = 0;
593
594                         shared_info = &p_x_ctx->bfw_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info->id];
595                 shared_info->free_cb     = NULL;
596                 shared_info->fcb_opaque  = NULL;
597
598                 mbuf = xran_ethdi_mbuf_indir_alloc();
599                 if(unlikely(mbuf == NULL)) {
600                     rte_panic("Alloc fail!\n");
601                 }
602                 //mbuf = rte_pktmbuf_alloc(_eth_mbuf_pool_vf_small[vf_id]);
603                         if(xran_cp_attach_ext_buf(mbuf, (uint8_t *)pPrbMapElem->bf_weight.p_ext_start, pPrbMapElem->bf_weight.maxExtBufSize, shared_info) < 0)
604                         {
605                     rte_pktmbuf_free(mbuf);
606                             ret=-1;
607                             goto _create_and_send_section_error;
608                 }
609
610                 rte_mbuf_ext_refcnt_update(shared_info, 0);
611
612                 ext11.RAD           = pPrbMapElem->bf_weight.RAD;
613                 ext11.disableBFWs   = pPrbMapElem->bf_weight.disableBFWs;
614
615                 ext11.numBundPrb    = pPrbMapElem->bf_weight.numBundPrb;
616                 ext11.numSetBFWs    = pPrbMapElem->bf_weight.numSetBFWs;
617
618                 ext11.bfwCompMeth   = pPrbMapElem->bf_weight.bfwCompMeth;
619                 ext11.bfwIqWidth    = pPrbMapElem->bf_weight.bfwIqWidth;
620
621                 ext11.maxExtBufSize = pPrbMapElem->bf_weight.maxExtBufSize;
622                 ext11.pExtBufShinfo = shared_info;
623
624                 ext11.pExtBuf       = (uint8_t *)pPrbMapElem->bf_weight.p_ext_start;
625                 ext11.totalBfwIQLen = pPrbMapElem->bf_weight.ext_section_sz;
626
627                 sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_11;
628                 sect_geninfo[0].exData[next].len    = sizeof(ext11);
629                 sect_geninfo[0].exData[next].data   = &ext11;
630
631                         sect_geninfo[0].info->ef       = 1;
632                 sect_geninfo[0].exDataSize++;
633                 next++;
634             }
635                 } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
636                 else
637                 {
638             mbuf = xran_ethdi_mbuf_alloc();
639
640                     sect_geninfo[0].info->ef          = 0;
641             sect_geninfo[0].exDataSize       = 0;
642
643                     if(p_x_ctx->dssEnable == 1) {
644                         uint8_t dssSlot = 0;
645                         dssSlot = tti % (p_x_ctx->dssPeriod);
646
647                         ext9.technology = p_x_ctx->technology[dssSlot];
648                         ext9.reserved = 0;
649
650                         sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_9;
651                         sect_geninfo[0].exData[next].len    = sizeof(ext9);
652                         sect_geninfo[0].exData[next].data   = &ext9;
653
654                         sect_geninfo[0].info->ef       = 1;
655                         sect_geninfo[0].exDataSize++;
656                         next++;
657                     }
658         }
659
660                 if(unlikely(mbuf == NULL))
661                 {
662             print_err("Alloc fail!\n");
663                     ret=-1;
664                     goto _create_and_send_section_error;
665         }
666
667                 params.numSections          = numCPSections;
668         params.sections             = sect_geninfo;
669
670                 seq_id = xran_get_cp_seqid(pHandle, ((XRAN_DIR_DL == dir)? XRAN_DIR_DL : XRAN_DIR_UL), cc_id, ru_port_id);
671                 ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id,start_sect_id);
672             } /* if (dir==XRAN_DIR_UL || generateCpPkt) */
673
674             if(replacePrbStartNSize && XRAN_DIR_DL == dir)
675             {
676                 sect_geninfo[curr_sec_id-1].info->startPrbc = pPrbMapElem->UP_nRBStart;
677                 sect_geninfo[curr_sec_id-1].info->numPrbc   = pPrbMapElem->UP_nRBSize;
678             }
679
680             if(ret < 0)
681             {
682             print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
683                         frame_id, subframe_id, slot_id, dir);
684             }
685             else
686             {
687                 if((dir==XRAN_DIR_UL) || generateCpPkt) //only send actual new CP section
688                 {
689             int32_t cp_sent = 0;
690             int32_t pkt_len = 0;
691             /* add in the ethernet header */
692             struct rte_ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
693             pkt_len = rte_pktmbuf_pkt_len(mbuf);
694             pCnt->tx_counter++;
695             pCnt->tx_bytes_counter += pkt_len; //rte_pktmbuf_pkt_len(mbuf);
696             if(pkt_len > p_x_ctx->fh_init.mtu)
697                 rte_panic("section %d: pkt_len = %d maxExtBufSize %d\n", i, pkt_len, pPrbMapElem->bf_weight.maxExtBufSize);
698
699             cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
700                     if(cp_sent != 1)
701                     {
702                 rte_pktmbuf_free(mbuf);
703             }
704                 }
705         }
706     } /* for (i=0; i<nsection; i++) */
707     }
708 #if 1
709     else
710     {
711         /* Generate a C-Plane message with multi sections,
712         * a C-Plane message for each section*/
713         if(prbMap)
714         {
715             if(0 == prbMap->nPrbElm)
716             {
717                 print_dbg("prbMap->nPrbElm is %d\n",prbMap->nPrbElm);
718                 return 0;
719             }
720
721             nsection = prbMap->nPrbElm;
722             i=0;
723             if(XRAN_DIR_DL == dir)
724             {
725                 prbElmProcInfo->numSymsRemaining = 0;
726                 prbElmProcInfo->nPrbElmProcessed = 0;
727                 prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm;
728                 nsection = prbMap->nPrbElm;
729             } //dir = DL
730             else
731             {
732                 nsection = prbMap->nPrbElm;
733             } //dir = UL
734         }
735         else
736         {
737             print_err("prbMap is NULL\n");
738             return (-1);
739         }
740
741         pPrbMapElem = &prbMap->prbMap[0];
742
743         if(xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_FDD) != 1
744             && xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_SP) == 1)
745         {
746             startSym = xran_check_symbolrange(
747                                 ((dir==XRAN_DIR_DL)?XRAN_SYMBOL_TYPE_DL:XRAN_SYMBOL_TYPE_UL),
748                                 PortId, cc_id, tti,
749                                 pPrbMapElem->nStartSymb,
750                                 pPrbMapElem->numSymb, &numSyms);
751
752             if(startSym < 0 || numSyms == 0)
753             {
754                 /* if start symbol is not valid, then skip this section */
755                 print_err("Skip section %d due to invalid symbol range - [%d:%d], [%d:%d]",
756                             i,
757                             pPrbMapElem->nStartSymb, pPrbMapElem->numSymb,
758                             startSym, numSyms);
759             }
760         }
761         else
762         {
763             startSym    = pPrbMapElem->nStartSymb;
764             numSyms     = pPrbMapElem->numSymb;
765         }
766
767         vf_id  = xran_map_ecpriRtcid_to_vf(p_x_ctx, dir, cc_id, ru_port_id);
768         params.dir                  = dir;
769         params.sectionType          = XRAN_CP_SECTIONTYPE_1;
770         params.hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;
771         params.hdr.frameId          = frame_id;
772         params.hdr.subframeId       = subframe_id;
773         params.hdr.slotId           = slot_id;
774         params.hdr.startSymId       = startSym;
775         params.hdr.iqWidth          = pPrbMapElem->iqWidth;
776         params.hdr.compMeth         = pPrbMapElem->compMethod;
777         params.sections             = sect_geninfo;
778
779         for (i = 0, j = 0; j < nsection; j++)
780         {
781             sect_geninfo[i].exDataSize=0;
782             sect_geninfo[i].info = xran_cp_get_section_info_ptr(pHandle, dir, cc_id, ru_port_id, ctx_id);
783             sect_geninfo[i].info->prbElemBegin = ((j == 0 ) ?  1 : 0);
784             sect_geninfo[i].info->prbElemEnd   = ((j + 1 == nsection) ?  1 : 0);
785             if(sect_geninfo[i].info == NULL)
786             {
787                 rte_panic("xran_cp_get_section_info_ptr failed\n");
788             }
789             pPrbMapElem = &prbMap->prbMap[j];
790
791             sect_geninfo[i].info->type        = XRAN_CP_SECTIONTYPE_1;
792             sect_geninfo[i].info->startSymId  = pPrbMapElem->nStartSymb;
793             sect_geninfo[i].info->iqWidth     = params.hdr.iqWidth;
794             sect_geninfo[i].info->compMeth    = params.hdr.compMeth;
795             sect_geninfo[i].info->id          = pPrbMapElem->nSectId;
796
797             if(sect_geninfo[i].info->id > XRAN_MAX_SECTIONS_PER_SLOT)
798                 print_err("sectinfo->id %d\n", sect_geninfo[i].info->id);
799
800             sect_geninfo[i].info->rb          = XRAN_RBIND_EVERY;
801             sect_geninfo[i].info->startPrbc   = pPrbMapElem->UP_nRBStart;
802             sect_geninfo[i].info->numPrbc     = pPrbMapElem->UP_nRBSize;
803             sect_geninfo[i].info->numSymbol   = pPrbMapElem->numSymb;
804             sect_geninfo[i].info->reMask      = 0xfff;
805             sect_geninfo[i].info->beamId      = pPrbMapElem->nBeamIndex;
806
807             if(startSym == pPrbMapElem->nStartSymb)
808                 sect_geninfo[i].info->symInc  = XRAN_SYMBOLNUMBER_NOTINC;
809             else
810             {
811                 if((startSym + numSyms) == pPrbMapElem->nStartSymb)
812                 {
813                     sect_geninfo[i].info->symInc  = XRAN_SYMBOLNUMBER_INC;
814                     startSym  =   pPrbMapElem->nStartSymb;
815                     numSyms   =   pPrbMapElem->numSymb;
816                 }
817                 else
818                 {
819                     sect_geninfo[i].info->startSymId = startSym;
820                     sect_geninfo[i].info->numSymbol  = numSyms;
821                     print_dbg("Last startSym is %d. Last numSyms is %d. But current pPrbMapElem->nStartSymb is %d.\n", startSym, numSyms, pPrbMapElem->nStartSymb);
822                 }
823             }
824
825
826             for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
827             {
828                 struct xran_section_desc *p_sec_desc =  &pPrbMapElem->sec_desc[loc_sym][0];
829                 if(p_sec_desc)
830                 {
831                     p_sec_desc->section_id   = sect_geninfo[i].info->id;
832
833                     sect_geninfo[i].info->sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;
834                     sect_geninfo[i].info->sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;
835                 }
836                 else
837                 {
838                     print_err("section desc is NULL\n");
839                 }
840             }
841
842             next = 0;
843             sect_geninfo[i].exDataSize       = 0;
844
845           /* Extension 4 for modulation compression */
846             if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
847             {
848                 // print_dbg("[%s]:%d Modulation Compression need to verify for this code branch and may not be available\n");
849                 print_err("[%s]:%d Modulation Compression need to verify for this code branch and may not be available\n",__FUNCTION__, __LINE__);
850             }
851             /* Extension 1 or 11 for Beam forming weights */
852             /* add section extention for BF Weights if update is needed */
853             if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
854             {
855                 // print_dbg("[%s]:%d Category B need to verify for this code branch and may not be available\n");
856                 print_err("[%s]:%d Category B need to verify for this code branch and may not be available\n",__FUNCTION__, __LINE__);
857             } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
858             else
859             {
860                 sect_geninfo[i].info->ef          = 0;
861                 sect_geninfo[i].exDataSize       = 0;
862
863                 if(p_x_ctx->dssEnable == 1) {
864                     uint8_t dssSlot = 0;
865                     dssSlot = tti % (p_x_ctx->dssPeriod);
866
867                     ext9.technology = p_x_ctx->technology[dssSlot];
868                     ext9.reserved = 0;
869
870                     sect_geninfo[i].exData[next].type   = XRAN_CP_SECTIONEXTCMD_9;
871                     sect_geninfo[i].exData[next].len    = sizeof(ext9);
872                     sect_geninfo[i].exData[next].data   = &ext9;
873
874                     sect_geninfo[i].info->ef       = 1;
875                     sect_geninfo[i].exDataSize++;
876                     next++;
877                 }
878             }
879
880             // xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id, &sect_geninfo[i].info);
881
882             if(pPrbMapElem->IsNewSect == 1)
883             {
884                 sect_geninfo[i].info->startPrbc   = pPrbMapElem->nRBStart;
885                 sect_geninfo[i].info->numPrbc     = pPrbMapElem->nRBSize;
886                 i++;
887             }
888         }
889
890         params.numSections          = i;
891
892         mbuf = xran_ethdi_mbuf_alloc();
893         if(unlikely(mbuf == NULL))
894         {
895             print_err("Alloc fail!\n");
896             ret=-1;
897             goto _create_and_send_section_error;
898         }
899
900         seq_id = xran_get_cp_seqid(pHandle, ((XRAN_DIR_DL == dir)? XRAN_DIR_DL : XRAN_DIR_UL), cc_id, ru_port_id);
901         ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id,start_sect_id);
902
903         if(ret < 0)
904         {
905             print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
906                         frame_id, subframe_id, slot_id, dir);
907         }
908         else
909         {
910
911             int32_t cp_sent = 0;
912             int32_t pkt_len = 0;
913             /* add in the ethernet header */
914             struct rte_ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
915             pkt_len = rte_pktmbuf_pkt_len(mbuf);
916             pCnt->tx_counter++;
917             pCnt->tx_bytes_counter += pkt_len; //rte_pktmbuf_pkt_len(mbuf);
918             if(pkt_len > p_x_ctx->fh_init.mtu)
919                 rte_panic("section %d: pkt_len = %d maxExtBufSize %d\n", i, pkt_len, pPrbMapElem->bf_weight.maxExtBufSize);
920
921             cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
922             if(cp_sent != 1)
923             {
924                 rte_pktmbuf_free(mbuf);
925             }
926         }
927
928         struct xran_section_info *info;
929         for (j = 0; j < nsection; j++)
930         {
931             pPrbMapElem = &prbMap->prbMap[j];
932             info = xran_cp_find_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id,j);
933             if(info == NULL)
934             {
935                 rte_panic("xran_cp_get_section_info_ptr failed\n");
936             }
937             info->startPrbc   = pPrbMapElem->UP_nRBStart;
938             info->numPrbc     = pPrbMapElem->UP_nRBSize;
939         }
940     }
941 #endif
942 _create_and_send_section_error:
943     if(XRAN_DIR_DL == dir)
944     {
945         prbElmProcInfo->nPrbElmProcessed = nsection;
946     }
947
948     return ret;
949 }
950
951 int32_t
952 xran_ruemul_init(void *pHandle)
953 {
954     uint16_t xran_port_id;
955     struct xran_device_ctx* p_dev = NULL;
956
957     if(pHandle) {
958         p_dev = (struct xran_device_ctx* )pHandle;
959         xran_port_id = p_dev->xran_port_id;
960     } else {
961         print_err("Invalid pHandle - %p", pHandle);
962         return (XRAN_STATUS_FAIL);
963     }
964
965     if(xran_port_id < XRAN_PORTS_NUM) {
966         if(recvSections[xran_port_id]) {
967             print_err("Memory already allocated!");
968             return (-1);
969             }
970
971         recvSections[xran_port_id] = malloc(sizeof(struct xran_section_recv_info) * XRAN_MAX_NUM_SECTIONS);
972         if(recvSections[xran_port_id] == NULL) {
973             print_err("Fail to allocate memory!");
974             return (-1);
975             }
976
977         recvCpInfo[xran_port_id].sections = recvSections[xran_port_id];
978     } else {
979         print_err("Incorrect xran port %d\n", xran_port_id);
980         return (-1);
981     }
982
983
984     return (0);
985 }
986
987 int32_t
988 xran_ruemul_release(void *pHandle)
989 {
990     uint16_t xran_port_id;
991     struct xran_device_ctx* p_dev = NULL;
992
993     if(pHandle) {
994         p_dev = (struct xran_device_ctx* )pHandle;
995         xran_port_id = p_dev->xran_port_id;
996     } else {
997         print_err("Invalid pHandle - %p", pHandle);
998         return (XRAN_STATUS_FAIL);
999     }
1000
1001     if(xran_port_id < XRAN_PORTS_NUM){
1002         if(recvSections[xran_port_id]) {
1003             free(recvSections[xran_port_id]);
1004             recvCpInfo[xran_port_id].sections = NULL;
1005         }
1006     } else {
1007         print_err("Incorrect xran port %d\n", xran_port_id);
1008         return (-1);
1009     }
1010
1011     return (0);
1012 }