1 /******************************************************************************
3 * Copyright (c) 2020 Intel.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 *******************************************************************************/
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
32 #include <sys/queue.h>
38 #include <immintrin.h>
40 #include <rte_common.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>
49 #include <rte_malloc.h>
51 #include "xran_fh_o_du.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"
62 #include "xran_frame_struct.h"
63 #include "xran_printf.h"
64 #include "xran_cp_proc.h"
65 #include "xran_tx_proc.h"
67 #include "xran_mlog_lnx.h"
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];
75 struct xran_recv_packet_info parse_recv[XRAN_PORTS_NUM];
77 //////////////////////////////////////////
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];
82 extern int32_t first_call;
85 extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)
87 /*long t1 = MLogTick();
88 MLogTask(77777, t1, t1+100);*/
92 xran_init_sectionid(void *pHandle)
95 struct xran_device_ctx* p_dev = NULL;
96 uint8_t xran_port_id = 0;
99 p_dev = (struct xran_device_ctx* )pHandle;
100 xran_port_id = p_dev->xran_port_id;
102 print_err("Invalid pHandle - %p", pHandle);
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;
119 xran_init_seqid(void *pHandle)
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);
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;
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;
144 process_cplane(struct rte_mbuf *pkt, void* handle)
146 uint32_t mb_free = MBUF_FREE;
147 struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)handle;
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);
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)
161 int first_pos, last_pos;
162 int start_pos, end_pos;
164 first_pos = last_pos = -1;
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;
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));
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)
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;
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)
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;
201 ext_buff = p_ext_buff - (RTE_PKTMBUF_HEADROOM +
202 sizeof(struct xran_ecpri_hdr) +
203 sizeof(struct xran_cp_radioapp_section1_header));
205 ext_buff_len += (RTE_PKTMBUF_HEADROOM +
206 sizeof(struct xran_ecpri_hdr) +
207 sizeof(struct xran_cp_radioapp_section1_header) + 18);
209 // mb_oran_hdr_ext = rte_pktmbuf_alloc(_eth_mbuf_pool_small);
210 mb_oran_hdr_ext = xran_ethdi_mbuf_indir_alloc();
212 if (unlikely (( mb_oran_hdr_ext) == NULL)) {
213 rte_panic("Failed rte_pktmbuf_alloc\n");
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);
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");
225 if (unlikely (( (rte_iova_t)ext_buff_iova) == RTE_BAD_IOVA)) {
226 rte_panic("Failed rte_mem_virt2iova RTE_BAD_IOVA \n");
229 rte_pktmbuf_attach_extbuf(mb_oran_hdr_ext,
231 ext_buff_iova + RTE_PTR_DIFF(ext_buff , p_ext_buff_start),
235 rte_pktmbuf_reset_headroom(mb_oran_hdr_ext);
237 return mb_oran_hdr_ext;
240 /* TO DO: __thread is slow. We should allocate global 2D array and index it using current core index
241 * for better performance.
243 __thread struct xran_section_gen_info sect_geninfo[XRAN_MAX_SECTIONS_PER_SLOT];
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)
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;
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));
267 uint16_t vf_id = 0 , curr_sec_id = 0 , prb_per_section, start_Prb;
268 int32_t startSym = 0, numSyms = 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;
276 frame_id = (frame_id & 0xff); /* ORAN frameId, 8 bits, [0, 255] */
278 if(unlikely((category != XRAN_CATEGORY_A) && (category != XRAN_CATEGORY_B)))
280 print_err("Unsupported Category %d\n", category);
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)
290 nsection = prbMap->nPrbElm;
292 if(XRAN_DIR_DL == dir)
294 if(0 == p_x_ctx->numSymsForDlCP)
296 print_dbg("No symbol available for DL CP transmission\n");
300 if(prbMap->nPrbElm == prbElmProcInfo->nPrbElmProcessed && 0 != prbElmProcInfo->numSymsRemaining)
302 prbElmProcInfo->numSymsRemaining--;
303 print_dbg("All sections already processed\n");
307 if(0== prbElmProcInfo->numSymsRemaining)
309 prbElmProcInfo->numSymsRemaining = p_x_ctx->numSymsForDlCP;
310 prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm/p_x_ctx->numSymsForDlCP;
311 prbElmProcInfo->nPrbElmProcessed = 0;
314 if(1 == prbElmProcInfo->numSymsRemaining)
315 {/* last symbol:: send all remaining */
316 nsection = prbMap->nPrbElm;
320 if(0 == prbElmProcInfo->nPrbElmPerSym)
321 nsection=prbElmProcInfo->nPrbElmProcessed + 1;
323 nsection = prbElmProcInfo->nPrbElmProcessed + prbElmProcInfo->nPrbElmPerSym;
326 i=prbElmProcInfo->nPrbElmProcessed;
327 prbElmProcInfo->numSymsRemaining--;
332 nsection = prbMap->nPrbElm;
336 pPrbMapElem = &prbMap->prbMap[0];
340 print_err("prbMap is NULL\n");
346 if(pPrbMapElem->bf_weight.extType == 1)
349 curr_sec_id += prbMap->prbMap[j].bf_weight.numSetBFWs;
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 */
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;
366 pPrbMapElem = &prbMap->prbMap[i];
367 prb_per_section = pPrbMapElem->bf_weight.numBundPrb;
368 start_Prb = pPrbMapElem->nRBStart;
370 if((pPrbMapElem->bf_weight.extType == 1) &&
371 (((i+1)<nsection && prbMap->prbMap[i+1].IsNewSect==1) ||
376 else if(pPrbMapElem->IsNewSect)
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)
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),
393 pPrbMapElem->nStartSymb,
394 pPrbMapElem->numSymb, &numSyms);
395 if(startSym < 0 || numSyms == 0)
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]",
400 pPrbMapElem->nStartSymb, pPrbMapElem->numSymb,
407 startSym = pPrbMapElem->nStartSymb;
408 numSyms = pPrbMapElem->numSymb;
411 vf_id = xran_map_ecpriRtcid_to_vf(p_x_ctx, dir, cc_id, ru_port_id);
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;
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);
425 if(pPrbMapElem->bf_weight.extType == 1)
427 /* Send multiple CP sections per prbElement for ext-1 */
428 numCPSections = pPrbMapElem->bf_weight.numSetBFWs;
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 */
437 /** Prepare section info for multiple sections in a PRB element */
438 for(idx=0; idx < numCPSections; idx++) {
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))
444 rte_panic("xran_cp_get_section_info_ptr failed\n");
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;
451 info->freqOffset = 0;
455 if((idx+1)*prb_per_section > pPrbMapElem->nRBSize){
456 prb_per_section = pPrbMapElem->nRBSize - idx*prb_per_section;
459 if(numCPSections == 1)
461 info->startPrbc = pPrbMapElem->nRBStart;
462 info->numPrbc = pPrbMapElem->nRBSize;
466 info->startPrbc = start_Prb;
467 info->numPrbc = prb_per_section;
468 start_Prb += prb_per_section;
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;
477 if(info->prbElemBegin && pPrbMapElem->IsNewSect==1)
479 start_sect_id = info->id;
482 if(unlikely(info->id > XRAN_MAX_SECTIONS_PER_SLOT))
483 print_err("sectinfo->id %d\n", info->id);
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;
491 for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
493 struct xran_section_desc *p_sec_desc = &pPrbMapElem->sec_desc[loc_sym][0];
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;
500 p_sec_desc->section_id = info->id;
504 print_err("section desc is NULL\n");
507 } /* for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) */
509 /* Add extentions if required */
510 if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
512 if(pPrbMapElem->bf_weight.extType == 1) /* Prepare section data for ext-1 */
515 sect_geninfo[curr_sec_id].exDataSize = 0;
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
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);
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;
532 sect_geninfo[curr_sec_id].exDataSize++;
540 } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
543 } /* for(idx=0; idx < numCPSections;idx++) */
545 if (dir==XRAN_DIR_UL || generateCpPkt) //only send actual new CP section
547 /* Extension 4 for modulation compression */
548 if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
550 mbuf = xran_ethdi_mbuf_alloc();
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;
559 sect_geninfo[0].info->ef = 1;
560 sect_geninfo[0].exDataSize++;
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))
568 if(pPrbMapElem->bf_weight.extType == 1) /* Using Extension 1 */
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];
574 if(pPrbMapElem->bf_weight.p_ext_start)
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);
583 print_err("p %d cc %d dir %d Alloc fail!\n", PortId, cc_id, dir);
585 goto _create_and_send_section_error;
587 } /* if(pPrbMapElem->bf_weight.extType == 1) */
590 /* Using Extension 11 */
591 struct rte_mbuf_ext_shared_info *shared_info;
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;
598 mbuf = xran_ethdi_mbuf_indir_alloc();
599 if(unlikely(mbuf == NULL)) {
600 rte_panic("Alloc fail!\n");
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)
605 rte_pktmbuf_free(mbuf);
607 goto _create_and_send_section_error;
610 rte_mbuf_ext_refcnt_update(shared_info, 0);
612 ext11.RAD = pPrbMapElem->bf_weight.RAD;
613 ext11.disableBFWs = pPrbMapElem->bf_weight.disableBFWs;
615 ext11.numBundPrb = pPrbMapElem->bf_weight.numBundPrb;
616 ext11.numSetBFWs = pPrbMapElem->bf_weight.numSetBFWs;
618 ext11.bfwCompMeth = pPrbMapElem->bf_weight.bfwCompMeth;
619 ext11.bfwIqWidth = pPrbMapElem->bf_weight.bfwIqWidth;
621 ext11.maxExtBufSize = pPrbMapElem->bf_weight.maxExtBufSize;
622 ext11.pExtBufShinfo = shared_info;
624 ext11.pExtBuf = (uint8_t *)pPrbMapElem->bf_weight.p_ext_start;
625 ext11.totalBfwIQLen = pPrbMapElem->bf_weight.ext_section_sz;
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;
631 sect_geninfo[0].info->ef = 1;
632 sect_geninfo[0].exDataSize++;
635 } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
638 mbuf = xran_ethdi_mbuf_alloc();
640 sect_geninfo[0].info->ef = 0;
641 sect_geninfo[0].exDataSize = 0;
643 if(p_x_ctx->dssEnable == 1) {
645 dssSlot = tti % (p_x_ctx->dssPeriod);
647 ext9.technology = p_x_ctx->technology[dssSlot];
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;
654 sect_geninfo[0].info->ef = 1;
655 sect_geninfo[0].exDataSize++;
660 if(unlikely(mbuf == NULL))
662 print_err("Alloc fail!\n");
664 goto _create_and_send_section_error;
667 params.numSections = numCPSections;
668 params.sections = sect_geninfo;
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, ¶ms, cc_id, ru_port_id, seq_id,start_sect_id);
672 } /* if (dir==XRAN_DIR_UL || generateCpPkt) */
674 if(replacePrbStartNSize && XRAN_DIR_DL == dir)
676 sect_geninfo[curr_sec_id-1].info->startPrbc = pPrbMapElem->UP_nRBStart;
677 sect_geninfo[curr_sec_id-1].info->numPrbc = pPrbMapElem->UP_nRBSize;
682 print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
683 frame_id, subframe_id, slot_id, dir);
687 if((dir==XRAN_DIR_UL) || generateCpPkt) //only send actual new CP section
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);
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);
699 cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
702 rte_pktmbuf_free(mbuf);
706 } /* for (i=0; i<nsection; i++) */
711 /* Generate a C-Plane message with multi sections,
712 * a C-Plane message for each section*/
715 if(0 == prbMap->nPrbElm)
717 print_dbg("prbMap->nPrbElm is %d\n",prbMap->nPrbElm);
721 nsection = prbMap->nPrbElm;
723 if(XRAN_DIR_DL == dir)
725 prbElmProcInfo->numSymsRemaining = 0;
726 prbElmProcInfo->nPrbElmProcessed = 0;
727 prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm;
728 nsection = prbMap->nPrbElm;
732 nsection = prbMap->nPrbElm;
737 print_err("prbMap is NULL\n");
741 pPrbMapElem = &prbMap->prbMap[0];
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)
746 startSym = xran_check_symbolrange(
747 ((dir==XRAN_DIR_DL)?XRAN_SYMBOL_TYPE_DL:XRAN_SYMBOL_TYPE_UL),
749 pPrbMapElem->nStartSymb,
750 pPrbMapElem->numSymb, &numSyms);
752 if(startSym < 0 || numSyms == 0)
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]",
757 pPrbMapElem->nStartSymb, pPrbMapElem->numSymb,
763 startSym = pPrbMapElem->nStartSymb;
764 numSyms = pPrbMapElem->numSymb;
767 vf_id = xran_map_ecpriRtcid_to_vf(p_x_ctx, dir, cc_id, ru_port_id);
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;
779 for (i = 0, j = 0; j < nsection; j++)
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)
787 rte_panic("xran_cp_get_section_info_ptr failed\n");
789 pPrbMapElem = &prbMap->prbMap[j];
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;
797 if(sect_geninfo[i].info->id > XRAN_MAX_SECTIONS_PER_SLOT)
798 print_err("sectinfo->id %d\n", sect_geninfo[i].info->id);
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;
807 if(startSym == pPrbMapElem->nStartSymb)
808 sect_geninfo[i].info->symInc = XRAN_SYMBOLNUMBER_NOTINC;
811 if((startSym + numSyms) == pPrbMapElem->nStartSymb)
813 sect_geninfo[i].info->symInc = XRAN_SYMBOLNUMBER_INC;
814 startSym = pPrbMapElem->nStartSymb;
815 numSyms = pPrbMapElem->numSymb;
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);
826 for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
828 struct xran_section_desc *p_sec_desc = &pPrbMapElem->sec_desc[loc_sym][0];
831 p_sec_desc->section_id = sect_geninfo[i].info->id;
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;
838 print_err("section desc is NULL\n");
843 sect_geninfo[i].exDataSize = 0;
845 /* Extension 4 for modulation compression */
846 if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
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__);
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))
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)) */
860 sect_geninfo[i].info->ef = 0;
861 sect_geninfo[i].exDataSize = 0;
863 if(p_x_ctx->dssEnable == 1) {
865 dssSlot = tti % (p_x_ctx->dssPeriod);
867 ext9.technology = p_x_ctx->technology[dssSlot];
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;
874 sect_geninfo[i].info->ef = 1;
875 sect_geninfo[i].exDataSize++;
880 // xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id, §_geninfo[i].info);
882 if(pPrbMapElem->IsNewSect == 1)
884 sect_geninfo[i].info->startPrbc = pPrbMapElem->nRBStart;
885 sect_geninfo[i].info->numPrbc = pPrbMapElem->nRBSize;
890 params.numSections = i;
892 mbuf = xran_ethdi_mbuf_alloc();
893 if(unlikely(mbuf == NULL))
895 print_err("Alloc fail!\n");
897 goto _create_and_send_section_error;
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, ¶ms, cc_id, ru_port_id, seq_id,start_sect_id);
905 print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
906 frame_id, subframe_id, slot_id, dir);
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);
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);
921 cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
924 rte_pktmbuf_free(mbuf);
928 struct xran_section_info *info;
929 for (j = 0; j < nsection; j++)
931 pPrbMapElem = &prbMap->prbMap[j];
932 info = xran_cp_find_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id,j);
935 rte_panic("xran_cp_get_section_info_ptr failed\n");
937 info->startPrbc = pPrbMapElem->UP_nRBStart;
938 info->numPrbc = pPrbMapElem->UP_nRBSize;
942 _create_and_send_section_error:
943 if(XRAN_DIR_DL == dir)
945 prbElmProcInfo->nPrbElmProcessed = nsection;
952 xran_ruemul_init(void *pHandle)
954 uint16_t xran_port_id;
955 struct xran_device_ctx* p_dev = NULL;
958 p_dev = (struct xran_device_ctx* )pHandle;
959 xran_port_id = p_dev->xran_port_id;
961 print_err("Invalid pHandle - %p", pHandle);
962 return (XRAN_STATUS_FAIL);
965 if(xran_port_id < XRAN_PORTS_NUM) {
966 if(recvSections[xran_port_id]) {
967 print_err("Memory already allocated!");
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!");
977 recvCpInfo[xran_port_id].sections = recvSections[xran_port_id];
979 print_err("Incorrect xran port %d\n", xran_port_id);
988 xran_ruemul_release(void *pHandle)
990 uint16_t xran_port_id;
991 struct xran_device_ctx* p_dev = NULL;
994 p_dev = (struct xran_device_ctx* )pHandle;
995 xran_port_id = p_dev->xran_port_id;
997 print_err("Invalid pHandle - %p", pHandle);
998 return (XRAN_STATUS_FAIL);
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;
1007 print_err("Incorrect xran port %d\n", xran_port_id);