1. Update Dockerfile for CI build. But there is dependency on Intel System Studio...
[o-du/phy.git] / fhi_lib / lib / src / xran_main.c
1 /******************************************************************************\r
2 *\r
3 *   Copyright (c) 2019 Intel.\r
4 *\r
5 *   Licensed under the Apache License, Version 2.0 (the "License");\r
6 *   you may not use this file except in compliance with the License.\r
7 *   You may obtain a copy of the License at\r
8 *\r
9 *       http://www.apache.org/licenses/LICENSE-2.0\r
10 *\r
11 *   Unless required by applicable law or agreed to in writing, software\r
12 *   distributed under the License is distributed on an "AS IS" BASIS,\r
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
14 *   See the License for the specific language governing permissions and\r
15 *   limitations under the License.\r
16 *\r
17 *******************************************************************************/\r
18 \r
19 /**\r
20  * @brief XRAN main functionality module\r
21  * @file xran_main.c\r
22  * @ingroup group_source_xran\r
23  * @author Intel Corporation\r
24  **/\r
25 \r
26 #define _GNU_SOURCE\r
27 #include <sched.h>\r
28 #include <assert.h>\r
29 #include <err.h>\r
30 #include <libgen.h>\r
31 #include <sys/time.h>\r
32 #include <sys/queue.h>\r
33 #include <time.h>\r
34 #include <unistd.h>\r
35 #include <stdio.h>\r
36 #include <pthread.h>\r
37 #include <malloc.h>\r
38 \r
39 #include <rte_common.h>\r
40 #include <rte_eal.h>\r
41 #include <rte_errno.h>\r
42 #include <rte_lcore.h>\r
43 #include <rte_cycles.h>\r
44 #include <rte_memory.h>\r
45 #include <rte_memzone.h>\r
46 #include <rte_mbuf.h>\r
47 #include <rte_ring.h>\r
48 \r
49 #include "xran_fh_o_du.h"\r
50 \r
51 #include "ethdi.h"\r
52 #include "xran_pkt.h"\r
53 #include "xran_up_api.h"\r
54 #include "xran_cp_api.h"\r
55 #include "xran_sync_api.h"\r
56 #include "xran_lib_mlog_tasks_id.h"\r
57 #include "xran_timer.h"\r
58 #include "xran_common.h"\r
59 #include "xran_frame_struct.h"\r
60 #include "xran_printf.h"\r
61 #include "xran_app_frag.h"\r
62 \r
63 #include "xran_mlog_lnx.h"\r
64 \r
65 #define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) )\r
66 \r
67 #define XranOffsetSym(offSym, otaSym, numSymTotal)  (((int32_t)offSym > (int32_t)otaSym) ? \\r
68                             ((int32_t)otaSym + ((int32_t)numSymTotal) - (uint32_t)offSym) : \\r
69                             (((int32_t)otaSym - (int32_t)offSym) >= numSymTotal) ?  \\r
70                                     (((int32_t)otaSym - (int32_t)offSym) - numSymTotal) : \\r
71                                     ((int32_t)otaSym - (int32_t)offSym))\r
72 \r
73 #define MAX_NUM_OF_XRAN_CTX          (2)\r
74 #define XranIncrementCtx(ctx)                             ((ctx >= (MAX_NUM_OF_XRAN_CTX-1)) ? 0 : (ctx+1))\r
75 #define XranDecrementCtx(ctx)                             ((ctx == 0) ? (MAX_NUM_OF_XRAN_CTX-1) : (ctx-1))\r
76 \r
77 #define MAX_NUM_OF_DPDK_TIMERS       (10)\r
78 #define DpdkTimerIncrementCtx(ctx)           ((ctx >= (MAX_NUM_OF_DPDK_TIMERS-1)) ? 0 : (ctx+1))\r
79 #define DpdkTimerDecrementCtx(ctx)           ((ctx == 0) ? (MAX_NUM_OF_DPDK_TIMERS-1) : (ctx-1))\r
80 \r
81 /* Difference between Unix seconds to GPS seconds\r
82    GPS epoch: 1980.1.6 00:00:00 (UTC); Unix time epoch: 1970:1.1 00:00:00 UTC\r
83    Value is calculated on Sep.6 2019. Need to be change if International\r
84    Earth Rotation and Reference Systems Service (IERS) adds more leap seconds\r
85    1970:1.1 - 1980.1.6: 3657 days\r
86    3657*24*3600=315 964 800 seconds (unix seconds value at 1980.1.6 00:00:00 (UTC))\r
87    There are 18 leap seconds inserted after 1980.1.6 00:00:00 (UTC), which means\r
88    GPS is 18 larger. 315 964 800 - 18 = 315 964 782\r
89 */\r
90 #define UNIX_TO_GPS_SECONDS_OFFSET 315964782UL\r
91 #define NUM_OF_FRAMES_PER_SECOND 100\r
92 \r
93 //#define XRAN_CREATE_RBMAP /**< generate slot map base on symbols */\r
94 \r
95 \r
96 struct xran_timer_ctx {\r
97     uint32_t    tti_to_process;\r
98 };\r
99 \r
100 static xran_cc_handle_t pLibInstanceHandles[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR] = {NULL};\r
101 static struct xran_device_ctx g_xran_dev_ctx[XRAN_PORTS_NUM] = { 0 };\r
102 \r
103 struct xran_timer_ctx timer_ctx[MAX_NUM_OF_XRAN_CTX];\r
104 \r
105 static struct rte_timer tti_to_phy_timer[10];\r
106 static struct rte_timer sym_timer;\r
107 static struct rte_timer dpdk_timer[MAX_NUM_OF_DPDK_TIMERS];\r
108 \r
109 uint64_t interval_us = 1000;\r
110 \r
111 uint32_t xran_lib_ota_tti        = 0; /**< Slot index in a second [0:(1000000/TTI-1)] */\r
112 uint32_t xran_lib_ota_sym        = 0; /**< Symbol index in a slot [0:13] */\r
113 uint32_t xran_lib_ota_sym_idx    = 0; /**< Symbol index in a second [0 : 14*(1000000/TTI)-1]\r
114                                                 where TTI is TTI interval in microseconds */\r
115 uint16_t xran_SFN_at_Sec_Start   = 0; /**< SFN at current second start */\r
116 uint16_t xran_max_frame          = 1023; /**< value of max frame used. expected to be 99 (old compatibility mode) and 1023 as per section 9.7.2 System Frame Number Calculation */\r
117 \r
118 static uint8_t xran_cp_seq_id_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 */\r
119 static uint8_t xran_updl_seq_id_num[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR];\r
120 static uint8_t xran_upul_seq_id_num[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR]; /**< PUSCH, PRACH, SRS for Cat B */\r
121 \r
122 static uint8_t xran_section_id_curslot[XRAN_DIR_MAX][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2+ XRAN_MAX_ANT_ARRAY_ELM_NR];\r
123 static uint16_t xran_section_id[XRAN_DIR_MAX][XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR * 2+ XRAN_MAX_ANT_ARRAY_ELM_NR];\r
124 static uint64_t xran_total_tick = 0, xran_used_tick = 0;\r
125 static uint32_t xran_core_used = 0;\r
126 static int32_t first_call = 0;\r
127 \r
128 \r
129 static void\r
130 extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)\r
131 {\r
132 }\r
133 \r
134 static struct rte_mbuf_ext_shared_info share_data[XRAN_N_FE_BUF_LEN];\r
135 \r
136 void xran_timer_arm(struct rte_timer *tim, void* arg);\r
137 \r
138 int32_t xran_process_tx_sym(void *arg);\r
139 \r
140 int32_t xran_process_rx_sym(void *arg,\r
141                         struct rte_mbuf *mbuf,\r
142                         void *iq_data_start,\r
143                         uint16_t size,\r
144                         uint8_t CC_ID,\r
145                         uint8_t Ant_ID,\r
146                         uint8_t frame_id,\r
147                         uint8_t subframe_id,\r
148                         uint8_t slot_id,\r
149                         uint8_t symb_id,\r
150                         uint16_t num_prbu,\r
151                         uint16_t start_prbu,\r
152                         uint16_t sym_inc,\r
153                         uint16_t rb,\r
154                         uint16_t sect_id,\r
155                         uint32_t *mb_free);\r
156 \r
157 int32_t xran_process_prach_sym(void *arg,\r
158                         struct rte_mbuf *mbuf,\r
159                         void *iq_data_start,\r
160                         uint16_t size,\r
161                         uint8_t CC_ID,\r
162                         uint8_t Ant_ID,\r
163                         uint8_t frame_id,\r
164                         uint8_t subframe_id,\r
165                         uint8_t slot_id,\r
166                         uint8_t symb_id,\r
167                         uint16_t num_prbu,\r
168                         uint16_t start_prbu,\r
169                         uint16_t sym_inc,\r
170                         uint16_t rb,\r
171                         uint16_t sect_id,\r
172                         uint32_t *mb_free);\r
173 \r
174 int32_t xran_process_srs_sym(void *arg,\r
175                         struct rte_mbuf *mbuf,\r
176                         void *iq_data_start,\r
177                         uint16_t size,\r
178                         uint8_t CC_ID,\r
179                         uint8_t Ant_ID,\r
180                         uint8_t frame_id,\r
181                         uint8_t subframe_id,\r
182                         uint8_t slot_id,\r
183                         uint8_t symb_id,\r
184                         uint16_t num_prbu,\r
185                         uint16_t start_prbu,\r
186                         uint16_t sym_inc,\r
187                         uint16_t rb,\r
188                         uint16_t sect_id,\r
189                         uint32_t *mb_free);\r
190 \r
191 \r
192 void tti_ota_cb(struct rte_timer *tim, void *arg);\r
193 void tti_to_phy_cb(struct rte_timer *tim, void *arg);\r
194 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore);\r
195 \r
196 // Return SFN at current second start, 10 bits, [0, 1023]\r
197 static inline uint16_t xran_getSfnSecStart(void)\r
198 {\r
199     return xran_SFN_at_Sec_Start;\r
200 }\r
201 void xran_updateSfnSecStart(void)\r
202 {\r
203     uint64_t currentSecond = timing_get_current_second();\r
204     // Assume always positive\r
205     uint64_t gpsSecond = currentSecond - UNIX_TO_GPS_SECONDS_OFFSET;\r
206     uint64_t nFrames = gpsSecond * NUM_OF_FRAMES_PER_SECOND;\r
207     uint16_t sfn = (uint16_t)(nFrames % (xran_max_frame + 1));\r
208     xran_SFN_at_Sec_Start = sfn;\r
209 \r
210     tx_bytes_per_sec = tx_bytes_counter;\r
211     rx_bytes_per_sec = rx_bytes_counter;\r
212     tx_bytes_counter = 0;\r
213     rx_bytes_counter = 0;\r
214 }\r
215 \r
216 static inline int32_t xran_getSlotIdxSecond(void)\r
217 {\r
218     int32_t frameIdxSecond = xran_getSfnSecStart();\r
219     int32_t slotIndxSecond = frameIdxSecond * SLOTS_PER_SYSTEMFRAME;\r
220     return slotIndxSecond;\r
221 }\r
222 \r
223 struct xran_device_ctx *xran_dev_get_ctx(void)\r
224 {\r
225     return &g_xran_dev_ctx[0];\r
226 }\r
227 \r
228 static inline struct xran_fh_config *xran_lib_get_ctx_fhcfg(void)\r
229 {\r
230     return (&(xran_dev_get_ctx()->fh_cfg));\r
231 }\r
232 \r
233 uint16_t xran_get_beamid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id)\r
234 {\r
235     return (0);     // NO BEAMFORMING\r
236 }\r
237 \r
238 enum xran_if_state xran_get_if_state(void)\r
239 {\r
240     return xran_if_current_state;\r
241 }\r
242 \r
243 int xran_is_prach_slot(uint32_t subframe_id, uint32_t slot_id)\r
244 {\r
245     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
246     struct xran_prach_cp_config *pPrachCPConfig = &(p_xran_dev_ctx->PrachCPConfig);\r
247     int32_t is_prach_slot = 0;\r
248 \r
249     if (p_xran_dev_ctx->fh_cfg.frame_conf.nNumerology < 2){\r
250         //for FR1, in 38.211 tab 6.3.3.2-2&3 it is subframe index\r
251         if (pPrachCPConfig->isPRACHslot[subframe_id] == 1){\r
252             if (pPrachCPConfig->nrofPrachInSlot != 1)\r
253                 is_prach_slot = 1;\r
254             else{\r
255                 if (p_xran_dev_ctx->fh_cfg.frame_conf.nNumerology == 0)\r
256                     is_prach_slot = 1;\r
257                 else if (slot_id == 1)\r
258                     is_prach_slot = 1;\r
259             }\r
260         }\r
261     } else if (p_xran_dev_ctx->fh_cfg.frame_conf.nNumerology == 3){\r
262         //for FR2, 38.211 tab 6.3.3.4 it is slot index of 60kHz slot\r
263         uint32_t slotidx;\r
264         slotidx = subframe_id * SLOTNUM_PER_SUBFRAME + slot_id;\r
265         if (pPrachCPConfig->nrofPrachInSlot == 2){\r
266             if (pPrachCPConfig->isPRACHslot[slotidx>>1] == 1)\r
267                 is_prach_slot = 1;\r
268         } else {\r
269             if ((pPrachCPConfig->isPRACHslot[slotidx>>1] == 1) && ((slotidx % 2) == 1)){\r
270                 is_prach_slot = 1;\r
271             }\r
272         }\r
273     } else\r
274         print_err("Numerology %d not supported", p_xran_dev_ctx->fh_cfg.frame_conf.nNumerology);\r
275     return is_prach_slot;\r
276 }\r
277 \r
278 int xran_init_sectionid(void *pHandle)\r
279 {\r
280   int cell, ant, dir;\r
281 \r
282     for (dir = 0; dir < XRAN_DIR_MAX; dir++){\r
283         for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {\r
284             for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) {\r
285                 xran_section_id[dir][cell][ant] = 0;\r
286                 xran_section_id_curslot[dir][cell][ant] = 255;\r
287             }\r
288         }\r
289     }\r
290 \r
291     return (0);\r
292 }\r
293 \r
294 int xran_init_srs(struct xran_fh_config* pConf, struct xran_device_ctx * p_xran_dev_ctx)\r
295 {\r
296     struct xran_srs_config *p_srs = &(p_xran_dev_ctx->srs_cfg);\r
297 \r
298     if(p_srs){\r
299         p_srs->symbMask = pConf->srs_conf.symbMask;\r
300         p_srs->eAxC_offset = pConf->srs_conf.eAxC_offset;\r
301         print_dbg("SRS sym         %d\n", p_srs->symbMask );\r
302         print_dbg("SRS eAxC_offset %d\n", p_srs->eAxC_offset);\r
303     }\r
304     return (XRAN_STATUS_SUCCESS);\r
305 }\r
306 \r
307 \r
308 int xran_init_prach(struct xran_fh_config* pConf, struct xran_device_ctx * p_xran_dev_ctx)\r
309 {\r
310     int32_t i;\r
311     uint8_t slotNr;\r
312     struct xran_prach_config* pPRACHConfig = &(pConf->prach_conf);\r
313     const xRANPrachConfigTableStruct *pxRANPrachConfigTable;\r
314     uint8_t nNumerology = pConf->frame_conf.nNumerology;\r
315     uint8_t nPrachConfIdx = pPRACHConfig->nPrachConfIdx;\r
316     struct xran_prach_cp_config *pPrachCPConfig = &(p_xran_dev_ctx->PrachCPConfig);\r
317 \r
318     if (nNumerology > 2)\r
319         pxRANPrachConfigTable = &gxranPrachDataTable_mmw[nPrachConfIdx];\r
320     else if (pConf->frame_conf.nFrameDuplexType == 1)\r
321         pxRANPrachConfigTable = &gxranPrachDataTable_sub6_tdd[nPrachConfIdx];\r
322     else\r
323         pxRANPrachConfigTable = &gxranPrachDataTable_sub6_fdd[nPrachConfIdx];\r
324 \r
325     uint8_t preambleFmrt = pxRANPrachConfigTable->preambleFmrt[0];\r
326     const xRANPrachPreambleLRAStruct *pxranPreambleforLRA = &gxranPreambleforLRA[preambleFmrt];\r
327     memset(pPrachCPConfig, 0, sizeof(struct xran_prach_cp_config));\r
328     if(pConf->log_level)\r
329         printf("xRAN open PRACH config: Numerology %u ConfIdx %u, preambleFmrt %u startsymb %u, numSymbol %u, occassionsInPrachSlot %u\n", nNumerology, nPrachConfIdx, preambleFmrt, pxRANPrachConfigTable->startingSym, pxRANPrachConfigTable->duration, pxRANPrachConfigTable->occassionsInPrachSlot);\r
330 \r
331     pPrachCPConfig->filterIdx = XRAN_FILTERINDEX_PRACH_ABC;         // 3, PRACH preamble format A1~3, B1~4, C0, C2\r
332     pPrachCPConfig->startSymId = pxRANPrachConfigTable->startingSym;\r
333     pPrachCPConfig->startPrbc = pPRACHConfig->nPrachFreqStart;\r
334     pPrachCPConfig->numPrbc = (preambleFmrt >= FORMAT_A1)? 12 : 70;\r
335     pPrachCPConfig->timeOffset = pxranPreambleforLRA->nRaCp;\r
336     pPrachCPConfig->freqOffset = xran_get_freqoffset(pPRACHConfig->nPrachFreqOffset, pPRACHConfig->nPrachSubcSpacing);\r
337     pPrachCPConfig->x = pxRANPrachConfigTable->x;\r
338     pPrachCPConfig->nrofPrachInSlot = pxRANPrachConfigTable->nrofPrachInSlot;\r
339     pPrachCPConfig->y[0] = pxRANPrachConfigTable->y[0];\r
340     pPrachCPConfig->y[1] = pxRANPrachConfigTable->y[1];\r
341     if (preambleFmrt >= FORMAT_A1)\r
342     {\r
343         pPrachCPConfig->numSymbol = pxRANPrachConfigTable->duration;\r
344         pPrachCPConfig->occassionsInPrachSlot = pxRANPrachConfigTable->occassionsInPrachSlot;\r
345     }\r
346     else\r
347     {\r
348         pPrachCPConfig->numSymbol = 1;\r
349         pPrachCPConfig->occassionsInPrachSlot = 1;\r
350     }\r
351 \r
352     if(pConf->log_level)\r
353         printf("PRACH: x %u y[0] %u, y[1] %u prach slot: %u ..", pPrachCPConfig->x, pPrachCPConfig->y[0], pPrachCPConfig->y[1], pxRANPrachConfigTable->slotNr[0]);\r
354     pPrachCPConfig->isPRACHslot[pxRANPrachConfigTable->slotNr[0]] = 1;\r
355     for (i=1; i < XRAN_PRACH_CANDIDATE_SLOT; i++)\r
356     {\r
357         slotNr = pxRANPrachConfigTable->slotNr[i];\r
358         if (slotNr > 0){\r
359             pPrachCPConfig->isPRACHslot[slotNr] = 1;\r
360             if(pConf->log_level)\r
361                 printf(" %u ..", slotNr);\r
362         }\r
363     }\r
364     printf("\n");\r
365     for (i = 0; i < XRAN_MAX_SECTOR_NR; i++){\r
366         p_xran_dev_ctx->prach_start_symbol[i] = pPrachCPConfig->startSymId;\r
367         p_xran_dev_ctx->prach_last_symbol[i] = pPrachCPConfig->startSymId + pPrachCPConfig->numSymbol * pPrachCPConfig->occassionsInPrachSlot - 1;\r
368     }\r
369     if(pConf->log_level){\r
370         printf("PRACH start symbol %u lastsymbol %u\n", p_xran_dev_ctx->prach_start_symbol[0], p_xran_dev_ctx->prach_last_symbol[0]);\r
371     }\r
372 \r
373     pPrachCPConfig->eAxC_offset = xran_get_num_eAxc(NULL);\r
374     print_dbg("PRACH eAxC_offset %d\n",  pPrachCPConfig->eAxC_offset);\r
375 \r
376     return (XRAN_STATUS_SUCCESS);\r
377 }\r
378 \r
379 inline uint16_t xran_alloc_sectionid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id)\r
380 {\r
381     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
382         print_err("Invalid CC ID - %d", cc_id);\r
383         return (0);\r
384         }\r
385     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR) {  //for PRACH, ant_id starts from num_ant\r
386         print_err("Invalid antenna ID - %d", ant_id);\r
387         return (0);\r
388     }\r
389 \r
390     /* if new slot has been started,\r
391      * then initializes section id again for new start */\r
392     if(xran_section_id_curslot[dir][cc_id][ant_id] != slot_id) {\r
393         xran_section_id[dir][cc_id][ant_id] = 0;\r
394         xran_section_id_curslot[dir][cc_id][ant_id] = slot_id;\r
395     }\r
396 \r
397     return(xran_section_id[dir][cc_id][ant_id]++);\r
398 }\r
399 \r
400 int xran_init_seqid(void *pHandle)\r
401 {\r
402     int cell, dir, ant;\r
403 \r
404     for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {\r
405         for(dir=0; dir < XRAN_DIR_MAX; dir++) {\r
406             for(ant=0; ant < XRAN_MAX_ANTENNA_NR * 2; ant++)\r
407                 xran_cp_seq_id_num[cell][dir][ant] = 0;\r
408             }\r
409         for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++)\r
410                 xran_updl_seq_id_num[cell][ant] = 0;\r
411         for(ant=0; ant < XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR; ant++)\r
412                 xran_upul_seq_id_num[cell][ant] = 0;\r
413         }\r
414 \r
415     return (0);\r
416 }\r
417 \r
418 static inline uint8_t xran_get_cp_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id)\r
419 {\r
420     if(dir >= XRAN_DIR_MAX) {\r
421         print_err("Invalid direction - %d", dir);\r
422         return (0);\r
423         }\r
424     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
425         print_err("Invalid CC ID - %d", cc_id);\r
426         return (0);\r
427         }\r
428     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR) {\r
429         print_err("Invalid antenna ID - %d", ant_id);\r
430         return (0);\r
431         }\r
432 \r
433     return(xran_cp_seq_id_num[cc_id][dir][ant_id]++);\r
434 }\r
435 static inline uint8_t xran_get_updl_seqid(void *pHandle, uint8_t cc_id, uint8_t ant_id)\r
436 {\r
437     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
438         print_err("Invalid CC ID - %d", cc_id);\r
439         return (0);\r
440         }\r
441     if(ant_id >= XRAN_MAX_ANTENNA_NR) {\r
442         print_err("Invalid antenna ID - %d", ant_id);\r
443         return (0);\r
444         }\r
445 \r
446     /* Only U-Plane DL needs to get sequence ID in O-DU */\r
447     return(xran_updl_seq_id_num[cc_id][ant_id]++);\r
448 }\r
449 static inline uint8_t *xran_get_updl_seqid_addr(void *pHandle, uint8_t cc_id, uint8_t ant_id)\r
450 {\r
451     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
452         print_err("Invalid CC ID - %d", cc_id);\r
453         return (NULL);\r
454     }\r
455     if(ant_id >= XRAN_MAX_ANTENNA_NR) {\r
456         print_err("Invalid antenna ID - %d", ant_id);\r
457         return (NULL);\r
458     }\r
459 \r
460     /* Only U-Plane DL needs to get sequence ID in O-DU */\r
461     return(&xran_updl_seq_id_num[cc_id][ant_id]);\r
462 }\r
463 static inline int8_t xran_check_upul_seqid(void *pHandle, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id, uint8_t seq_id)\r
464 {\r
465 \r
466     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
467         print_err("Invalid CC ID - %d", cc_id);\r
468         return (-1);\r
469     }\r
470 \r
471     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR) {\r
472         print_err("Invalid antenna ID - %d", ant_id);\r
473         return (-1);\r
474     }\r
475 \r
476     /* O-DU needs to check the sequence ID of U-Plane UL from O-RU */\r
477     xran_upul_seq_id_num[cc_id][ant_id]++;\r
478     if(xran_upul_seq_id_num[cc_id][ant_id] == seq_id) { /* expected sequence */\r
479         return (XRAN_STATUS_SUCCESS);\r
480     } else {\r
481         print_err("expected seqid %u received %u, slot %u, ant %u cc %u", xran_upul_seq_id_num[cc_id][ant_id], seq_id, slot_id, ant_id, cc_id);\r
482         xran_upul_seq_id_num[cc_id][ant_id] = seq_id; // for next\r
483         return (-1);\r
484     }\r
485 }\r
486 \r
487 //////////////////////////////////////////\r
488 // For RU emulation\r
489 static inline uint8_t xran_get_upul_seqid(void *pHandle, uint8_t cc_id, uint8_t ant_id)\r
490 {\r
491     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
492         print_err("Invalid CC ID - %d", cc_id);\r
493         return (0);\r
494         }\r
495     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2 + XRAN_MAX_ANT_ARRAY_ELM_NR) {\r
496         print_err("Invalid antenna ID - %d", ant_id);\r
497         return (0);\r
498         }\r
499 \r
500     return(xran_upul_seq_id_num[cc_id][ant_id]++);\r
501 }\r
502 static inline uint8_t *xran_get_upul_seqid_addr(void *pHandle, uint8_t cc_id, uint8_t ant_id)\r
503 {\r
504     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
505         print_err("Invalid CC ID - %d", cc_id);\r
506         return (0);\r
507         }\r
508     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2) {\r
509         print_err("Invalid antenna ID - %d", ant_id);\r
510         return (0);\r
511         }\r
512 \r
513     return(&xran_upul_seq_id_num[cc_id][ant_id]);\r
514 }\r
515 static inline int8_t xran_check_cp_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t seq_id)\r
516 {\r
517     if(dir >= XRAN_DIR_MAX) {\r
518         print_err("Invalid direction - %d", dir);\r
519         return (-1);\r
520         }\r
521     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
522         print_err("Invalid CC ID - %d", cc_id);\r
523         return (-1);\r
524         }\r
525     if(ant_id >= XRAN_MAX_ANTENNA_NR * 2) {\r
526         print_err("Invalid antenna ID - %d", ant_id);\r
527         return (-1);\r
528         }\r
529 \r
530     xran_cp_seq_id_num[cc_id][dir][ant_id]++;\r
531     if(xran_cp_seq_id_num[cc_id][dir][ant_id] == seq_id) { /* expected sequence */\r
532         return (0);\r
533         }\r
534     else {\r
535         xran_cp_seq_id_num[cc_id][dir][ant_id] = seq_id;\r
536         return (-1);\r
537         }\r
538 }\r
539 static inline int8_t xran_check_updl_seqid(void *pHandle, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id, uint8_t seq_id)\r
540 {\r
541     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {\r
542         print_err("Invalid CC ID - %d", cc_id);\r
543         return (-1);\r
544     }\r
545 \r
546     if(ant_id >= XRAN_MAX_ANTENNA_NR) {\r
547         print_err("Invalid antenna ID - %d", ant_id);\r
548         return (-1);\r
549     }\r
550 \r
551     /* O-RU needs to check the sequence ID of U-Plane DL from O-DU */\r
552     xran_updl_seq_id_num[cc_id][ant_id]++;\r
553     if(xran_updl_seq_id_num[cc_id][ant_id] == seq_id) {\r
554         /* expected sequence */\r
555         /*print_dbg("ant %u  cc_id %u : slot_id %u : seq_id %u : expected seq_id %u\n",\r
556             ant_id, cc_id, slot_id, seq_id, xran_updl_seq_id_num[cc_id][ant_id]);*/\r
557         return (0);\r
558     } else {\r
559        /* print_err("ant %u  cc_id %u : slot_id %u : seq_id %u : expected seq_id %u\n",\r
560             ant_id, cc_id, slot_id, seq_id, xran_updl_seq_id_num[cc_id][ant_id]);*/\r
561 \r
562         xran_updl_seq_id_num[cc_id][ant_id] = seq_id;\r
563 \r
564         return (-1);\r
565     }\r
566 }\r
567 \r
568 \r
569 static struct xran_section_gen_info cpSections[XRAN_MAX_NUM_SECTIONS];\r
570 static struct xran_cp_gen_params cpInfo;\r
571 int process_cplane(struct rte_mbuf *pkt)\r
572 {\r
573   struct xran_recv_packet_info recv;\r
574 \r
575     cpInfo.sections = cpSections;\r
576     xran_parse_cp_pkt(pkt, &cpInfo, &recv);\r
577 \r
578     return (MBUF_FREE);\r
579 }\r
580 //////////////////////////////////////////\r
581 \r
582 void sym_ota_cb(struct rte_timer *tim, void *arg, unsigned long *used_tick)\r
583 {\r
584     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
585     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;\r
586     long t1 = MLogTick(), t2;\r
587     long t3;\r
588     static int32_t ctx = 0;\r
589 \r
590     if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 0){\r
591         t3 = xran_tick();\r
592         tti_ota_cb(NULL, arg);\r
593         *used_tick += get_ticks_diff(xran_tick(), t3);\r
594     }\r
595 \r
596     if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 3){\r
597         if(p_xran_dev_ctx->phy_tti_cb_done == 0){\r
598             /* rearm timer to deliver TTI event to PHY */\r
599             t3 = xran_tick();\r
600             p_xran_dev_ctx->phy_tti_cb_done = 0;\r
601             xran_timer_arm_ex(&tti_to_phy_timer[xran_lib_ota_tti % 10], tti_to_phy_cb, (void*)pTCtx, p_xran_dev_ctx->fh_init.io_cfg.timing_core);\r
602             *used_tick += get_ticks_diff(xran_tick(), t3);\r
603         }\r
604     }\r
605 \r
606     t3 = xran_tick();\r
607     if (xran_process_tx_sym(timer_ctx))\r
608     {\r
609         *used_tick += get_ticks_diff(xran_tick(), t3);\r
610     }\r
611 \r
612     /* check if there is call back to do something else on this symbol */\r
613 \r
614     struct cb_elem_entry *cb_elm;\r
615     LIST_FOREACH(cb_elm, &p_xran_dev_ctx->sym_cb_list_head[0][xran_lib_ota_sym], pointers){\r
616         if(cb_elm){\r
617             cb_elm->pSymCallback(&dpdk_timer[ctx], cb_elm->pSymCallbackTag);\r
618             ctx = DpdkTimerIncrementCtx(ctx);\r
619         }\r
620     }\r
621 \r
622     // This counter is incremented in advance before it is the time for the next symbol\r
623     xran_lib_ota_sym++;\r
624     if(xran_lib_ota_sym >= N_SYM_PER_SLOT){\r
625         xran_lib_ota_sym=0;\r
626     }\r
627 \r
628     t2 = MLogTick();\r
629     MLogTask(PID_SYM_OTA_CB, t1, t2);\r
630 }\r
631 \r
632 void tti_ota_cb(struct rte_timer *tim, void *arg)\r
633 {\r
634     uint32_t    frame_id    = 0;\r
635     uint32_t    subframe_id = 0;\r
636     uint32_t    slot_id     = 0;\r
637     uint32_t    next_tti    = 0;\r
638 \r
639     uint32_t mlogVar[10];\r
640     uint32_t mlogVarCnt = 0;\r
641     uint64_t t1 = MLogTick();\r
642     uint64_t t3 = 0;\r
643     uint32_t reg_tti  = 0;\r
644     uint32_t reg_sfn  = 0;\r
645     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;\r
646     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
647 \r
648     MLogTask(PID_TTI_TIMER, t1, MLogTick());\r
649 \r
650     /* To match TTbox */\r
651     if(xran_lib_ota_tti == 0)\r
652         reg_tti = xran_fs_get_max_slot() - 1;\r
653     else\r
654         reg_tti = xran_lib_ota_tti -1;\r
655     MLogIncrementCounter();\r
656     reg_sfn    = XranGetFrameNum(reg_tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME)*10 + XranGetSubFrameNum(reg_tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);;\r
657     /* subframe and slot */\r
658     MLogRegisterFrameSubframe(reg_sfn, reg_tti % (SLOTNUM_PER_SUBFRAME));\r
659     MLogMark(1, t1);\r
660 \r
661     slot_id     = XranGetSlotNum(xran_lib_ota_tti, SLOTNUM_PER_SUBFRAME);\r
662     subframe_id = XranGetSubFrameNum(xran_lib_ota_tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
663     frame_id    = XranGetFrameNum(xran_lib_ota_tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
664 \r
665     pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process = xran_lib_ota_tti;\r
666 \r
667     mlogVar[mlogVarCnt++] = 0x11111111;\r
668     mlogVar[mlogVarCnt++] = xran_lib_ota_tti;\r
669     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx;\r
670     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx / 14;\r
671     mlogVar[mlogVarCnt++] = frame_id;\r
672     mlogVar[mlogVarCnt++] = subframe_id;\r
673     mlogVar[mlogVarCnt++] = slot_id;\r
674     mlogVar[mlogVarCnt++] = 0;\r
675     MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());\r
676 \r
677     if(p_xran_dev_ctx->fh_init.io_cfg.id == ID_LLS_CU)\r
678         next_tti = xran_lib_ota_tti + 1;\r
679     else\r
680         next_tti = xran_lib_ota_tti;\r
681 \r
682     if(next_tti>= xran_fs_get_max_slot()){\r
683         print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id);\r
684         next_tti=0;\r
685     }\r
686 \r
687     slot_id     = XranGetSlotNum(next_tti, SLOTNUM_PER_SUBFRAME);\r
688     subframe_id = XranGetSubFrameNum(next_tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
689     frame_id    = XranGetFrameNum(next_tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
690 \r
691     print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id);\r
692 \r
693     if(p_xran_dev_ctx->fh_init.io_cfg.id == ID_LLS_CU){\r
694         pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = next_tti;\r
695     } else {\r
696         pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = pTCtx[(xran_lib_ota_tti & 1)^1].tti_to_process;\r
697     }\r
698 \r
699     p_xran_dev_ctx->phy_tti_cb_done = 0;\r
700     xran_timer_arm_ex(&tti_to_phy_timer[xran_lib_ota_tti % 10], tti_to_phy_cb, (void*)pTCtx, p_xran_dev_ctx->fh_init.io_cfg.timing_core);\r
701 \r
702     //slot index is increased to next slot at the beginning of current OTA slot\r
703     xran_lib_ota_tti++;\r
704     if(xran_lib_ota_tti >= xran_fs_get_max_slot()){\r
705         print_dbg("[%d]SFN %d sf %d slot %d\n",xran_lib_ota_tti, frame_id, subframe_id, slot_id);\r
706         xran_lib_ota_tti=0;\r
707     }\r
708     MLogTask(PID_TTI_CB, t1, MLogTick());\r
709 }\r
710 \r
711 void xran_timer_arm(struct rte_timer *tim, void* arg)\r
712 {\r
713     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
714     uint64_t t3 = MLogTick();\r
715 \r
716     if (xran_if_current_state == XRAN_RUNNING){\r
717         rte_timer_cb_t fct = (rte_timer_cb_t)arg;\r
718         rte_timer_init(tim);\r
719         rte_timer_reset_sync(tim, 0, SINGLE, p_xran_dev_ctx->fh_init.io_cfg.timing_core, fct, &timer_ctx[0]);\r
720     }\r
721     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());\r
722 }\r
723 \r
724 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore)\r
725 {\r
726     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
727     uint64_t t3 = MLogTick();\r
728 \r
729     if (xran_if_current_state == XRAN_RUNNING){\r
730         rte_timer_cb_t fct = (rte_timer_cb_t)CbFct;\r
731         rte_timer_init(tim);\r
732         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, CbArg);\r
733     }\r
734     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());\r
735 }\r
736 \r
737 int xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int tti, int cc_id,\r
738         struct xran_prb_map *prbMap, enum xran_category category,  uint8_t ctx_id)\r
739 {\r
740     struct xran_device_ctx *p_x_ctx = xran_dev_get_ctx();\r
741     struct xran_cp_gen_params params;\r
742     struct xran_section_gen_info sect_geninfo[1];\r
743     struct rte_mbuf *mbuf;\r
744     int ret = 0;\r
745     uint32_t i, j, loc_sym;\r
746     uint32_t nsection = 0;\r
747     struct xran_prb_elm *pPrbMapElem = NULL;\r
748     struct xran_prb_elm *pPrbMapElemPrev = NULL;\r
749     uint32_t slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
750     uint32_t subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
751     uint32_t frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
752 \r
753     frame_id = (frame_id & 0xff); /* ORAN frameId, 8 bits, [0, 255] */\r
754     uint8_t seq_id = 0;\r
755 \r
756     struct xran_sectionext1_info m_ext1;\r
757 \r
758     if(prbMap) {\r
759         nsection = prbMap->nPrbElm;\r
760         pPrbMapElem = &prbMap->prbMap[0];\r
761         if (nsection < 1){\r
762             print_dbg("cp[%d:%d:%d] ru_port_id %d dir=%d nsection %d\n",\r
763                                    frame_id, subframe_id, slot_id, ru_port_id, dir, nsection);\r
764         }\r
765     } else {\r
766         print_err("prbMap is NULL\n");\r
767         return (-1);\r
768     }\r
769     for (i=0; i<nsection; i++)\r
770     {\r
771         pPrbMapElem                 = &prbMap->prbMap[i];\r
772         params.dir                  = dir;\r
773         params.sectionType          = XRAN_CP_SECTIONTYPE_1;        /* Most DL/UL Radio Channels */\r
774         params.hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;\r
775         params.hdr.frameId          = frame_id;\r
776         params.hdr.subframeId       = subframe_id;\r
777         params.hdr.slotId           = slot_id;\r
778         params.hdr.startSymId       = pPrbMapElem->nStartSymb;\r
779         params.hdr.iqWidth          = pPrbMapElem->iqWidth; /*xran_get_conf_iqwidth(pHandle);*/\r
780         params.hdr.compMeth         = pPrbMapElem->compMethod;\r
781 \r
782         print_dbg("cp[%d:%d:%d] ru_port_id %d dir=%d\n",\r
783                                frame_id, subframe_id, slot_id, ru_port_id, dir);\r
784 \r
785         seq_id = xran_get_cp_seqid(pHandle, XRAN_DIR_DL, cc_id, ru_port_id);\r
786 \r
787         sect_geninfo[0].info.type        = params.sectionType;       // for database\r
788         sect_geninfo[0].info.startSymId  = params.hdr.startSymId;    // for database\r
789         sect_geninfo[0].info.iqWidth     = params.hdr.iqWidth;       // for database\r
790         sect_geninfo[0].info.compMeth    = params.hdr.compMeth;      // for database\r
791         sect_geninfo[0].info.id          = i; /*xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id);*/\r
792 \r
793         if(sect_geninfo[0].info.id > 7)\r
794             print_err("sectinfo->id %d\n", sect_geninfo[0].info.id);\r
795 \r
796         if (dir == XRAN_DIR_UL) {\r
797             for (loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++){\r
798                 struct xran_section_desc *p_sec_desc =  pPrbMapElem->p_sec_desc[loc_sym];\r
799                 if(p_sec_desc) {\r
800                     p_sec_desc->section_id   = sect_geninfo[0].info.id;\r
801                     if(p_sec_desc->pCtrl) {\r
802                         rte_pktmbuf_free(p_sec_desc->pCtrl);\r
803                         p_sec_desc->pCtrl = NULL;\r
804                         p_sec_desc->pData = NULL;\r
805                     }\r
806                 } else {\r
807                     print_err("section desc is NULL\n");\r
808                 }\r
809             }\r
810         }\r
811 \r
812         sect_geninfo[0].info.rb          = XRAN_RBIND_EVERY;\r
813         sect_geninfo[0].info.startPrbc   = pPrbMapElem->nRBStart;\r
814         sect_geninfo[0].info.numPrbc     = pPrbMapElem->nRBSize;\r
815         sect_geninfo[0].info.numSymbol   = pPrbMapElem->numSymb;\r
816         sect_geninfo[0].info.reMask      = 0xfff;\r
817         sect_geninfo[0].info.beamId      = pPrbMapElem->nBeamIndex;\r
818 \r
819         for (loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++){\r
820             struct xran_section_desc *p_sec_desc =  pPrbMapElem->p_sec_desc[loc_sym];\r
821             if(p_sec_desc) {\r
822                 p_sec_desc->section_id   = sect_geninfo[0].info.id;\r
823 \r
824                 sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;\r
825                 sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;\r
826             } else {\r
827                 print_err("section desc is NULL\n");\r
828             }\r
829         }\r
830 \r
831         if (i==0)\r
832             sect_geninfo[0].info.symInc      = XRAN_SYMBOLNUMBER_NOTINC;\r
833         else\r
834         {\r
835             pPrbMapElemPrev = &prbMap->prbMap[i-1];\r
836             if (pPrbMapElemPrev->nStartSymb == pPrbMapElem->nStartSymb)\r
837             {\r
838                 sect_geninfo[0].info.symInc      = XRAN_SYMBOLNUMBER_NOTINC;\r
839                 if (pPrbMapElemPrev->numSymb != pPrbMapElem->numSymb)\r
840                     print_err("section info error: previous numSymb %d not equal to current numSymb %d\n", pPrbMapElemPrev->numSymb, pPrbMapElem->numSymb);\r
841             }\r
842             else\r
843             {\r
844                 sect_geninfo[0].info.symInc      = XRAN_SYMBOLNUMBER_INC;\r
845                 if (pPrbMapElem->nStartSymb != (pPrbMapElemPrev->nStartSymb + pPrbMapElemPrev->numSymb))\r
846                     print_err("section info error: current startSym %d not equal to previous endSymb %d\n", pPrbMapElem->nStartSymb, pPrbMapElemPrev->nStartSymb + pPrbMapElemPrev->numSymb);\r
847             }\r
848         }\r
849 \r
850         if(category == XRAN_CATEGORY_A){\r
851             /* no extention sections for category */\r
852             sect_geninfo[0].info.ef          = 0;\r
853             sect_geninfo[0].exDataSize       = 0;\r
854         } else if (category == XRAN_CATEGORY_B) {\r
855             /*add extantion section for BF Weights if update is needed */\r
856             if(pPrbMapElem->bf_weight_update){\r
857                 memset(&m_ext1, 0, sizeof (struct xran_sectionext1_info));\r
858                 m_ext1.bfwNumber      = pPrbMapElem->bf_weight.nAntElmTRx;\r
859                 m_ext1.bfwiqWidth     = pPrbMapElem->iqWidth;\r
860                 m_ext1.bfwCompMeth    = pPrbMapElem->compMethod;\r
861                 m_ext1.p_bfwIQ        = (int16_t*)pPrbMapElem->bf_weight.p_ext_section;\r
862                 m_ext1.bfwIQ_sz       = pPrbMapElem->bf_weight.ext_section_sz;\r
863 \r
864                 sect_geninfo[0].exData[0].type = XRAN_CP_SECTIONEXTCMD_1;\r
865                 sect_geninfo[0].exData[0].len  = sizeof(m_ext1);\r
866                 sect_geninfo[0].exData[0].data = &m_ext1;\r
867 \r
868                 sect_geninfo[0].info.ef       = 1;\r
869                 sect_geninfo[0].exDataSize    = 1;\r
870             } else {\r
871                 sect_geninfo[0].info.ef          = 0;\r
872                 sect_geninfo[0].exDataSize       = 0;\r
873             }\r
874         } else {\r
875             print_err("Unsupported Category %d\n", category);\r
876             return (-1);\r
877         }\r
878 \r
879         params.numSections          = 1;//nsection;\r
880         params.sections             = sect_geninfo;\r
881 \r
882         mbuf = xran_ethdi_mbuf_alloc();\r
883         if(unlikely(mbuf == NULL)) {\r
884             print_err("Alloc fail!\n");\r
885             return (-1);\r
886         }\r
887 \r
888         ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id);\r
889         if(ret < 0) {\r
890             print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",\r
891                         frame_id, subframe_id, slot_id, dir);\r
892         } else {\r
893             /* add in the ethernet header */\r
894             struct ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));\r
895             tx_counter++;\r
896             tx_bytes_counter += rte_pktmbuf_pkt_len(mbuf);\r
897             p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI);\r
898 \r
899             /*for(i=0; i<nsection; i++)*/\r
900                 xran_cp_add_section_info(pHandle,\r
901                         dir, cc_id, ru_port_id,\r
902                         ctx_id,\r
903                         &sect_geninfo[0].info);\r
904         }\r
905     }\r
906 \r
907     return ret;\r
908 }\r
909 \r
910 void tx_cp_dl_cb(struct rte_timer *tim, void *arg)\r
911 {\r
912     long t1 = MLogTick();\r
913     int tti, buf_id;\r
914     int i, ret;\r
915     uint32_t slot_id, subframe_id, frame_id;\r
916     int cc_id;\r
917     uint8_t ctx_id;\r
918     uint8_t ant_id, num_eAxc, num_CCPorts;\r
919     void *pHandle;\r
920     int num_list;\r
921     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
922     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;\r
923 \r
924     pHandle = NULL;     // TODO: temp implemantation\r
925     num_eAxc    = xran_get_num_eAxc(pHandle);\r
926     num_CCPorts = xran_get_num_cc(pHandle);\r
927 \r
928     if(first_call && p_xran_dev_ctx->enableCP) {\r
929 \r
930         tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process;\r
931         buf_id = tti % XRAN_N_FE_BUF_LEN;\r
932 \r
933         slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
934         subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
935         frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
936         if (tti == 0){\r
937             /* Wrap around to next second */\r
938             frame_id = (frame_id + NUM_OF_FRAMES_PER_SECOND) & 0x3ff;\r
939         }\r
940 \r
941         ctx_id      = XranGetSlotNum(tti, SLOTS_PER_SYSTEMFRAME) % XRAN_MAX_SECTIONDB_CTX;\r
942 \r
943         print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);\r
944         for(ant_id = 0; ant_id < num_eAxc; ++ant_id) {\r
945             for(cc_id = 0; cc_id < num_CCPorts; cc_id++ ) {\r
946                 /* start new section information list */\r
947                 xran_cp_reset_section_info(pHandle, XRAN_DIR_DL, cc_id, ant_id, ctx_id);\r
948                 if(xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_DL) == 1) {\r
949                     if(p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList.pBuffers->pData){\r
950                         num_list = xran_cp_create_and_send_section(pHandle, ant_id, XRAN_DIR_DL, tti, cc_id,\r
951                             (struct xran_prb_map *)p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList.pBuffers->pData,\r
952                             p_xran_dev_ctx->fh_cfg.ru_conf.xranCat, ctx_id);\r
953                     } else {\r
954                         print_err("[%d]SFN %d sf %d slot %d: ant_id %d cc_id %d \n", tti, frame_id, subframe_id, slot_id, ant_id, cc_id);\r
955                     }\r
956                 } /* if(xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_DL) == 1) */\r
957             } /* for(cc_id = 0; cc_id < num_CCPorts; cc_id++) */\r
958         } /* for(ant_id = 0; ant_id < num_eAxc; ++ant_id) */\r
959         MLogTask(PID_CP_DL_CB, t1, MLogTick());\r
960     }\r
961 }\r
962 \r
963 void rx_ul_deadline_half_cb(struct rte_timer *tim, void *arg)\r
964 {\r
965     long t1 = MLogTick();\r
966     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
967     xran_status_t status;\r
968     /* half of RX for current TTI as measured against current OTA time */\r
969     int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
970     int32_t cc_id;\r
971     uint32_t nFrameIdx;\r
972     uint32_t nSubframeIdx;\r
973     uint32_t nSlotIdx;\r
974     uint64_t nSecond;\r
975 \r
976     uint32_t nXranTime  = xran_get_slot_idx(&nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);\r
977     rx_tti = nFrameIdx*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME\r
978            + nSubframeIdx*SLOTNUM_PER_SUBFRAME\r
979            + nSlotIdx;\r
980 \r
981     if(p_xran_dev_ctx->xran2phy_mem_ready == 0)\r
982         return;\r
983 \r
984     for(cc_id = 0; cc_id < xran_get_num_cc(p_xran_dev_ctx); cc_id++) {\r
985         if(p_xran_dev_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][cc_id] == 0){\r
986             struct xran_cb_tag *pTag = p_xran_dev_ctx->pCallbackTag[cc_id];\r
987             pTag->slotiId = rx_tti;\r
988             pTag->symbol  = 0; /* last 7 sym means full slot of Symb */\r
989             status = XRAN_STATUS_SUCCESS;\r
990             if(p_xran_dev_ctx->pCallback[cc_id])\r
991                p_xran_dev_ctx->pCallback[cc_id](p_xran_dev_ctx->pCallbackTag[cc_id], status);\r
992         } else {\r
993             p_xran_dev_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][cc_id] = 0;\r
994         }\r
995     }\r
996     MLogTask(PID_UP_UL_HALF_DEAD_LINE_CB, t1, MLogTick());\r
997 }\r
998 \r
999 void rx_ul_deadline_full_cb(struct rte_timer *tim, void *arg)\r
1000 {\r
1001     long t1 = MLogTick();\r
1002     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1003     xran_status_t status = 0;\r
1004     int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
1005     int32_t cc_id = 0;\r
1006     uint32_t nFrameIdx;\r
1007     uint32_t nSubframeIdx;\r
1008     uint32_t nSlotIdx;\r
1009     uint64_t nSecond;\r
1010 \r
1011     uint32_t nXranTime  = xran_get_slot_idx(&nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);\r
1012     rx_tti = nFrameIdx*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME\r
1013         + nSubframeIdx*SLOTNUM_PER_SUBFRAME\r
1014         + nSlotIdx;\r
1015 \r
1016     if(rx_tti == 0)\r
1017        rx_tti = (xran_fs_get_max_slot_SFN()-1);\r
1018     else\r
1019        rx_tti -= 1; /* end of RX for prev TTI as measured against current OTA time */\r
1020 \r
1021     if(p_xran_dev_ctx->xran2phy_mem_ready == 0)\r
1022         return;\r
1023 \r
1024     /* U-Plane */\r
1025     for(cc_id = 0; cc_id < xran_get_num_cc(p_xran_dev_ctx); cc_id++) {\r
1026         struct xran_cb_tag *pTag = p_xran_dev_ctx->pCallbackTag[cc_id];\r
1027         pTag->slotiId = rx_tti;\r
1028         pTag->symbol  = 7; /* last 7 sym means full slot of Symb */\r
1029         status = XRAN_STATUS_SUCCESS;\r
1030         if(p_xran_dev_ctx->pCallback[cc_id])\r
1031             p_xran_dev_ctx->pCallback[cc_id](p_xran_dev_ctx->pCallbackTag[cc_id], status);\r
1032 \r
1033         if(p_xran_dev_ctx->pPrachCallback[cc_id]){\r
1034             struct xran_cb_tag *pTag = p_xran_dev_ctx->pPrachCallbackTag[cc_id];\r
1035             pTag->slotiId = rx_tti;\r
1036             pTag->symbol  = 7; /* last 7 sym means full slot of Symb */\r
1037             p_xran_dev_ctx->pPrachCallback[cc_id](p_xran_dev_ctx->pPrachCallbackTag[cc_id], status);\r
1038         }\r
1039     }\r
1040 \r
1041     MLogTask(PID_UP_UL_FULL_DEAD_LINE_CB, t1, MLogTick());\r
1042 }\r
1043 \r
1044 \r
1045 void tx_cp_ul_cb(struct rte_timer *tim, void *arg)\r
1046 {\r
1047     long t1 = MLogTick();\r
1048     int tti, buf_id;\r
1049     int i, ret;\r
1050     uint32_t slot_id, subframe_id, frame_id;\r
1051     int32_t cc_id;\r
1052     int ant_id, prach_port_id;\r
1053     uint16_t beam_id;\r
1054     uint8_t num_eAxc, num_CCPorts;\r
1055     uint8_t ctx_id;\r
1056 \r
1057     void *pHandle;\r
1058     int num_list;\r
1059 \r
1060     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1061     struct xran_prach_cp_config *pPrachCPConfig = &(p_xran_dev_ctx->PrachCPConfig);\r
1062     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;\r
1063 \r
1064     pHandle     = NULL;     // TODO: temp implemantation\r
1065 \r
1066     if(xran_get_ru_category(pHandle) == XRAN_CATEGORY_A)\r
1067         num_eAxc    = xran_get_num_eAxc(pHandle);\r
1068     else\r
1069         num_eAxc    = xran_get_num_eAxcUl(pHandle);\r
1070 \r
1071     num_CCPorts = xran_get_num_cc(pHandle);\r
1072     tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process;\r
1073     buf_id = tti % XRAN_N_FE_BUF_LEN;\r
1074     slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
1075     subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
1076     frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
1077     if (tti == 0) {\r
1078         //Wrap around to next second\r
1079         frame_id = (frame_id + NUM_OF_FRAMES_PER_SECOND) & 0x3ff;\r
1080     }\r
1081     ctx_id      = XranGetSlotNum(tti, SLOTS_PER_SYSTEMFRAME) % XRAN_MAX_SECTIONDB_CTX;\r
1082 \r
1083     if(first_call && p_xran_dev_ctx->enableCP) {\r
1084 \r
1085         print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);\r
1086 \r
1087         for(ant_id = 0; ant_id < num_eAxc; ++ant_id) {\r
1088             for(cc_id = 0; cc_id < num_CCPorts; cc_id++) {\r
1089                 if(xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_UL) == 1 ||\r
1090                     xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_SP) == 1 ){\r
1091                     /* start new section information list */\r
1092                     xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, ant_id, ctx_id);\r
1093                     num_list = xran_cp_create_and_send_section(pHandle, ant_id, XRAN_DIR_UL, tti, cc_id,\r
1094                         (struct xran_prb_map *)p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList.pBuffers->pData,\r
1095                         p_xran_dev_ctx->fh_cfg.ru_conf.xranCat, ctx_id);\r
1096                 } /* if(xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_UL) == 1 */\r
1097             } /* for(cc_id = 0; cc_id < num_CCPorts; cc_id++) */\r
1098         } /* for(ant_id = 0; ant_id < num_eAxc; ++ant_id) */\r
1099 \r
1100         if(p_xran_dev_ctx->enablePrach) {\r
1101             uint32_t is_prach_slot = xran_is_prach_slot(subframe_id, slot_id);\r
1102             if(((frame_id % pPrachCPConfig->x) == pPrachCPConfig->y[0]) && (is_prach_slot==1)) {   //is prach slot\r
1103                 for(ant_id = 0; ant_id < num_eAxc; ++ant_id) {\r
1104                     for(cc_id = 0; cc_id < num_CCPorts; cc_id++) {\r
1105                         struct xran_cp_gen_params params;\r
1106                         struct xran_section_gen_info sect_geninfo[8];\r
1107                         struct rte_mbuf *mbuf = xran_ethdi_mbuf_alloc();\r
1108                         prach_port_id = ant_id + num_eAxc;\r
1109                         /* start new section information list */\r
1110                         xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, ctx_id);\r
1111 \r
1112                         beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);\r
1113                         ret = generate_cpmsg_prach(pHandle, &params, sect_geninfo, mbuf, p_xran_dev_ctx,\r
1114                                     frame_id, subframe_id, slot_id,\r
1115                                     beam_id, cc_id, prach_port_id,\r
1116                                     xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id));\r
1117                         if (ret == XRAN_STATUS_SUCCESS)\r
1118                             send_cpmsg(pHandle, mbuf, &params, sect_geninfo,\r
1119                                 cc_id, prach_port_id, xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id));\r
1120                     }\r
1121                 }\r
1122             }\r
1123         }\r
1124     } /* if(p_xran_dev_ctx->enableCP) */\r
1125 \r
1126     MLogTask(PID_CP_UL_CB, t1, MLogTick());\r
1127 }\r
1128 \r
1129 void ul_up_full_slot_cb(struct rte_timer *tim, void *arg)\r
1130 {\r
1131     long t1 = MLogTick();\r
1132     rte_pause();\r
1133     MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick());\r
1134 }\r
1135 \r
1136 void tti_to_phy_cb(struct rte_timer *tim, void *arg)\r
1137 {\r
1138     long t1 = MLogTick();\r
1139     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1140 \r
1141     p_xran_dev_ctx->phy_tti_cb_done = 1; /* DPDK called CB */\r
1142     if (first_call){\r
1143         if(p_xran_dev_ctx->ttiCb[XRAN_CB_TTI]){\r
1144             if(p_xran_dev_ctx->SkipTti[XRAN_CB_TTI] <= 0){\r
1145                 p_xran_dev_ctx->ttiCb[XRAN_CB_TTI](p_xran_dev_ctx->TtiCbParam[XRAN_CB_TTI]);\r
1146             }else{\r
1147                 p_xran_dev_ctx->SkipTti[XRAN_CB_TTI]--;\r
1148             }\r
1149         }\r
1150     } else {\r
1151         if(p_xran_dev_ctx->ttiCb[XRAN_CB_TTI]){\r
1152             int32_t tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
1153             uint32_t slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
1154             uint32_t subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
1155             uint32_t frame_id = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
1156             if((frame_id == xran_max_frame)&&(subframe_id==9)&&(slot_id == SLOTNUM_PER_SUBFRAME-1)) {  //(tti == xran_fs_get_max_slot()-1)\r
1157                 first_call = 1;\r
1158             }\r
1159         }\r
1160     }\r
1161 \r
1162     MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick());\r
1163 }\r
1164 \r
1165 int xran_timing_source_thread(void *args)\r
1166 {\r
1167     int res = 0;\r
1168     cpu_set_t cpuset;\r
1169     int32_t   do_reset = 0;\r
1170     uint64_t  t1 = 0;\r
1171     uint64_t  delta;\r
1172     int32_t   result1,i,j;\r
1173     uint32_t delay_cp_dl;\r
1174     uint32_t delay_cp_ul;\r
1175     uint32_t delay_up;\r
1176     uint32_t delay_up_ul;\r
1177     uint32_t delay_cp2up;\r
1178     uint32_t sym_cp_dl;\r
1179     uint32_t sym_cp_ul;\r
1180     uint32_t sym_up_ul;\r
1181     int32_t sym_up;\r
1182     struct sched_param sched_param;\r
1183     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1184     uint64_t tWake = 0, tWakePrev = 0, tUsed = 0;\r
1185     struct cb_elem_entry * cb_elm = NULL;\r
1186 \r
1187     /* ToS = Top of Second start +- 1.5us */\r
1188     struct timespec ts;\r
1189 \r
1190     char buff[100];\r
1191 \r
1192     xran_core_used = rte_lcore_id();\r
1193     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());\r
1194 \r
1195     /* set main thread affinity mask to CPU2 */\r
1196     sched_param.sched_priority = 98;\r
1197 \r
1198     CPU_ZERO(&cpuset);\r
1199     CPU_SET(p_xran_dev_ctx->fh_init.io_cfg.timing_core, &cpuset);\r
1200     if (result1 = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset))\r
1201     {\r
1202         printf("pthread_setaffinity_np failed: coreId = 2, result1 = %d\n",result1);\r
1203     }\r
1204     if ((result1 = pthread_setschedparam(pthread_self(), 1, &sched_param)))\r
1205     {\r
1206         printf("priority is not changed: coreId = 2, result1 = %d\n",result1);\r
1207     }\r
1208 \r
1209     if (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) {\r
1210         do {\r
1211            timespec_get(&ts, TIME_UTC);\r
1212         }while (ts.tv_nsec >1500);\r
1213         struct tm * ptm = gmtime(&ts.tv_sec);\r
1214         if(ptm){\r
1215             strftime(buff, sizeof buff, "%D %T", ptm);\r
1216             printf("O-DU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us);\r
1217         }\r
1218 \r
1219         delay_cp_dl = interval_us - p_xran_dev_ctx->fh_init.T1a_max_cp_dl;\r
1220         delay_cp_ul = interval_us - p_xran_dev_ctx->fh_init.T1a_max_cp_ul;\r
1221         delay_up    = p_xran_dev_ctx->fh_init.T1a_max_up;\r
1222         delay_up_ul = p_xran_dev_ctx->fh_init.Ta4_max;\r
1223 \r
1224         delay_cp2up = delay_up-delay_cp_dl;\r
1225 \r
1226         sym_cp_dl = delay_cp_dl*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;\r
1227         sym_cp_ul = delay_cp_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;\r
1228         sym_up_ul = delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT);\r
1229         p_xran_dev_ctx->sym_up = sym_up = -(delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT));\r
1230         p_xran_dev_ctx->sym_up_ul = sym_up_ul = (delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1);\r
1231 \r
1232         printf("Start C-plane DL %d us after TTI  [trigger on sym %d]\n", delay_cp_dl, sym_cp_dl);\r
1233         printf("Start C-plane UL %d us after TTI  [trigger on sym %d]\n", delay_cp_ul, sym_cp_ul);\r
1234         printf("Start U-plane DL %d us before OTA [offset  in sym %d]\n", delay_up, sym_up);\r
1235         printf("Start U-plane UL %d us OTA        [offset  in sym %d]\n", delay_up_ul, sym_up_ul);\r
1236 \r
1237         printf("C-plane to U-plane delay %d us after TTI\n", delay_cp2up);\r
1238         printf("Start Sym timer %ld ns\n", TX_TIMER_INTERVAL/N_SYM_PER_SLOT);\r
1239 \r
1240         cb_elm = xran_create_cb(xran_timer_arm, tx_cp_dl_cb);\r
1241         if(cb_elm){\r
1242             LIST_INSERT_HEAD(&p_xran_dev_ctx->sym_cb_list_head[0][sym_cp_dl],\r
1243                              cb_elm,\r
1244                              pointers);\r
1245         } else {\r
1246             print_err("cb_elm is NULL\n");\r
1247             res =  -1;\r
1248             goto err0;\r
1249         }\r
1250 \r
1251         cb_elm = xran_create_cb(xran_timer_arm, tx_cp_ul_cb);\r
1252         if(cb_elm){\r
1253             LIST_INSERT_HEAD(&p_xran_dev_ctx->sym_cb_list_head[0][sym_cp_ul],\r
1254                              cb_elm,\r
1255                              pointers);\r
1256         } else {\r
1257             print_err("cb_elm is NULL\n");\r
1258             res =  -1;\r
1259             goto err0;\r
1260         }\r
1261 \r
1262         /* Full slot UL OTA + delay_up_ul */\r
1263         cb_elm = xran_create_cb(xran_timer_arm, rx_ul_deadline_full_cb);\r
1264         if(cb_elm){\r
1265             LIST_INSERT_HEAD(&p_xran_dev_ctx->sym_cb_list_head[0][sym_up_ul],\r
1266                              cb_elm,\r
1267                              pointers);\r
1268         } else {\r
1269             print_err("cb_elm is NULL\n");\r
1270             res =  -1;\r
1271             goto err0;\r
1272         }\r
1273 \r
1274         /* Half slot UL OTA + delay_up_ul*/\r
1275         cb_elm = xran_create_cb(xran_timer_arm, rx_ul_deadline_half_cb);\r
1276         if(cb_elm){\r
1277             LIST_INSERT_HEAD(&p_xran_dev_ctx->sym_cb_list_head[0][sym_up_ul + N_SYM_PER_SLOT/2],\r
1278                          cb_elm,\r
1279                          pointers);\r
1280         } else {\r
1281             print_err("cb_elm is NULL\n");\r
1282             res =  -1;\r
1283             goto err0;\r
1284         }\r
1285     } else {    // APP_O_RU\r
1286         /* calcualte when to send UL U-plane */\r
1287         delay_up = p_xran_dev_ctx->fh_init.Ta3_min;\r
1288         p_xran_dev_ctx->sym_up = sym_up = delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;\r
1289         printf("Start UL U-plane %d us after OTA [offset in sym %d]\n", delay_up, sym_up);\r
1290         do {\r
1291            timespec_get(&ts, TIME_UTC);\r
1292         }while (ts.tv_nsec >1500);\r
1293         struct tm * ptm = gmtime(&ts.tv_sec);\r
1294         if(ptm){\r
1295             strftime(buff, sizeof buff, "%D %T", ptm);\r
1296             printf("RU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us);\r
1297         }\r
1298     }\r
1299 \r
1300     printf("interval_us %ld\n", interval_us);\r
1301     do {\r
1302        timespec_get(&ts, TIME_UTC);\r
1303     }while (ts.tv_nsec == 0);\r
1304 \r
1305     while(1) {\r
1306         /* Update Usage Stats */\r
1307         tWake = xran_tick();\r
1308         xran_used_tick += tUsed;\r
1309         if (tWakePrev)\r
1310         {\r
1311             xran_total_tick += get_ticks_diff(tWake, tWakePrev);\r
1312         }\r
1313         tWakePrev = tWake;\r
1314         tUsed = 0;\r
1315 \r
1316         delta = poll_next_tick(interval_us*1000L/N_SYM_PER_SLOT, &tUsed);\r
1317         if (XRAN_STOPPED == xran_if_current_state)\r
1318             break;\r
1319 \r
1320         if (likely(XRAN_RUNNING == xran_if_current_state))\r
1321             sym_ota_cb(&sym_timer, timer_ctx, &tUsed);\r
1322     }\r
1323 \r
1324     err0:\r
1325     for (i = 0; i< XRAN_MAX_SECTOR_NR; i++){\r
1326         for (j = 0; j< XRAN_NUM_OF_SYMBOL_PER_SLOT; j++){\r
1327             struct cb_elem_entry *cb_elm;\r
1328             LIST_FOREACH(cb_elm, &p_xran_dev_ctx->sym_cb_list_head[i][j], pointers){\r
1329                 if(cb_elm){\r
1330                     LIST_REMOVE(cb_elm, pointers);\r
1331                     xran_destroy_cb(cb_elm);\r
1332                 }\r
1333             }\r
1334         }\r
1335     }\r
1336 \r
1337     printf("Closing timing source thread...tx counter %lu, rx counter %lu\n", tx_counter, rx_counter);\r
1338     return res;\r
1339 }\r
1340 \r
1341 /* Handle ecpri format. */\r
1342 int handle_ecpri_ethertype(struct rte_mbuf *pkt, uint64_t rx_time)\r
1343 {\r
1344     const struct xran_ecpri_hdr *ecpri_hdr;\r
1345     unsigned long t1;\r
1346     int32_t ret = MBUF_FREE;\r
1347 \r
1348     if (rte_pktmbuf_data_len(pkt) < sizeof(struct xran_ecpri_hdr)) {\r
1349         print_err("Packet too short - %d bytes", rte_pktmbuf_data_len(pkt));\r
1350         return 0;\r
1351     }\r
1352 \r
1353     /* check eCPRI header. */\r
1354     ecpri_hdr = rte_pktmbuf_mtod(pkt, struct xran_ecpri_hdr *);\r
1355     if(ecpri_hdr == NULL){\r
1356         print_err("ecpri_hdr error\n");\r
1357         return MBUF_FREE;\r
1358     }\r
1359 \r
1360     rx_bytes_counter += rte_pktmbuf_pkt_len(pkt);\r
1361     switch(ecpri_hdr->cmnhdr.ecpri_mesg_type) {\r
1362         case ECPRI_IQ_DATA:\r
1363            // t1 = MLogTick();\r
1364             ret = process_mbuf(pkt);\r
1365           //  MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick());\r
1366             break;\r
1367         // For RU emulation\r
1368         case ECPRI_RT_CONTROL_DATA:\r
1369             t1 = MLogTick();\r
1370             if(xran_dev_get_ctx()->fh_init.io_cfg.id == O_RU) {\r
1371                 ret = process_cplane(pkt);\r
1372             } else {\r
1373                 print_err("O-DU recevied C-Plane message!");\r
1374             }\r
1375             MLogTask(PID_PROCESS_CP_PKT, t1, MLogTick());\r
1376             break;\r
1377         default:\r
1378             print_err("Invalid eCPRI message type - %d", ecpri_hdr->cmnhdr.ecpri_mesg_type);\r
1379         }\r
1380 \r
1381     return ret;\r
1382 }\r
1383 \r
1384 int xran_process_prach_sym(void *arg,\r
1385                         struct rte_mbuf *mbuf,\r
1386                         void *iq_data_start,\r
1387                         uint16_t size,\r
1388                         uint8_t CC_ID,\r
1389                         uint8_t Ant_ID,\r
1390                         uint8_t frame_id,\r
1391                         uint8_t subframe_id,\r
1392                         uint8_t slot_id,\r
1393                         uint8_t symb_id,\r
1394                         uint16_t num_prbu,\r
1395                         uint16_t start_prbu,\r
1396                         uint16_t sym_inc,\r
1397                         uint16_t rb,\r
1398                         uint16_t sect_id,\r
1399                         uint32_t *mb_free)\r
1400 {\r
1401     char        *pos = NULL;\r
1402     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1403     uint8_t symb_id_offset;\r
1404     uint32_t tti = 0;\r
1405     xran_status_t status;\r
1406     void *pHandle = NULL;\r
1407     struct rte_mbuf *mb;\r
1408 \r
1409     uint16_t iq_sample_size_bits = 16;\r
1410 \r
1411     if(p_xran_dev_ctx->xran2phy_mem_ready == 0)\r
1412         return 0;\r
1413 \r
1414     tti = frame_id * SLOTS_PER_SYSTEMFRAME + subframe_id * SLOTNUM_PER_SUBFRAME + slot_id;\r
1415 \r
1416     status = tti << 16 | symb_id;\r
1417 \r
1418     if(CC_ID < XRAN_MAX_SECTOR_NR && Ant_ID < XRAN_MAX_ANTENNA_NR && symb_id < XRAN_NUM_OF_SYMBOL_PER_SLOT){\r
1419         symb_id_offset = symb_id - p_xran_dev_ctx->prach_start_symbol[CC_ID]; //make the storing of prach packets to start from 0 for easy of processing within PHY\r
1420         pos = (char*) p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id_offset].pData;\r
1421         if(pos && iq_data_start && size){\r
1422             if (p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder == XRAN_CPU_LE_BYTE_ORDER) {\r
1423                 int idx = 0;\r
1424                 uint16_t *psrc = (uint16_t *)iq_data_start;\r
1425                 uint16_t *pdst = (uint16_t *)pos;\r
1426                 /* network byte (be) order of IQ to CPU byte order (le) */\r
1427                 for (idx = 0; idx < size/sizeof(int16_t); idx++){\r
1428                     pdst[idx]  = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_be_to_cpu_16(psrc[idx]);\r
1429                 }\r
1430                 *mb_free = MBUF_FREE;\r
1431             }else {\r
1432                 mb = p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id_offset].pCtrl;\r
1433                 if(mb){\r
1434                    rte_pktmbuf_free(mb);\r
1435                 }else{\r
1436                    print_err("mb==NULL\n");\r
1437                 }\r
1438                 p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id_offset].pData = iq_data_start;\r
1439                 p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id_offset].pCtrl = mbuf;\r
1440                 *mb_free = MBUF_KEEP;\r
1441             }\r
1442         } else {\r
1443             print_err("pos %p iq_data_start %p size %d\n",pos, iq_data_start, size);\r
1444         }\r
1445     } else {\r
1446         print_err("TTI %d(f_%d sf_%d slot_%d) CC %d Ant_ID %d symb_id %d\n",tti, frame_id, subframe_id, slot_id, CC_ID, Ant_ID, symb_id);\r
1447     }\r
1448 \r
1449 /*    if (symb_id == p_xran_dev_ctx->prach_last_symbol[CC_ID] ){\r
1450         p_xran_dev_ctx->rx_packet_prach_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id]++;\r
1451         if(p_xran_dev_ctx->rx_packet_prach_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] >= xran_get_num_eAxc(pHandle)){\r
1452             if(p_xran_dev_ctx->pPrachCallback[0])\r
1453                p_xran_dev_ctx->pPrachCallback[0](p_xran_dev_ctx->pPrachCallbackTag[0], status);\r
1454             p_xran_dev_ctx->rx_packet_prach_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] = 0;\r
1455         }\r
1456     }\r
1457 */\r
1458     return size;\r
1459 }\r
1460 \r
1461 int32_t xran_process_srs_sym(void *arg,\r
1462                         struct rte_mbuf *mbuf,\r
1463                         void *iq_data_start,\r
1464                         uint16_t size,\r
1465                         uint8_t CC_ID,\r
1466                         uint8_t Ant_ID,\r
1467                         uint8_t frame_id,\r
1468                         uint8_t subframe_id,\r
1469                         uint8_t slot_id,\r
1470                         uint8_t symb_id,\r
1471                         uint16_t num_prbu,\r
1472                         uint16_t start_prbu,\r
1473                         uint16_t sym_inc,\r
1474                         uint16_t rb,\r
1475                         uint16_t sect_id,\r
1476                         uint32_t *mb_free)\r
1477 {\r
1478     char        *pos = NULL;\r
1479     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1480     uint32_t tti = 0;\r
1481     xran_status_t status;\r
1482     void *pHandle = NULL;\r
1483     struct rte_mbuf *mb = NULL;\r
1484 \r
1485     uint16_t iq_sample_size_bits = 16;\r
1486 \r
1487     if(p_xran_dev_ctx->xran2phy_mem_ready == 0)\r
1488         return 0;\r
1489 \r
1490     tti = frame_id * SLOTS_PER_SYSTEMFRAME + subframe_id * SLOTNUM_PER_SUBFRAME + slot_id;\r
1491 \r
1492     status = tti << 16 | symb_id;\r
1493 \r
1494     if(CC_ID < XRAN_MAX_SECTOR_NR && Ant_ID < p_xran_dev_ctx->fh_cfg.nAntElmTRx && symb_id < XRAN_NUM_OF_SYMBOL_PER_SLOT) {\r
1495         pos = (char*) p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData;\r
1496         pos += start_prbu * N_SC_PER_PRB*(iq_sample_size_bits/8)*2;\r
1497         if(pos && iq_data_start && size){\r
1498             if (p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder == XRAN_CPU_LE_BYTE_ORDER) {\r
1499                 int idx = 0;\r
1500                 uint16_t *psrc = (uint16_t *)iq_data_start;\r
1501                 uint16_t *pdst = (uint16_t *)pos;\r
1502                 rte_panic("XRAN_CPU_LE_BYTE_ORDER is not supported 0x16%lx\n", (long)mb);\r
1503                 /* network byte (be) order of IQ to CPU byte order (le) */\r
1504                 for (idx = 0; idx < size/sizeof(int16_t); idx++){\r
1505                     pdst[idx]  = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_be_to_cpu_16(psrc[idx]);\r
1506                 }\r
1507             } else if (likely(p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder == XRAN_NE_BE_BYTE_ORDER)){\r
1508                 if (likely (p_xran_dev_ctx->fh_init.mtu >=\r
1509                               p_xran_dev_ctx->fh_cfg.nULRBs * N_SC_PER_PRB*(iq_sample_size_bits/8)*2)) {\r
1510                     /* no fragmentation */\r
1511                     mb = p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pCtrl;\r
1512                     if(mb){\r
1513                        rte_pktmbuf_free(mb);\r
1514                     }else{\r
1515                        print_err("mb==NULL\n");\r
1516                     }\r
1517                     p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData = iq_data_start;\r
1518                     p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pCtrl = mbuf;\r
1519                     *mb_free = MBUF_KEEP;\r
1520                 } else {\r
1521                     /* packet can be fragmented copy RBs */\r
1522                     rte_memcpy(pos, iq_data_start, size);\r
1523                     *mb_free = MBUF_FREE;\r
1524                 }\r
1525             }\r
1526         } else {\r
1527             print_err("pos %p iq_data_start %p size %d\n",pos, iq_data_start, size);\r
1528         }\r
1529     } else {\r
1530         print_err("TTI %d(f_%d sf_%d slot_%d) CC %d Ant_ID %d symb_id %d\n",tti, frame_id, subframe_id, slot_id, CC_ID, Ant_ID, symb_id);\r
1531     }\r
1532 \r
1533     return size;\r
1534 }\r
1535 \r
1536 int32_t xran_pkt_validate(void *arg,\r
1537                         struct rte_mbuf *mbuf,\r
1538                         void *iq_data_start,\r
1539                         uint16_t size,\r
1540                         uint8_t CC_ID,\r
1541                         uint8_t Ant_ID,\r
1542                         uint8_t frame_id,\r
1543                         uint8_t subframe_id,\r
1544                         uint8_t slot_id,\r
1545                         uint8_t symb_id,\r
1546                         struct ecpri_seq_id *seq_id,\r
1547                         uint16_t num_prbu,\r
1548                         uint16_t start_prbu,\r
1549                         uint16_t sym_inc,\r
1550                         uint16_t rb,\r
1551                         uint16_t sect_id)\r
1552 {\r
1553     struct xran_device_ctx * pctx = xran_dev_get_ctx();\r
1554     struct xran_common_counters *pCnt = &pctx->fh_counters;\r
1555 \r
1556     if(pctx->fh_init.io_cfg.id == O_DU) {\r
1557         if(xran_check_upul_seqid(NULL, CC_ID, Ant_ID, slot_id, seq_id->seq_id) != XRAN_STATUS_SUCCESS) {\r
1558             pCnt->Rx_pkt_dupl++;\r
1559             return (XRAN_STATUS_FAIL);\r
1560         }\r
1561     }else if(pctx->fh_init.io_cfg.id == O_RU) {\r
1562         if(xran_check_updl_seqid(NULL, CC_ID, Ant_ID, slot_id, seq_id->seq_id) != XRAN_STATUS_SUCCESS) {\r
1563             pCnt->Rx_pkt_dupl++;\r
1564             return (XRAN_STATUS_FAIL);\r
1565         }\r
1566     }else {\r
1567         print_err("incorrect dev type %d\n", pctx->fh_init.io_cfg.id);\r
1568     }\r
1569 \r
1570     rx_counter++;\r
1571 \r
1572     pCnt->Rx_on_time++;\r
1573     pCnt->Total_msgs_rcvd++;\r
1574 \r
1575     return XRAN_STATUS_SUCCESS;\r
1576 }\r
1577 \r
1578 int32_t xran_process_rx_sym(void *arg,\r
1579                         struct rte_mbuf *mbuf,\r
1580                         void *iq_data_start,\r
1581                         uint16_t size,\r
1582                         uint8_t CC_ID,\r
1583                         uint8_t Ant_ID,\r
1584                         uint8_t frame_id,\r
1585                         uint8_t subframe_id,\r
1586                         uint8_t slot_id,\r
1587                         uint8_t symb_id,\r
1588                         uint16_t num_prbu,\r
1589                         uint16_t start_prbu,\r
1590                         uint16_t sym_inc,\r
1591                         uint16_t rb,\r
1592                         uint16_t sect_id,\r
1593                         uint32_t *mb_free)\r
1594 {\r
1595     char        *pos = NULL;\r
1596     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1597     uint32_t tti = 0;\r
1598     xran_status_t status;\r
1599     void *pHandle = NULL;\r
1600     struct rte_mbuf *mb = NULL;\r
1601     struct xran_prb_map * pRbMap    = NULL;\r
1602     struct xran_prb_elm * prbMapElm = NULL;\r
1603 \r
1604     uint16_t iq_sample_size_bits = 16;\r
1605 \r
1606     tti = frame_id * SLOTS_PER_SYSTEMFRAME + subframe_id * SLOTNUM_PER_SUBFRAME + slot_id;\r
1607 \r
1608     status = tti << 16 | symb_id;\r
1609 \r
1610     if(CC_ID < XRAN_MAX_SECTOR_NR && Ant_ID < XRAN_MAX_ANTENNA_NR && symb_id < XRAN_NUM_OF_SYMBOL_PER_SLOT){\r
1611         pos = (char*) p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData;\r
1612         pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData;\r
1613         if(pRbMap){\r
1614             prbMapElm = &pRbMap->prbMap[sect_id];\r
1615             if(sect_id >= pRbMap->nPrbElm) {\r
1616                 print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm);\r
1617                 *mb_free = MBUF_FREE;\r
1618                 return size;\r
1619             }\r
1620         } else {\r
1621             print_err("pRbMap==NULL\n");\r
1622             *mb_free = MBUF_FREE;\r
1623             return size;\r
1624         }\r
1625 \r
1626         pos += start_prbu * N_SC_PER_PRB*(iq_sample_size_bits/8)*2;\r
1627         if(pos && iq_data_start && size){\r
1628             if (p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder == XRAN_CPU_LE_BYTE_ORDER) {\r
1629                 int idx = 0;\r
1630                 uint16_t *psrc = (uint16_t *)iq_data_start;\r
1631                 uint16_t *pdst = (uint16_t *)pos;\r
1632                 rte_panic("XRAN_CPU_LE_BYTE_ORDER is not supported 0x16%lx\n", (long)mb);\r
1633                 /* network byte (be) order of IQ to CPU byte order (le) */\r
1634                 for (idx = 0; idx < size/sizeof(int16_t); idx++){\r
1635                     pdst[idx]  = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_be_to_cpu_16(psrc[idx]);\r
1636                 }\r
1637             } else if (likely(p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder == XRAN_NE_BE_BYTE_ORDER)){\r
1638                 if (/*likely (p_xran_dev_ctx->fh_init.mtu >=\r
1639                               p_xran_dev_ctx->fh_cfg.nULRBs * N_SC_PER_PRB*(iq_sample_size_bits/8)*2)\r
1640                               &&  p_xran_dev_ctx->fh_init.io_cfg.id == O_DU*/ 1) {\r
1641                     if (pRbMap->nPrbElm == 1){\r
1642                         /* no fragmentation */\r
1643                         mb = p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pCtrl;\r
1644                         if(mb){\r
1645                            rte_pktmbuf_free(mb);\r
1646                         }else{\r
1647                            print_err("mb==NULL\n");\r
1648                         }\r
1649                         p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData = iq_data_start;\r
1650                         p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pCtrl = mbuf;\r
1651                         *mb_free = MBUF_KEEP;\r
1652                     } else {\r
1653                         prbMapElm = &pRbMap->prbMap[sect_id];\r
1654                         struct xran_section_desc *p_sec_desc =  prbMapElm->p_sec_desc[symb_id];\r
1655                         if(p_sec_desc){\r
1656                             mb = p_sec_desc->pCtrl;\r
1657                             if(mb){\r
1658                                rte_pktmbuf_free(mb);\r
1659                             }\r
1660                             p_sec_desc->pData         = iq_data_start;\r
1661                             p_sec_desc->pCtrl         = mbuf;\r
1662                             p_sec_desc->iq_buffer_len = size;\r
1663                             p_sec_desc->iq_buffer_offset = RTE_PTR_DIFF(iq_data_start, mbuf);\r
1664                         } else {\r
1665                             print_err("p_sec_desc==NULL\n");\r
1666                             *mb_free = MBUF_FREE;\r
1667                             return size;\r
1668                         }\r
1669                         *mb_free = MBUF_KEEP;\r
1670                     }\r
1671                 } else {\r
1672                     /* packet can be fragmented copy RBs */\r
1673                     rte_memcpy(pos, iq_data_start, size);\r
1674                     *mb_free = MBUF_FREE;\r
1675                 }\r
1676             }\r
1677         } else {\r
1678             print_err("pos %p iq_data_start %p size %d\n",pos, iq_data_start, size);\r
1679         }\r
1680     } else {\r
1681         print_err("TTI %d(f_%d sf_%d slot_%d) CC %d Ant_ID %d symb_id %d\n",tti, frame_id, subframe_id, slot_id, CC_ID, Ant_ID, symb_id);\r
1682     }\r
1683 \r
1684     return size;\r
1685 }\r
1686 \r
1687 /* Send burst of packets on an output interface */\r
1688 static inline int\r
1689 xran_send_burst(struct xran_device_ctx *dev, uint16_t n, uint16_t port)\r
1690 {\r
1691     struct rte_mbuf **m_table;\r
1692     struct rte_mbuf *m;\r
1693     int32_t i   = 0;\r
1694     int j;\r
1695     int32_t ret = 0;\r
1696 \r
1697     m_table = (struct rte_mbuf **)dev->tx_mbufs[port].m_table;\r
1698 \r
1699     for(i = 0; i < n; i++){\r
1700         rte_mbuf_sanity_check(m_table[i], 0);\r
1701         /*rte_pktmbuf_dump(stdout, m_table[i], 256);*/\r
1702         tx_counter++;\r
1703         tx_bytes_counter += rte_pktmbuf_pkt_len(m_table[i]);\r
1704         ret += dev->send_upmbuf2ring(m_table[i], ETHER_TYPE_ECPRI);\r
1705     }\r
1706 \r
1707 \r
1708     if (unlikely(ret < n)) {\r
1709         print_err("ret < n\n");\r
1710     }\r
1711 \r
1712     return 0;\r
1713 }\r
1714 \r
1715 int32_t xran_process_tx_sym_cp_off(uint8_t ctx_id, uint32_t tti, int32_t cc_id, int32_t ant_id, uint32_t frame_id, uint32_t subframe_id, uint32_t slot_id, uint32_t sym_id,\r
1716     int32_t do_srs)\r
1717 {\r
1718     int32_t     retval = 0;\r
1719     uint64_t    t1 = MLogTick();\r
1720 \r
1721     void        *pHandle = NULL;\r
1722     char        *pos = NULL;\r
1723     char        *p_sec_iq = NULL;\r
1724     char        *p_sect_iq = NULL;\r
1725     void        *mb  = NULL;\r
1726     int         prb_num = 0;\r
1727     uint16_t    iq_sample_size_bits = 16; // TODO: make dynamic per\r
1728 \r
1729     struct xran_prb_map *prb_map = NULL;\r
1730     uint8_t  num_ant_elm  = 0;\r
1731 \r
1732     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
1733     struct xran_prach_cp_config *pPrachCPConfig = &(p_xran_dev_ctx->PrachCPConfig);\r
1734     struct xran_srs_config *p_srs_cfg = &(p_xran_dev_ctx->srs_cfg);\r
1735     num_ant_elm = xran_get_num_ant_elm(pHandle);\r
1736     enum xran_pkt_dir direction;\r
1737 \r
1738     struct rte_mbuf *eth_oran_hdr = NULL;\r
1739     char        *ext_buff = NULL;\r
1740     uint16_t    ext_buff_len = 0;\r
1741     struct rte_mbuf *tmp = NULL;\r
1742     rte_iova_t ext_buff_iova = 0;\r
1743 \r
1744     struct rte_mbuf_ext_shared_info * p_share_data = &share_data[tti % XRAN_N_FE_BUF_LEN];\r
1745 \r
1746     if(p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) {\r
1747         direction = XRAN_DIR_DL; /* O-DU */\r
1748         prb_num = p_xran_dev_ctx->fh_cfg.nDLRBs;\r
1749     } else {\r
1750         direction = XRAN_DIR_UL; /* RU */\r
1751         prb_num = p_xran_dev_ctx->fh_cfg.nULRBs;\r
1752     }\r
1753 \r
1754     if(xran_fs_get_slot_type(cc_id, tti, ((p_xran_dev_ctx->fh_init.io_cfg.id == O_DU)? XRAN_SLOT_TYPE_DL : XRAN_SLOT_TYPE_UL)) ==  1\r
1755             || xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_SP) ==  1\r
1756             || xran_fs_get_slot_type(cc_id, tti, XRAN_SLOT_TYPE_FDD) ==  1){\r
1757 \r
1758         if(xran_fs_get_symbol_type(cc_id, tti, sym_id) == ((p_xran_dev_ctx->fh_init.io_cfg.id == O_DU)? XRAN_SYMBOL_TYPE_DL : XRAN_SYMBOL_TYPE_UL)\r
1759            || xran_fs_get_symbol_type(cc_id, tti, sym_id) == XRAN_SYMBOL_TYPE_FDD){\r
1760 \r
1761             if(iq_sample_size_bits != 16)\r
1762                 print_err("Incorrect iqWidth %d\n", iq_sample_size_bits );\r
1763 \r
1764             pos = (char*) p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;\r
1765             mb  = (void*) p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pCtrl;\r
1766             prb_map  = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers->pData;\r
1767 \r
1768 \r
1769             if(prb_map){\r
1770                 int32_t elmIdx = 0;\r
1771                 for (elmIdx = 0; elmIdx < prb_map->nPrbElm; elmIdx++){\r
1772                     uint16_t sec_id  = elmIdx;\r
1773                     struct xran_prb_elm * prb_map_elm = &prb_map->prbMap[elmIdx];\r
1774                     struct xran_section_desc * p_sec_desc = NULL;\r
1775 \r
1776                     if(prb_map_elm == NULL){\r
1777                         rte_panic("p_sec_desc == NULL\n");\r
1778                     }\r
1779 \r
1780                     p_sec_desc =  prb_map_elm->p_sec_desc[sym_id];\r
1781 \r
1782                     if(p_sec_desc == NULL){\r
1783                         rte_panic("p_sec_desc == NULL\n");\r
1784                     }\r
1785 \r
1786 #if 1\r
1787                     p_sec_iq = ((char*)pos + p_sec_desc->iq_buffer_offset);\r
1788 \r
1789                     /* calculete offset for external buffer */\r
1790                     ext_buff_len = p_sec_desc->iq_buffer_len;\r
1791                     ext_buff = p_sec_iq - (RTE_PKTMBUF_HEADROOM +\r
1792                                     sizeof (struct xran_ecpri_hdr) +\r
1793                                     sizeof (struct radio_app_common_hdr) +\r
1794                                     sizeof(struct data_section_hdr));\r
1795 \r
1796                     ext_buff_len += RTE_PKTMBUF_HEADROOM +\r
1797                                     sizeof (struct xran_ecpri_hdr) +\r
1798                                     sizeof (struct radio_app_common_hdr) +\r
1799                                     sizeof(struct data_section_hdr) + 18;\r
1800 \r
1801                     if(prb_map_elm->compMethod != XRAN_COMPMETHOD_NONE){\r
1802                         ext_buff     -= sizeof (struct data_section_compression_hdr);\r
1803                         ext_buff_len += sizeof (struct data_section_compression_hdr);\r
1804                     }\r
1805 \r
1806                     eth_oran_hdr =  rte_pktmbuf_alloc(_eth_mbuf_pool_small);\r
1807 \r
1808                     if (unlikely (( eth_oran_hdr) == NULL)) {\r
1809                         rte_panic("Failed rte_pktmbuf_alloc\n");\r
1810                     }\r
1811 \r
1812                     p_share_data->free_cb = extbuf_free_callback;\r
1813                     p_share_data->fcb_opaque = NULL;\r
1814                     rte_mbuf_ext_refcnt_set(p_share_data, 1);\r
1815 \r
1816                     ext_buff_iova = rte_mempool_virt2iova(mb);\r
1817                     if (unlikely (( ext_buff_iova) == 0)) {\r
1818                         rte_panic("Failed rte_mem_virt2iova \n");\r
1819                     }\r
1820 \r
1821                     if (unlikely (( (rte_iova_t)ext_buff_iova) == RTE_BAD_IOVA)) {\r
1822                         rte_panic("Failed rte_mem_virt2iova RTE_BAD_IOVA \n");\r
1823                     }\r
1824 \r
1825                     rte_pktmbuf_attach_extbuf(eth_oran_hdr,\r
1826                                               ext_buff,\r
1827                                               ext_buff_iova + RTE_PTR_DIFF(ext_buff , mb),\r
1828                                               ext_buff_len,\r
1829                                               p_share_data);\r
1830 \r
1831                     rte_pktmbuf_reset_headroom(eth_oran_hdr);\r
1832 \r
1833                     tmp = (struct rte_mbuf *)rte_pktmbuf_prepend(eth_oran_hdr, sizeof(struct ether_hdr));\r
1834                     if (unlikely (( tmp) == NULL)) {\r
1835                         rte_panic("Failed rte_pktmbuf_prepend \n");\r
1836                     }\r
1837                     mb = eth_oran_hdr;\r
1838 \r
1839                     /* first all PRBs */\r
1840                     prepare_symbol_ex(direction, sec_id,\r
1841                                       mb,\r
1842                                       (struct rb_map *)p_sec_iq,\r
1843                                       prb_map_elm->compMethod,\r
1844                                       prb_map_elm->iqWidth,\r
1845                                       p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1846                                       frame_id, subframe_id, slot_id, sym_id,\r
1847                                       prb_map_elm->nRBStart, prb_map_elm->nRBSize,\r
1848                                       cc_id, ant_id,\r
1849                                       (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1850                                           xran_get_updl_seqid(pHandle, cc_id, ant_id) :\r
1851                                           xran_get_upul_seqid(pHandle, cc_id, ant_id),\r
1852                                       0);\r
1853 \r
1854                     rte_mbuf_sanity_check((struct rte_mbuf *)mb, 0);\r
1855                     tx_counter++;\r
1856                     tx_bytes_counter += rte_pktmbuf_pkt_len((struct rte_mbuf *)mb);\r
1857                     p_xran_dev_ctx->send_upmbuf2ring((struct rte_mbuf *)mb, ETHER_TYPE_ECPRI);\r
1858 #else\r
1859         p_sect_iq = pos + p_sec_desc->iq_buffer_offset;\r
1860         prb_num = prb_map_elm->nRBSize;\r
1861 \r
1862         if( prb_num > 136 || prb_num == 0) {\r
1863             /* first 136 PRBs */\r
1864             rte_panic("first 136 PRBs\n");\r
1865             send_symbol_ex(direction,\r
1866                             sec_id,\r
1867                             NULL,\r
1868                             (struct rb_map *)p_sect_iq,\r
1869                             p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1870                             frame_id, subframe_id, slot_id, sym_id,\r
1871                             0, 136,\r
1872                             cc_id, ant_id,\r
1873                             (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1874                                 xran_get_updl_seqid(pHandle, cc_id, ant_id) :\r
1875                                 xran_get_upul_seqid(pHandle, cc_id, ant_id));\r
1876 \r
1877              pos += 136 * N_SC_PER_PRB * (iq_sample_size_bits/8)*2;\r
1878              /* last 137 PRBs */\r
1879              send_symbol_ex(direction, sec_id,\r
1880                              NULL,\r
1881                              (struct rb_map *)p_sect_iq,\r
1882                              p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1883                              frame_id, subframe_id, slot_id, sym_id,\r
1884                              136, 137,\r
1885                              cc_id, ant_id,\r
1886                              (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1887                                 xran_get_updl_seqid(pHandle, cc_id, ant_id) :\r
1888                                 xran_get_upul_seqid(pHandle,  cc_id, ant_id));\r
1889             retval = 1;\r
1890         } else {\r
1891             send_symbol_ex(direction,\r
1892                     sec_id, /* xran_alloc_sectionid(pHandle, direction, cc_id, ant_id, slot_id)*/\r
1893                     /*(struct rte_mbuf *)mb*/ NULL,\r
1894                     (struct rb_map *)p_sect_iq,\r
1895                     p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1896                     frame_id, subframe_id, slot_id, sym_id,\r
1897                     prb_map_elm->nRBStart, prb_map_elm->nRBSize,\r
1898                     cc_id, ant_id,\r
1899                     (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1900                         xran_get_updl_seqid(pHandle, cc_id, ant_id) :\r
1901                         xran_get_upul_seqid(pHandle, cc_id, ant_id));\r
1902             retval = 1;\r
1903         }\r
1904 \r
1905 #endif\r
1906 \r
1907                 }\r
1908             } else {\r
1909                 printf("(%d %d %d %d) prb_map == NULL\n", tti % XRAN_N_FE_BUF_LEN, cc_id, ant_id, sym_id);\r
1910             }\r
1911 \r
1912             if(p_xran_dev_ctx->enablePrach\r
1913               && (p_xran_dev_ctx->fh_init.io_cfg.id == O_RU)) {   /* Only RU needs to send PRACH I/Q */\r
1914                 uint32_t is_prach_slot = xran_is_prach_slot(subframe_id, slot_id);\r
1915                 if(((frame_id % pPrachCPConfig->x) == pPrachCPConfig->y[0])\r
1916                         && (is_prach_slot == 1)\r
1917                         && (sym_id >= p_xran_dev_ctx->prach_start_symbol[cc_id])\r
1918                         && (sym_id <= p_xran_dev_ctx->prach_last_symbol[cc_id])) {  //is prach slot\r
1919                         int prach_port_id = ant_id + pPrachCPConfig->eAxC_offset;\r
1920                         pos = (char*) p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[0].pData;\r
1921                         pos += (sym_id - p_xran_dev_ctx->prach_start_symbol[cc_id]) * pPrachCPConfig->numPrbc * N_SC_PER_PRB * 4;\r
1922                         mb  = NULL;//(void*) p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[0].pCtrl;\r
1923 \r
1924                         send_symbol_ex(direction,\r
1925                                 xran_alloc_sectionid(pHandle, direction, cc_id, prach_port_id, slot_id),\r
1926                                 (struct rte_mbuf *)mb,\r
1927                                 (struct rb_map *)pos,\r
1928                                 p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1929                                 frame_id, subframe_id, slot_id, sym_id,\r
1930                                 pPrachCPConfig->startPrbc, pPrachCPConfig->numPrbc,\r
1931                                 cc_id, prach_port_id,\r
1932                                 xran_get_upul_seqid(pHandle, cc_id, prach_port_id));\r
1933                         retval = 1;\r
1934                 } /* if((frame_id % pPrachCPConfig->x == pPrachCPConfig->y[0]) .... */\r
1935             } /* if(p_xran_dev_ctx->enablePrach ..... */\r
1936 \r
1937 \r
1938             if(p_xran_dev_ctx->enableSrs && (p_xran_dev_ctx->fh_init.io_cfg.id == O_RU)){\r
1939                 if( p_srs_cfg->symbMask & (1 << sym_id) /* is SRS symbol */\r
1940                     && do_srs) {\r
1941                     int32_t ant_elm_id = 0;\r
1942 \r
1943                     for (ant_elm_id = 0; ant_elm_id < num_ant_elm; ant_elm_id++){\r
1944                         int32_t ant_elm_eAxC_id = ant_elm_id + p_srs_cfg->eAxC_offset;\r
1945 \r
1946                         pos = (char*) p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_elm_id].sBufferList.pBuffers[sym_id].pData;\r
1947                         mb  = (void*) p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_elm_id].sBufferList.pBuffers[sym_id].pCtrl;\r
1948 \r
1949                         if( prb_num > 136 || prb_num == 0) {\r
1950                             uint16_t sec_id  = xran_alloc_sectionid(pHandle, direction, cc_id, ant_id, slot_id);\r
1951                             /* first 136 PRBs */\r
1952                             send_symbol_ex(direction,\r
1953                                             sec_id,\r
1954                                             NULL,\r
1955                                             (struct rb_map *)pos,\r
1956                                             p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1957                                             frame_id, subframe_id, slot_id, sym_id,\r
1958                                             0, 136,\r
1959                                             cc_id, ant_elm_eAxC_id,\r
1960                                             (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1961                                                 xran_get_updl_seqid(pHandle, cc_id, ant_elm_eAxC_id) :\r
1962                                                 xran_get_upul_seqid(pHandle, cc_id, ant_elm_eAxC_id));\r
1963 \r
1964                              pos += 136 * N_SC_PER_PRB * (iq_sample_size_bits/8)*2;\r
1965                              /* last 137 PRBs */\r
1966                              send_symbol_ex(direction, sec_id,\r
1967                                              NULL,\r
1968                                              (struct rb_map *)pos,\r
1969                                              p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1970                                              frame_id, subframe_id, slot_id, sym_id,\r
1971                                              136, 137,\r
1972                                              cc_id, ant_elm_eAxC_id,\r
1973                                              (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1974                                                 xran_get_updl_seqid(pHandle, cc_id, ant_elm_eAxC_id) :\r
1975                                                 xran_get_upul_seqid(pHandle, cc_id, ant_elm_eAxC_id));\r
1976                         } else {\r
1977                             send_symbol_ex(direction,\r
1978                                     xran_alloc_sectionid(pHandle, direction, cc_id, ant_elm_eAxC_id, slot_id),\r
1979                                     (struct rte_mbuf *)mb,\r
1980                                     (struct rb_map *)pos,\r
1981                                     p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
1982                                     frame_id, subframe_id, slot_id, sym_id,\r
1983                                     0, prb_num,\r
1984                                     cc_id, ant_elm_eAxC_id,\r
1985                                     (p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) ?\r
1986                                         xran_get_updl_seqid(pHandle, cc_id, ant_elm_eAxC_id) :\r
1987                                         xran_get_upul_seqid(pHandle, cc_id, ant_elm_eAxC_id));\r
1988                             retval = 1;\r
1989                         }\r
1990                     } /* for ant elem */\r
1991                 } /* SRS symbol */\r
1992             } /* SRS enabled */\r
1993         } /* RU mode or C-Plane is not used */\r
1994     }\r
1995 \r
1996     return retval;\r
1997 }\r
1998 \r
1999 \r
2000 int32_t xran_process_tx_sym_cp_on(uint8_t ctx_id, uint32_t tti, int32_t cc_id, int32_t ant_id, uint32_t frame_id, uint32_t subframe_id,\r
2001     uint32_t slot_id, uint32_t sym_id)\r
2002 {\r
2003     int32_t     retval = 0;\r
2004     uint64_t    t1 = MLogTick();\r
2005 \r
2006     struct rte_mbuf *eth_oran_hdr = NULL;\r
2007     char        *ext_buff = NULL;\r
2008     uint16_t    ext_buff_len = 0;\r
2009     struct rte_mbuf *tmp = NULL;\r
2010     rte_iova_t ext_buff_iova = 0;\r
2011     void        *pHandle  = NULL;\r
2012     char        *pos      = NULL;\r
2013     char        *p_sec_iq = NULL;\r
2014     void        *mb  = NULL;\r
2015     int         prb_num = 0;\r
2016     uint16_t    iq_sample_size_bits = 16; // TODO: make dynamic per\r
2017     uint32_t    next = 0;\r
2018     int32_t     num_sections = 0;\r
2019 \r
2020     struct xran_section_info *sectinfo = NULL;\r
2021     struct xran_device_ctx   *p_xran_dev_ctx = xran_dev_get_ctx();\r
2022 \r
2023     struct xran_prach_cp_config *pPrachCPConfig = &(p_xran_dev_ctx->PrachCPConfig);\r
2024     struct xran_srs_config *p_srs_cfg = &(p_xran_dev_ctx->srs_cfg);\r
2025     enum xran_pkt_dir direction;\r
2026 \r
2027     struct rte_mbuf_ext_shared_info * p_share_data = &share_data[tti % XRAN_N_FE_BUF_LEN];\r
2028 \r
2029     if(p_xran_dev_ctx->fh_init.io_cfg.id == O_DU) {\r
2030         direction = XRAN_DIR_DL; /* O-DU */\r
2031         prb_num = p_xran_dev_ctx->fh_cfg.nDLRBs;\r
2032     } else {\r
2033         direction = XRAN_DIR_UL; /* RU */\r
2034         prb_num = p_xran_dev_ctx->fh_cfg.nULRBs;\r
2035     }\r
2036 \r
2037     next = 0;\r
2038     num_sections = xran_cp_getsize_section_info(pHandle, direction, cc_id, ant_id, ctx_id);\r
2039     /* iterate C-Plane configuration to generate corresponding U-Plane */\r
2040     while(next < num_sections) {\r
2041         sectinfo = xran_cp_iterate_section_info(pHandle, direction, cc_id, ant_id, ctx_id, &next);\r
2042 \r
2043         if(sectinfo == NULL)\r
2044             break;\r
2045 \r
2046         if(sectinfo->type != XRAN_CP_SECTIONTYPE_1) {   /* only supports type 1 */\r
2047             print_err("Invalid section type in section DB - %d", sectinfo->type);\r
2048             continue;\r
2049         }\r
2050 \r
2051         /* skip, if not scheduled */\r
2052         if(sym_id < sectinfo->startSymId || sym_id >= sectinfo->startSymId + sectinfo->numSymbol)\r
2053             continue;\r
2054 \r
2055         if(sectinfo->compMeth)\r
2056             iq_sample_size_bits = sectinfo->iqWidth;\r
2057 \r
2058         print_dbg(">>> sym %2d [%d] type%d, id %d, startPrbc=%d, numPrbc=%d, numSymbol=%d\n", sym_id, next,\r
2059                         sectinfo->type, sectinfo->id, sectinfo->startPrbc,\r
2060                         sectinfo->numPrbc, sectinfo->numSymbol);\r
2061 \r
2062         p_xran_dev_ctx->tx_mbufs[0].len = 0;\r
2063         uint16_t len  = p_xran_dev_ctx->tx_mbufs[0].len;\r
2064         int16_t len2 = 0;\r
2065         uint16_t i    = 0;\r
2066 \r
2067         //Added for Klocworks\r
2068         if (len >= MBUF_TABLE_SIZE)\r
2069             len = MBUF_TABLE_SIZE - 1;\r
2070 \r
2071         pos = (char*) p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;\r
2072         mb  = p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pCtrl;\r
2073 \r
2074 #if 1\r
2075         p_sec_iq = ((char*)pos + sectinfo->sec_desc[sym_id].iq_buffer_offset);\r
2076 \r
2077         /* calculete offset for external buffer */\r
2078         ext_buff_len = sectinfo->sec_desc[sym_id].iq_buffer_len;\r
2079         ext_buff = p_sec_iq - (RTE_PKTMBUF_HEADROOM +\r
2080                         sizeof (struct xran_ecpri_hdr) +\r
2081                         sizeof (struct radio_app_common_hdr) +\r
2082                         sizeof(struct data_section_hdr));\r
2083 \r
2084         ext_buff_len += RTE_PKTMBUF_HEADROOM +\r
2085                         sizeof (struct xran_ecpri_hdr) +\r
2086                         sizeof (struct radio_app_common_hdr) +\r
2087                         sizeof(struct data_section_hdr) + 18;\r
2088 \r
2089         if(sectinfo->compMeth != XRAN_COMPMETHOD_NONE){\r
2090             ext_buff     -= sizeof (struct data_section_compression_hdr);\r
2091             ext_buff_len += sizeof (struct data_section_compression_hdr);\r
2092         }\r
2093 \r
2094         eth_oran_hdr =  rte_pktmbuf_alloc(_eth_mbuf_pool_small);\r
2095 \r
2096         if (unlikely (( eth_oran_hdr) == NULL)) {\r
2097             rte_panic("Failed rte_pktmbuf_alloc\n");\r
2098         }\r
2099 \r
2100         p_share_data->free_cb = extbuf_free_callback;\r
2101         p_share_data->fcb_opaque = NULL;\r
2102         rte_mbuf_ext_refcnt_set(p_share_data, 1);\r
2103 \r
2104         ext_buff_iova = rte_mempool_virt2iova(mb);\r
2105         if (unlikely (( ext_buff_iova) == 0)) {\r
2106             rte_panic("Failed rte_mem_virt2iova \n");\r
2107         }\r
2108 \r
2109         if (unlikely (( (rte_iova_t)ext_buff_iova) == RTE_BAD_IOVA)) {\r
2110             rte_panic("Failed rte_mem_virt2iova RTE_BAD_IOVA \n");\r
2111         }\r
2112 \r
2113         rte_pktmbuf_attach_extbuf(eth_oran_hdr,\r
2114                                   ext_buff,\r
2115                                   ext_buff_iova + RTE_PTR_DIFF(ext_buff , mb),\r
2116                                   ext_buff_len,\r
2117                                   p_share_data);\r
2118 \r
2119         rte_pktmbuf_reset_headroom(eth_oran_hdr);\r
2120 \r
2121         tmp = (struct rte_mbuf *)rte_pktmbuf_prepend(eth_oran_hdr, sizeof(struct ether_hdr));\r
2122         if (unlikely (( tmp) == NULL)) {\r
2123             rte_panic("Failed rte_pktmbuf_prepend \n");\r
2124         }\r
2125         mb = eth_oran_hdr;\r
2126 #else\r
2127         rte_pktmbuf_refcnt_update(mb, 1); /* make sure eth won't free our mbuf */\r
2128 #endif\r
2129         /* first all PRBs */\r
2130         prepare_symbol_ex(direction, sectinfo->id,\r
2131                           mb,\r
2132                           (struct rb_map *)p_sec_iq,\r
2133                           sectinfo->compMeth,\r
2134                           sectinfo->iqWidth,\r
2135                           p_xran_dev_ctx->fh_cfg.ru_conf.byteOrder,\r
2136                           frame_id, subframe_id, slot_id, sym_id,\r
2137                           sectinfo->startPrbc, sectinfo->numPrbc,\r
2138                           cc_id, ant_id,\r
2139                           xran_get_updl_seqid(pHandle, cc_id, ant_id),\r
2140                           0);\r
2141 \r
2142         /* if we don't need to do any fragmentation */\r
2143         if (likely (p_xran_dev_ctx->fh_init.mtu >=\r
2144                         sectinfo->numPrbc * (3*iq_sample_size_bits + 1))) {\r
2145             /* no fragmentation */\r
2146             p_xran_dev_ctx->tx_mbufs[0].m_table[len] = mb;\r
2147             len2 = 1;\r
2148         } else {\r
2149             /* fragmentation */\r
2150             uint8_t * seq_num = xran_get_updl_seqid_addr(pHandle, cc_id, ant_id);\r
2151             if(seq_num)\r
2152                 (*seq_num)--;\r
2153             else\r
2154                 rte_panic("pointer to seq number is NULL [CC %d Ant %d]\n", cc_id, ant_id);\r
2155 \r
2156             len2 = xran_app_fragment_packet(mb,\r
2157                                         &p_xran_dev_ctx->tx_mbufs[0].m_table[len],\r
2158                                         (uint16_t)(MBUF_TABLE_SIZE - len),\r
2159                                         p_xran_dev_ctx->fh_init.mtu,\r
2160                                         p_xran_dev_ctx->direct_pool,\r
2161                                         p_xran_dev_ctx->indirect_pool,\r
2162                                         sectinfo,\r
2163                                         seq_num);\r
2164 \r
2165             /* Free input packet */\r
2166             rte_pktmbuf_free(mb);\r
2167 \r
2168             /* If we fail to fragment the packet */\r
2169             if (unlikely (len2 < 0)){\r
2170                 print_err("len2= %d\n", len2);\r
2171                 return 0;\r
2172             }\r
2173         }\r
2174 \r
2175         if(len2 > 1){\r
2176             for (i = len; i < len + len2; i ++) {\r
2177                 struct rte_mbuf *m;\r
2178                 m = p_xran_dev_ctx->tx_mbufs[0].m_table[i];\r
2179                 struct ether_hdr *eth_hdr = (struct ether_hdr *)\r
2180                     rte_pktmbuf_prepend(m, (uint16_t)sizeof(struct ether_hdr));\r
2181                 if (eth_hdr == NULL) {\r
2182                     rte_panic("No headroom in mbuf.\n");\r
2183                 }\r
2184             }\r
2185         }\r
2186 \r
2187         len += len2;\r
2188 \r
2189         if (unlikely(len > XRAN_MAX_PKT_BURST_PER_SYM)) {\r
2190               rte_panic("XRAN_MAX_PKT_BURST_PER_SYM\n");\r
2191         }\r
2192 \r
2193         /* Transmit packets */\r
2194         xran_send_burst(p_xran_dev_ctx, (uint16_t)len, 0);\r
2195         p_xran_dev_ctx->tx_mbufs[0].len = 0;\r
2196         retval = 1;\r
2197     } /* while(section) */\r
2198 \r
2199     return retval;\r
2200 }\r
2201 \r
2202 int32_t xran_process_tx_sym(void *arg)\r
2203 {\r
2204     int32_t     retval = 0;\r
2205     uint32_t    tti=0;\r
2206 #if XRAN_MLOG_VAR\r
2207     uint32_t    mlogVar[10];\r
2208     uint32_t    mlogVarCnt = 0;\r
2209 #endif\r
2210     unsigned long t1 = MLogTick();\r
2211 \r
2212     void        *pHandle = NULL;\r
2213     int32_t     ant_id   = 0;\r
2214     int32_t     cc_id    = 0;\r
2215     uint8_t     num_eAxc = 0;\r
2216     uint8_t     num_CCPorts = 0;\r
2217     uint8_t     num_ant_elm = 0;\r
2218     uint32_t    frame_id    = 0;\r
2219     uint32_t    subframe_id = 0;\r
2220     uint32_t    slot_id     = 0;\r
2221     uint32_t    sym_id      = 0;\r
2222     uint32_t    sym_idx     = 0;\r
2223 \r
2224     uint8_t     ctx_id;\r
2225     enum xran_pkt_dir  direction;\r
2226     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2227 \r
2228     if(p_xran_dev_ctx->xran2phy_mem_ready == 0)\r
2229         return 0;\r
2230 \r
2231     /* O-RU: send symb after OTA time with delay (UL) */\r
2232     /* O-DU: send symb in advance of OTA time (DL) */\r
2233     sym_idx     = XranOffsetSym(p_xran_dev_ctx->sym_up, xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT*SLOTNUM_PER_SUBFRAME*1000);\r
2234 \r
2235     tti         = XranGetTtiNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
2236     slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
2237     subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
2238     frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
2239     // ORAN frameId, 8 bits, [0, 255]\r
2240     frame_id = (frame_id & 0xff);\r
2241 \r
2242     sym_id      = XranGetSymNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
2243     ctx_id      = XranGetSlotNum(tti, SLOTS_PER_SYSTEMFRAME) % XRAN_MAX_SECTIONDB_CTX;\r
2244 \r
2245     print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);\r
2246 \r
2247 #if XRAN_MLOG_VAR\r
2248     mlogVar[mlogVarCnt++] = 0xAAAAAAAA;\r
2249     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx;\r
2250     mlogVar[mlogVarCnt++] = sym_idx;\r
2251     mlogVar[mlogVarCnt++] = abs(p_xran_dev_ctx->sym_up);\r
2252     mlogVar[mlogVarCnt++] = tti;\r
2253     mlogVar[mlogVarCnt++] = frame_id;\r
2254     mlogVar[mlogVarCnt++] = subframe_id;\r
2255     mlogVar[mlogVarCnt++] = slot_id;\r
2256     mlogVar[mlogVarCnt++] = sym_id;\r
2257     MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());\r
2258 #endif\r
2259 \r
2260     if(p_xran_dev_ctx->fh_init.io_cfg.id == O_RU && xran_get_ru_category(pHandle) == XRAN_CATEGORY_B) {\r
2261             num_eAxc    = xran_get_num_eAxcUl(pHandle);\r
2262     } else {\r
2263             num_eAxc    = xran_get_num_eAxc(pHandle);\r
2264     }\r
2265 \r
2266     num_CCPorts = xran_get_num_cc(pHandle);\r
2267     /* U-Plane */\r
2268     for(ant_id = 0; ant_id < num_eAxc; ant_id++) {\r
2269         for(cc_id = 0; cc_id < num_CCPorts; cc_id++) {\r
2270             if(p_xran_dev_ctx->fh_init.io_cfg.id == O_DU && p_xran_dev_ctx->enableCP){\r
2271                 retval = xran_process_tx_sym_cp_on(ctx_id, tti, cc_id, ant_id, frame_id, subframe_id, slot_id, sym_id);\r
2272             } else {\r
2273                 retval = xran_process_tx_sym_cp_off(ctx_id, tti, cc_id, ant_id, frame_id, subframe_id, slot_id, sym_id, (ant_id == (num_eAxc - 1)));\r
2274             }\r
2275         } /* for(cc_id = 0; cc_id < num_CCPorts; cc_id++) */\r
2276     } /* for(ant_id = 0; ant_id < num_eAxc; ant_id++) */\r
2277 \r
2278     MLogTask(PID_PROCESS_TX_SYM, t1, MLogTick());\r
2279     return retval;\r
2280 }\r
2281 \r
2282 int xran_packet_and_dpdk_timer_thread(void *args)\r
2283 {\r
2284     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();\r
2285 \r
2286     uint64_t prev_tsc = 0;\r
2287     uint64_t cur_tsc = rte_rdtsc();\r
2288     uint64_t diff_tsc = cur_tsc - prev_tsc;\r
2289     cpu_set_t cpuset;\r
2290     struct sched_param sched_param;\r
2291     int res = 0;\r
2292     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());\r
2293 \r
2294     sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;\r
2295 \r
2296     if ((res  = pthread_setschedparam(pthread_self(), 1, &sched_param)))\r
2297     {\r
2298         printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);\r
2299     }\r
2300 \r
2301     while(1){\r
2302 \r
2303         cur_tsc  = rte_rdtsc();\r
2304         diff_tsc = cur_tsc - prev_tsc;\r
2305         if (diff_tsc > TIMER_RESOLUTION_CYCLES) {\r
2306             rte_timer_manage();\r
2307             prev_tsc = cur_tsc;\r
2308         }\r
2309 \r
2310         if (XRAN_STOPPED == xran_if_current_state)\r
2311             break;\r
2312     }\r
2313 \r
2314     printf("Closing pkts timer thread...\n");\r
2315     return 0;\r
2316 }\r
2317 \r
2318 \r
2319 int32_t xran_init(int argc, char *argv[],\r
2320            struct xran_fh_init *p_xran_fh_init, char *appName, void ** pXranLayerHandle)\r
2321 {\r
2322     int32_t i;\r
2323     int32_t j;\r
2324 \r
2325     struct xran_io_loop_cfg *p_io_cfg = (struct xran_io_loop_cfg *)&p_xran_fh_init->io_cfg;\r
2326     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2327 \r
2328     cpu_set_t system_cpuset;\r
2329     pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &system_cpuset);\r
2330     for (j = 0; j < CPU_SETSIZE; j++)\r
2331         if (CPU_ISSET(j, &system_cpuset))\r
2332             break;\r
2333 \r
2334     int32_t  lcore_id = j;\r
2335 \r
2336     char filename[64];\r
2337     int64_t offset_sec, offset_nsec;\r
2338 \r
2339     memset(p_xran_dev_ctx, 0, sizeof(struct xran_device_ctx));\r
2340 \r
2341     /* copy init */\r
2342     p_xran_dev_ctx->fh_init = *p_xran_fh_init;\r
2343 \r
2344     printf(" %s: MTU %d\n", __FUNCTION__, p_xran_dev_ctx->fh_init.mtu);\r
2345 \r
2346     xran_if_current_state = XRAN_INIT;\r
2347 \r
2348     memcpy(&(p_xran_dev_ctx->eAxc_id_cfg), &(p_xran_fh_init->eAxCId_conf), sizeof(struct xran_eaxcid_config));\r
2349 \r
2350     p_xran_dev_ctx->enableCP    = p_xran_fh_init->enableCP;\r
2351     p_xran_dev_ctx->enablePrach = p_xran_fh_init->prachEnable;\r
2352     p_xran_dev_ctx->enableSrs   = p_xran_fh_init->srsEnable;\r
2353     p_xran_dev_ctx->DynamicSectionEna = p_xran_fh_init->DynamicSectionEna;\r
2354 \r
2355     /* To make sure to set default functions */\r
2356     p_xran_dev_ctx->send_upmbuf2ring    = NULL;\r
2357     p_xran_dev_ctx->send_cpmbuf2ring    = NULL;\r
2358 \r
2359     xran_register_ethertype_handler(ETHER_TYPE_ECPRI, handle_ecpri_ethertype);\r
2360     if (p_io_cfg->id == 0)\r
2361         xran_ethdi_init_dpdk_io(p_xran_fh_init->filePrefix,\r
2362                            p_io_cfg,\r
2363                            &lcore_id,\r
2364                            (struct ether_addr *)p_xran_fh_init->p_o_du_addr,\r
2365                            (struct ether_addr *)p_xran_fh_init->p_o_ru_addr,\r
2366                            p_xran_fh_init->cp_vlan_tag,\r
2367                            p_xran_fh_init->up_vlan_tag);\r
2368     else\r
2369         xran_ethdi_init_dpdk_io(p_xran_fh_init->filePrefix,\r
2370                            p_io_cfg,\r
2371                            &lcore_id,\r
2372                            (struct ether_addr *)p_xran_fh_init->p_o_ru_addr,\r
2373                            (struct ether_addr *)p_xran_fh_init->p_o_du_addr,\r
2374                            p_xran_fh_init->cp_vlan_tag,\r
2375                            p_xran_fh_init->up_vlan_tag);\r
2376 \r
2377     for(i = 0; i < 10; i++ )\r
2378         rte_timer_init(&tti_to_phy_timer[i]);\r
2379 \r
2380     rte_timer_init(&sym_timer);\r
2381     for (i = 0; i< MAX_NUM_OF_DPDK_TIMERS; i++)\r
2382         rte_timer_init(&dpdk_timer[i]);\r
2383 \r
2384     p_xran_dev_ctx->direct_pool   = socket_direct_pool;\r
2385     p_xran_dev_ctx->indirect_pool = socket_indirect_pool;\r
2386 \r
2387     for (i = 0; i< XRAN_MAX_SECTOR_NR; i++){\r
2388         for (j = 0; j< XRAN_NUM_OF_SYMBOL_PER_SLOT; j++){\r
2389             LIST_INIT (&p_xran_dev_ctx->sym_cb_list_head[i][j]);\r
2390         }\r
2391     }\r
2392 \r
2393     printf("Set debug stop %d, debug stop count %d\n", p_xran_fh_init->debugStop, p_xran_fh_init->debugStopCount);\r
2394     timing_set_debug_stop(p_xran_fh_init->debugStop, p_xran_fh_init->debugStopCount);\r
2395 \r
2396     for (uint32_t nCellIdx = 0; nCellIdx < XRAN_MAX_SECTOR_NR; nCellIdx++){\r
2397         xran_fs_clear_slot_type(nCellIdx);\r
2398     }\r
2399 \r
2400     *pXranLayerHandle = p_xran_dev_ctx;\r
2401 \r
2402     if(p_xran_fh_init->GPS_Alpha || p_xran_fh_init->GPS_Beta ){\r
2403         offset_sec = p_xran_fh_init->GPS_Beta / 100;    //resolution of beta is 10ms\r
2404         offset_nsec = (p_xran_fh_init->GPS_Beta - offset_sec * 100) * 1e7 + p_xran_fh_init->GPS_Alpha;\r
2405         p_xran_dev_ctx->offset_sec = offset_sec;\r
2406         p_xran_dev_ctx->offset_nsec = offset_nsec;\r
2407     }else {\r
2408         p_xran_dev_ctx->offset_sec  = 0;\r
2409         p_xran_dev_ctx->offset_nsec = 0;\r
2410     }\r
2411 \r
2412     return 0;\r
2413 }\r
2414 \r
2415 int32_t xran_sector_get_instances (void * pDevHandle, uint16_t nNumInstances,\r
2416                xran_cc_handle_t * pSectorInstanceHandles)\r
2417 {\r
2418     xran_status_t nStatus = XRAN_STATUS_FAIL;\r
2419     struct xran_device_ctx *pDev = (struct xran_device_ctx *)pDevHandle;\r
2420     XranSectorHandleInfo *pCcHandle = NULL;\r
2421     int32_t i = 0;\r
2422 \r
2423     /* Check for the Valid Parameters */\r
2424     CHECK_NOT_NULL (pSectorInstanceHandles, XRAN_STATUS_INVALID_PARAM);\r
2425 \r
2426     if (!nNumInstances) {\r
2427         print_dbg("Instance is not assigned for this function !!! \n");\r
2428         return XRAN_STATUS_INVALID_PARAM;\r
2429     }\r
2430 \r
2431     for (i = 0; i < nNumInstances; i++) {\r
2432 \r
2433         /* Allocate Memory for CC handles */\r
2434         pCcHandle = (XranSectorHandleInfo *) _mm_malloc( /*"xran_cc_handles",*/ sizeof (XranSectorHandleInfo), 64);\r
2435 \r
2436         if(pCcHandle == NULL)\r
2437             return XRAN_STATUS_RESOURCE;\r
2438 \r
2439         memset (pCcHandle, 0, (sizeof (XranSectorHandleInfo)));\r
2440 \r
2441         pCcHandle->nIndex    = i;\r
2442         pCcHandle->nXranPort = pDev->xran_port_id;\r
2443 \r
2444         printf("%s [%d]: CC %d handle %p\n", __FUNCTION__, pDev->xran_port_id, i, pCcHandle);\r
2445         pLibInstanceHandles[pDev->xran_port_id][i] = pSectorInstanceHandles[i] = pCcHandle;\r
2446 \r
2447         printf("Handle: %p Instance: %p\n",\r
2448             &pSectorInstanceHandles[i], pSectorInstanceHandles[i]);\r
2449     }\r
2450 \r
2451     return XRAN_STATUS_SUCCESS;\r
2452 }\r
2453 \r
2454 int32_t xran_mm_init (void * pHandle, uint64_t nMemorySize,\r
2455             uint32_t nMemorySegmentSize)\r
2456 {\r
2457     /* we use mbuf from dpdk memory */\r
2458     return 0;\r
2459 }\r
2460 \r
2461 int32_t xran_bm_init (void * pHandle, uint32_t * pPoolIndex, uint32_t nNumberOfBuffers, uint32_t nBufferSize)\r
2462 {\r
2463     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2464     uint32_t nAllocBufferSize;\r
2465 \r
2466     char pool_name[RTE_MEMPOOL_NAMESIZE];\r
2467 \r
2468     snprintf(pool_name, RTE_MEMPOOL_NAMESIZE, "ru_%d_cc_%d_idx_%d",\r
2469         pXranCc->nXranPort, pXranCc->nIndex, pXranCc->nBufferPoolIndex);\r
2470 \r
2471     nAllocBufferSize = nBufferSize + sizeof(struct ether_hdr) +\r
2472         sizeof (struct xran_ecpri_hdr) +\r
2473         sizeof (struct radio_app_common_hdr) +\r
2474         sizeof(struct data_section_hdr) + 256;\r
2475 \r
2476     if(nAllocBufferSize >= UINT16_MAX) {\r
2477         rte_panic("nAllocBufferSize is failed [ handle %p %d %d ] [nPoolIndex %d] nNumberOfBuffers %d nBufferSize %d nAllocBufferSize %d\n",\r
2478                     pXranCc, pXranCc->nXranPort, pXranCc->nIndex, pXranCc->nBufferPoolIndex, nNumberOfBuffers, nBufferSize, nAllocBufferSize);\r
2479         return -1;\r
2480     }\r
2481 \r
2482     printf("%s: [ handle %p %d %d ] [nPoolIndex %d] nNumberOfBuffers %d nBufferSize %d\n", pool_name,\r
2483                         pXranCc, pXranCc->nXranPort, pXranCc->nIndex, pXranCc->nBufferPoolIndex, nNumberOfBuffers, nBufferSize);\r
2484 \r
2485     pXranCc->p_bufferPool[pXranCc->nBufferPoolIndex] = rte_pktmbuf_pool_create(pool_name, nNumberOfBuffers,\r
2486                                                                                MBUF_CACHE, 0, nAllocBufferSize, rte_socket_id());\r
2487 \r
2488     if(pXranCc->p_bufferPool[pXranCc->nBufferPoolIndex] == NULL){\r
2489         rte_panic("rte_pktmbuf_pool_create failed [ handle %p %d %d ] [nPoolIndex %d] nNumberOfBuffers %d nBufferSize %d errno %s\n",\r
2490                     pXranCc, pXranCc->nXranPort, pXranCc->nIndex, pXranCc->nBufferPoolIndex, nNumberOfBuffers, nBufferSize, rte_strerror(rte_errno));\r
2491         return -1;\r
2492     }\r
2493 \r
2494     pXranCc->bufferPoolElmSz[pXranCc->nBufferPoolIndex]  = nBufferSize;\r
2495     pXranCc->bufferPoolNumElm[pXranCc->nBufferPoolIndex] = nNumberOfBuffers;\r
2496 \r
2497     printf("CC:[ handle %p ru %d cc_idx %d ] [nPoolIndex %d] mb pool %p \n",\r
2498                 pXranCc, pXranCc->nXranPort, pXranCc->nIndex,\r
2499                     pXranCc->nBufferPoolIndex,  pXranCc->p_bufferPool[pXranCc->nBufferPoolIndex]);\r
2500 \r
2501     *pPoolIndex = pXranCc->nBufferPoolIndex++;\r
2502 \r
2503     return 0;\r
2504 }\r
2505 \r
2506 int32_t xran_bm_allocate_buffer(void * pHandle, uint32_t nPoolIndex, void **ppData,  void **ppCtrl)\r
2507 {\r
2508     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2509     *ppData = NULL;\r
2510     *ppCtrl = NULL;\r
2511 \r
2512     struct rte_mbuf * mb =  rte_pktmbuf_alloc(pXranCc->p_bufferPool[nPoolIndex]);\r
2513 \r
2514     if(mb){\r
2515         char * start     = rte_pktmbuf_append(mb, pXranCc->bufferPoolElmSz[nPoolIndex]);\r
2516         char * ethhdr    = rte_pktmbuf_prepend(mb, sizeof(struct ether_hdr));\r
2517 \r
2518         if(start && ethhdr){\r
2519             char * iq_offset = rte_pktmbuf_mtod(mb, char * );\r
2520             /* skip headers */\r
2521             iq_offset = iq_offset + sizeof(struct ether_hdr) +\r
2522                                     sizeof (struct xran_ecpri_hdr) +\r
2523                                     sizeof (struct radio_app_common_hdr) +\r
2524                                     sizeof(struct data_section_hdr);\r
2525 \r
2526             if (0) /* if compression */\r
2527                 iq_offset += sizeof (struct data_section_compression_hdr);\r
2528 \r
2529             *ppData = (void *)iq_offset;\r
2530             *ppCtrl  = (void *)mb;\r
2531         } else {\r
2532             print_err("[nPoolIndex %d] start ethhdr failed \n", nPoolIndex );\r
2533             return -1;\r
2534         }\r
2535     } else {\r
2536         print_err("[nPoolIndex %d] mb alloc failed \n", nPoolIndex );\r
2537         return -1;\r
2538     }\r
2539 \r
2540     if (*ppData ==  NULL){\r
2541         print_err("[nPoolIndex %d] rte_pktmbuf_append for %d failed \n", nPoolIndex, pXranCc->bufferPoolElmSz[nPoolIndex]);\r
2542         return -1;\r
2543     }\r
2544 \r
2545     return 0;\r
2546 }\r
2547 \r
2548 int32_t xran_bm_free_buffer(void * pHandle, void *pData, void *pCtrl)\r
2549 {\r
2550     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2551 \r
2552     if(pCtrl)\r
2553         rte_pktmbuf_free(pCtrl);\r
2554 \r
2555     return 0;\r
2556 }\r
2557 \r
2558 int32_t xran_5g_fronthault_config (void * pHandle,\r
2559                 struct xran_buffer_list *pSrcBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],\r
2560                 struct xran_buffer_list *pSrcCpBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],\r
2561                 struct xran_buffer_list *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],\r
2562                 struct xran_buffer_list *pDstCpBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],\r
2563                 xran_transport_callback_fn pCallback,\r
2564                 void *pCallbackTag)\r
2565 {\r
2566     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2567     xran_status_t nStatus = XRAN_STATUS_SUCCESS;\r
2568     int j, i = 0, z, k;\r
2569     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2570 \r
2571     print_dbg("%s\n", __FUNCTION__);\r
2572 \r
2573     if(NULL == pHandle)\r
2574     {\r
2575         printf("Handle is NULL!\n");\r
2576         return XRAN_STATUS_FAIL;\r
2577     }\r
2578 \r
2579     if (pCallback == NULL)\r
2580     {\r
2581         printf ("no callback\n");\r
2582         return XRAN_STATUS_FAIL;\r
2583     }\r
2584 \r
2585     i = pXranCc->nIndex;\r
2586 \r
2587     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)\r
2588     {\r
2589         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){\r
2590             /* U-plane TX */\r
2591 \r
2592             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0;\r
2593             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2594             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2595             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2596             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;\r
2597             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFrontHaulTxBuffers[j][i][z][0];\r
2598 \r
2599             p_xran_dev_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList =   *pSrcBuffer[z][j];\r
2600 \r
2601             /* C-plane TX */\r
2602             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].bValid = 0;\r
2603             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2604             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2605             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2606             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;\r
2607             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFrontHaulTxPrbMapBuffers[j][i][z][0];\r
2608 \r
2609             p_xran_dev_ctx->sFrontHaulTxPrbMapBbuIoBufCtrl[j][i][z].sBufferList =   *pSrcCpBuffer[z][j];\r
2610 \r
2611             /* U-plane RX */\r
2612 \r
2613             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0;\r
2614             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2615             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2616             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2617             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;\r
2618             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFrontHaulRxBuffers[j][i][z][0];\r
2619 \r
2620             p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList =   *pDstBuffer[z][j];\r
2621 \r
2622             /* C-plane RX */\r
2623             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].bValid = 0;\r
2624             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2625             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2626             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2627             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;\r
2628             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFrontHaulRxPrbMapBuffers[j][i][z][0];\r
2629 \r
2630             p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[j][i][z].sBufferList =   *pDstCpBuffer[z][j];\r
2631         }\r
2632     }\r
2633 \r
2634 \r
2635     p_xran_dev_ctx->pCallback[i]    = pCallback;\r
2636     p_xran_dev_ctx->pCallbackTag[i] = pCallbackTag;\r
2637 \r
2638     p_xran_dev_ctx->xran2phy_mem_ready = 1;\r
2639 \r
2640     return nStatus;\r
2641 }\r
2642 \r
2643 int32_t xran_5g_prach_req (void *  pHandle,\r
2644                 struct xran_buffer_list *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],\r
2645                 xran_transport_callback_fn pCallback,\r
2646                 void *pCallbackTag)\r
2647 {\r
2648     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2649     xran_status_t nStatus = XRAN_STATUS_SUCCESS;\r
2650     int j, i = 0, z;\r
2651     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2652 \r
2653     if(NULL == pHandle)\r
2654     {\r
2655         printf("Handle is NULL!\n");\r
2656         return XRAN_STATUS_FAIL;\r
2657     }\r
2658     if (pCallback == NULL)\r
2659     {\r
2660         printf ("no callback\n");\r
2661         return XRAN_STATUS_FAIL;\r
2662     }\r
2663 \r
2664     i = pXranCc->nIndex;\r
2665 \r
2666     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)\r
2667     {\r
2668         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){\r
2669            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0;\r
2670            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2671            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2672            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2673            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number.\r
2674            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFHPrachRxBuffers[j][i][z][0];\r
2675            p_xran_dev_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList =   *pDstBuffer[z][j];\r
2676         }\r
2677     }\r
2678 \r
2679     p_xran_dev_ctx->pPrachCallback[i]    = pCallback;\r
2680     p_xran_dev_ctx->pPrachCallbackTag[i] = pCallbackTag;\r
2681 \r
2682     return 0;\r
2683 }\r
2684 \r
2685 \r
2686 int32_t xran_5g_srs_req (void *  pHandle,\r
2687                 struct xran_buffer_list *pDstBuffer[XRAN_MAX_ANT_ARRAY_ELM_NR][XRAN_N_FE_BUF_LEN],\r
2688                 xran_transport_callback_fn pCallback,\r
2689                 void *pCallbackTag)\r
2690 {\r
2691     XranSectorHandleInfo* pXranCc = (XranSectorHandleInfo*) pHandle;\r
2692     xran_status_t nStatus = XRAN_STATUS_SUCCESS;\r
2693     int j, i = 0, z;\r
2694     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2695 \r
2696     if(NULL == pHandle)\r
2697     {\r
2698         printf("Handle is NULL!\n");\r
2699         return XRAN_STATUS_FAIL;\r
2700     }\r
2701     if (pCallback == NULL)\r
2702     {\r
2703         printf ("no callback\n");\r
2704         return XRAN_STATUS_FAIL;\r
2705     }\r
2706 \r
2707     i = pXranCc->nIndex;\r
2708 \r
2709     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)\r
2710     {\r
2711         for(z = 0; z < XRAN_MAX_ANT_ARRAY_ELM_NR; z++){\r
2712            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].bValid = 0;\r
2713            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;\r
2714            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;\r
2715            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;\r
2716            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANT_ARRAY_ELM_NR; // ant number.\r
2717            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_dev_ctx->sFHSrsRxBuffers[j][i][z][0];\r
2718            p_xran_dev_ctx->sFHSrsRxBbuIoBufCtrl[j][i][z].sBufferList =   *pDstBuffer[z][j];\r
2719         }\r
2720     }\r
2721 \r
2722     p_xran_dev_ctx->pSrsCallback[i]    = pCallback;\r
2723     p_xran_dev_ctx->pSrsCallbackTag[i] = pCallbackTag;\r
2724 \r
2725     return 0;\r
2726 }\r
2727 \r
2728 uint32_t xran_get_time_stats(uint64_t *total_time, uint64_t *used_time, uint32_t *core_used, uint32_t clear)\r
2729 {\r
2730     *total_time = xran_total_tick;\r
2731     *used_time = xran_used_tick;\r
2732     *core_used = xran_core_used;\r
2733 \r
2734     if (clear)\r
2735     {\r
2736         xran_total_tick = 0;\r
2737         xran_used_tick = 0;\r
2738     }\r
2739 \r
2740     return 0;\r
2741 }\r
2742 \r
2743 void * xran_malloc(size_t buf_len)\r
2744 {\r
2745     return rte_malloc("External buffer", buf_len, RTE_CACHE_LINE_SIZE);\r
2746 }\r
2747 \r
2748 uint8_t  *xran_add_hdr_offset(uint8_t  *dst, int16_t compMethod)\r
2749 {\r
2750     dst+= (RTE_PKTMBUF_HEADROOM +\r
2751           sizeof (struct xran_ecpri_hdr) +\r
2752           sizeof (struct radio_app_common_hdr) +\r
2753           sizeof(struct data_section_hdr));\r
2754 \r
2755     if(compMethod != XRAN_COMPMETHOD_NONE)\r
2756           dst += sizeof (struct data_section_compression_hdr);\r
2757 \r
2758     dst = RTE_PTR_ALIGN_CEIL(dst, 64);\r
2759 \r
2760     return dst;\r
2761 }\r
2762 \r
2763 int32_t xran_open(void *pHandle, struct xran_fh_config* pConf)\r
2764 {\r
2765     int32_t i;\r
2766     uint8_t nNumerology = 0;\r
2767     int32_t  lcore_id = 0;\r
2768     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2769     struct xran_fh_config *pFhCfg;\r
2770     pFhCfg = &(p_xran_dev_ctx->fh_cfg);\r
2771 \r
2772     memcpy(pFhCfg, pConf, sizeof(struct xran_fh_config));\r
2773 \r
2774     if(pConf->log_level)\r
2775         printf(" %s: O-RU Category %s\n", __FUNCTION__, (pFhCfg->ru_conf.xranCat == XRAN_CATEGORY_A) ? "A" : "B");\r
2776 \r
2777     nNumerology = xran_get_conf_numerology(pHandle);\r
2778 \r
2779     if (pConf->nCC > XRAN_MAX_SECTOR_NR)\r
2780     {\r
2781         if(pConf->log_level)\r
2782             printf("Number of cells %d exceeds max number supported %d!\n", pConf->nCC, XRAN_MAX_SECTOR_NR);\r
2783         pConf->nCC = XRAN_MAX_SECTOR_NR;\r
2784 \r
2785     }\r
2786     if(pConf->ru_conf.iqOrder != XRAN_I_Q_ORDER\r
2787         || pConf->ru_conf.byteOrder != XRAN_NE_BE_BYTE_ORDER ){\r
2788 \r
2789         print_err("Byte order and/or IQ order is not supported [IQ %d byte %d]\n", pConf->ru_conf.iqOrder, pConf->ru_conf.byteOrder);\r
2790         return XRAN_STATUS_FAIL;\r
2791     }\r
2792 \r
2793     /* setup PRACH configuration for C-Plane */\r
2794     xran_init_prach(pConf, p_xran_dev_ctx);\r
2795     xran_init_srs(pConf, p_xran_dev_ctx);\r
2796 \r
2797     xran_cp_init_sectiondb(pHandle);\r
2798     xran_init_sectionid(pHandle);\r
2799     xran_init_seqid(pHandle);\r
2800 \r
2801     if(pConf->ru_conf.xran_max_frame) {\r
2802        xran_max_frame = pConf->ru_conf.xran_max_frame;\r
2803        printf("xran_max_frame %d\n", xran_max_frame);\r
2804     }\r
2805 \r
2806     interval_us = xran_fs_get_tti_interval(nNumerology);\r
2807 \r
2808     if(pConf->log_level){\r
2809         printf("%s: interval_us=%ld\n", __FUNCTION__, interval_us);\r
2810     }\r
2811     timing_set_numerology(nNumerology);\r
2812 \r
2813     for(i = 0 ; i <pConf->nCC; i++){\r
2814         xran_fs_set_slot_type(i, pConf->frame_conf.nFrameDuplexType, pConf->frame_conf.nTddPeriod,\r
2815             pConf->frame_conf.sSlotConfig);\r
2816     }\r
2817 \r
2818     xran_fs_slot_limit_init(xran_fs_get_tti_interval(nNumerology));\r
2819 \r
2820     if(xran_ethdi_get_ctx()->io_cfg.bbdev_mode != XRAN_BBDEV_NOT_USED){\r
2821         p_xran_dev_ctx->bbdev_dec = pConf->bbdev_dec;\r
2822         p_xran_dev_ctx->bbdev_enc = pConf->bbdev_enc;\r
2823     }\r
2824 \r
2825     /* if send_xpmbuf2ring needs to be changed from default functions,\r
2826      * then those should be set between xran_init and xran_open */\r
2827     if(p_xran_dev_ctx->send_cpmbuf2ring == NULL)\r
2828         p_xran_dev_ctx->send_cpmbuf2ring    = xran_ethdi_mbuf_send_cp;\r
2829     if(p_xran_dev_ctx->send_upmbuf2ring == NULL)\r
2830         p_xran_dev_ctx->send_upmbuf2ring    = xran_ethdi_mbuf_send;\r
2831 \r
2832     /* Start packet processing thread */\r
2833     if((uint16_t)xran_ethdi_get_ctx()->io_cfg.port[XRAN_UP_VF] != 0xFFFF &&\r
2834         (uint16_t)xran_ethdi_get_ctx()->io_cfg.port[XRAN_CP_VF] != 0xFFFF ){\r
2835         if(pConf->log_level){\r
2836             print_dbg("XRAN_UP_VF: 0x%04x\n", xran_ethdi_get_ctx()->io_cfg.port[XRAN_UP_VF]);\r
2837             print_dbg("XRAN_CP_VF: 0x%04x\n", xran_ethdi_get_ctx()->io_cfg.port[XRAN_CP_VF]);\r
2838         }\r
2839         if (rte_eal_remote_launch(xran_timing_source_thread, xran_dev_get_ctx(), xran_ethdi_get_ctx()->io_cfg.timing_core))\r
2840             rte_panic("thread_run() failed to start\n");\r
2841     } else if(pConf->log_level){\r
2842             printf("Eth port was not open. Processing thread was not started\n");\r
2843     }\r
2844 \r
2845     return 0;\r
2846 }\r
2847 \r
2848 int32_t xran_start(void *pHandle)\r
2849 {\r
2850     if(xran_get_if_state() == XRAN_RUNNING) {\r
2851         print_err("Already STARTED!!");\r
2852         return (-1);\r
2853         }\r
2854 \r
2855     xran_if_current_state = XRAN_RUNNING;\r
2856     return 0;\r
2857 }\r
2858 \r
2859 int32_t xran_stop(void *pHandle)\r
2860 {\r
2861     if(xran_get_if_state() == XRAN_STOPPED) {\r
2862         print_err("Already STOPPED!!");\r
2863         return (-1);\r
2864         }\r
2865 \r
2866     xran_if_current_state = XRAN_STOPPED;\r
2867     return 0;\r
2868 }\r
2869 \r
2870 int32_t xran_close(void *pHandle)\r
2871 {\r
2872     xran_if_current_state = XRAN_STOPPED;\r
2873     //TODO: fix memory leak xran_cp_free_sectiondb(pHandle);\r
2874     //rte_eal_mp_wait_lcore();\r
2875     //xran_ethdi_ports_stats();\r
2876 \r
2877 #ifdef RTE_LIBRTE_PDUMP\r
2878     /* uninitialize packet capture framework */\r
2879     rte_pdump_uninit();\r
2880 #endif\r
2881     return 0;\r
2882 }\r
2883 \r
2884 int32_t xran_mm_destroy (void * pHandle)\r
2885 {\r
2886     if(xran_get_if_state() == XRAN_RUNNING) {\r
2887         print_err("Please STOP first !!");\r
2888         return (-1);\r
2889         }\r
2890 \r
2891     /* functionality is not yet implemented */\r
2892     return -1;\r
2893 }\r
2894 \r
2895 int32_t xran_reg_sym_cb(void *pHandle, xran_callback_sym_fn symCb, void * symCbParam, uint8_t symb,  uint8_t ant)\r
2896 {\r
2897     if(xran_get_if_state() == XRAN_RUNNING) {\r
2898         print_err("Cannot register callback while running!!\n");\r
2899         return (-1);\r
2900         }\r
2901 \r
2902     /* functionality is not yet implemented */\r
2903     print_err("Functionality is not yet implemented !");\r
2904     return -1;\r
2905 }\r
2906 \r
2907 int32_t xran_reg_physide_cb(void *pHandle, xran_fh_tti_callback_fn Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id id)\r
2908 {\r
2909     struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx();\r
2910 \r
2911     if(xran_get_if_state() == XRAN_RUNNING) {\r
2912         print_err("Cannot register callback while running!!\n");\r
2913         return (-1);\r
2914         }\r
2915 \r
2916     p_xran_dev_ctx->ttiCb[id]      = Cb;\r
2917     p_xran_dev_ctx->TtiCbParam[id] = cbParam;\r
2918     p_xran_dev_ctx->SkipTti[id]    = skipTtiNum;\r
2919 \r
2920     return 0;\r
2921 }\r
2922 \r
2923 /* send_cpmbuf2ring and send_upmbuf2ring should be set between xran_init and xran_open\r
2924  * each cb will be set by default duing open if it is set by NULL */\r
2925 int xran_register_cb_mbuf2ring(xran_ethdi_mbuf_send_fn mbuf_send_cp, xran_ethdi_mbuf_send_fn mbuf_send_up)\r
2926 {\r
2927     struct xran_device_ctx *p_xran_dev_ctx;\r
2928 \r
2929     if(xran_get_if_state() == XRAN_RUNNING) {\r
2930         print_err("Cannot register callback while running!!\n");\r
2931         return (-1);\r
2932         }\r
2933 \r
2934     p_xran_dev_ctx = xran_dev_get_ctx();\r
2935 \r
2936     p_xran_dev_ctx->send_cpmbuf2ring    = mbuf_send_cp;\r
2937     p_xran_dev_ctx->send_upmbuf2ring    = mbuf_send_up;\r
2938 \r
2939     return (0);\r
2940 }\r
2941 \r
2942 \r
2943 int32_t xran_get_slot_idx (uint32_t *nFrameIdx, uint32_t *nSubframeIdx,  uint32_t *nSlotIdx, uint64_t *nSecond)\r
2944 {\r
2945     int32_t tti = 0;\r
2946 \r
2947     tti           = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);\r
2948     *nSlotIdx     = (uint32_t)XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);\r
2949     *nSubframeIdx = (uint32_t)XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);\r
2950     *nFrameIdx    = (uint32_t)XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);\r
2951     *nSecond      = timing_get_current_second();\r
2952 \r
2953     return tti;\r
2954 }\r
2955 \r
2956 \r
2957 /**\r
2958  * @brief Get the configuration of eAxC ID\r
2959  *\r
2960  * @return the pointer of configuration\r
2961  */\r
2962 inline struct xran_eaxcid_config *xran_get_conf_eAxC(void *pHandle)\r
2963 {\r
2964     return (&(xran_dev_get_ctx()->eAxc_id_cfg));\r
2965 }\r
2966 \r
2967 /**\r
2968  * @brief Get the configuration of the total number of beamforming weights on RU\r
2969  *\r
2970  * @return Configured the number of beamforming weights\r
2971  */\r
2972 inline uint8_t xran_get_conf_num_bfweights(void *pHandle)\r
2973 {\r
2974     return (xran_dev_get_ctx()->fh_init.totalBfWeights);\r
2975 }\r
2976 \r
2977 /**\r
2978  * @brief Get the configuration of subcarrier spacing for PRACH\r
2979  *\r
2980  * @return subcarrier spacing value for PRACH\r
2981  */\r
2982 inline uint8_t xran_get_conf_prach_scs(void *pHandle)\r
2983 {\r
2984     return (xran_lib_get_ctx_fhcfg()->prach_conf.nPrachSubcSpacing);\r
2985 }\r
2986 \r
2987 /**\r
2988  * @brief Get the configuration of FFT size for RU\r
2989  *\r
2990  * @return FFT size value for RU\r
2991  */\r
2992 inline uint8_t xran_get_conf_fftsize(void *pHandle)\r
2993 {\r
2994     return (xran_lib_get_ctx_fhcfg()->ru_conf.fftSize);\r
2995 }\r
2996 \r
2997 /**\r
2998  * @brief Get the configuration of nummerology\r
2999  *\r
3000  * @return Configured numerology\r
3001  */\r
3002 inline uint8_t xran_get_conf_numerology(void *pHandle)\r
3003 {\r
3004     return (xran_lib_get_ctx_fhcfg()->frame_conf.nNumerology);\r
3005 }\r
3006 \r
3007 /**\r
3008  * @brief Get the configuration of IQ bit width for RU\r
3009  *\r
3010  * @return IQ bit width for RU\r
3011  */\r
3012 inline uint8_t xran_get_conf_iqwidth(void *pHandle)\r
3013 {\r
3014     struct xran_fh_config *pFhCfg;\r
3015 \r
3016     pFhCfg = xran_lib_get_ctx_fhcfg();\r
3017     return ((pFhCfg->ru_conf.iqWidth==16)?0:pFhCfg->ru_conf.iqWidth);\r
3018 }\r
3019 \r
3020 /**\r
3021  * @brief Get the configuration of compression method for RU\r
3022  *\r
3023  * @return Compression method for RU\r
3024  */\r
3025 inline uint8_t xran_get_conf_compmethod(void *pHandle)\r
3026 {\r
3027     return (xran_lib_get_ctx_fhcfg()->ru_conf.compMeth);\r
3028 }\r
3029 \r
3030 \r
3031 /**\r
3032  * @brief Get the configuration of the number of component carriers\r
3033  *\r
3034  * @return Configured the number of component carriers\r
3035  */\r
3036 inline uint8_t xran_get_num_cc(void *pHandle)\r
3037 {\r
3038     return (xran_lib_get_ctx_fhcfg()->nCC);\r
3039 }\r
3040 \r
3041 /**\r
3042  * @brief Get the configuration of the number of antenna for UL\r
3043  *\r
3044  * @return Configured the number of antenna\r
3045  */\r
3046 inline uint8_t xran_get_num_eAxc(void *pHandle)\r
3047 {\r
3048     return (xran_lib_get_ctx_fhcfg()->neAxc);\r
3049 }\r
3050 \r
3051 /**\r
3052  * @brief Get configuration of O-RU (Cat A or Cat B)\r
3053  *\r
3054  * @return Configured the number of antenna\r
3055  */\r
3056 inline enum xran_category xran_get_ru_category(void *pHandle)\r
3057 {\r
3058     return (xran_lib_get_ctx_fhcfg()->ru_conf.xranCat);\r
3059 }\r
3060 \r
3061 /**\r
3062  * @brief Get the configuration of the number of antenna\r
3063  *\r
3064  * @return Configured the number of antenna\r
3065  */\r
3066 inline uint8_t xran_get_num_eAxcUl(void *pHandle)\r
3067 {\r
3068     return (xran_lib_get_ctx_fhcfg()->neAxcUl);\r
3069 }\r
3070 \r
3071 /**\r
3072  * @brief Get the configuration of the number of antenna elements\r
3073  *\r
3074  * @return Configured the number of antenna\r
3075  */\r
3076 inline uint8_t xran_get_num_ant_elm(void *pHandle)\r
3077 {\r
3078     return (xran_lib_get_ctx_fhcfg()->nAntElmTRx);\r
3079 }\r
3080 \r
3081 int32_t xran_get_common_counters(void *pXranLayerHandle, struct xran_common_counters *pStats)\r
3082 {\r
3083     struct xran_device_ctx* pDev = (struct xran_device_ctx*)pXranLayerHandle;\r
3084 \r
3085     if(pStats && pDev) {\r
3086         *pStats  =  pDev->fh_counters;\r
3087         return XRAN_STATUS_SUCCESS;\r
3088     } else {\r
3089         return XRAN_STATUS_INVALID_PARAM;\r
3090     }\r
3091 }\r
3092 \r