Front Haul Interface Library first seed code contribution
[o-du/phy.git] / fhi_lib / lib / src / xran_main.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19
20 /**
21  * @brief XRAN main functionality module
22  * @file xran_main.c
23  * @ingroup group_source_xran
24  * @author Intel Corporation
25  **/
26
27 #define _GNU_SOURCE
28 #include <sched.h>
29 #include <assert.h>
30 #include <err.h>
31 #include <libgen.h>
32 #include <sys/time.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <stdio.h>
36 #include <pthread.h>
37
38 #include <rte_eal.h>
39 #include <rte_errno.h>
40 #include <rte_lcore.h>
41 #include <rte_cycles.h>
42 #include <rte_memory.h>
43 #include <rte_memzone.h>
44 #include <rte_ring.h>
45
46 #include "xran_fh_lls_cu.h"
47
48 #include "ethdi.h"
49 #include "xran_pkt.h"
50 #include "xran_up_api.h"
51 #include "xran_cp_api.h"
52 #include "xran_sync_api.h"
53 #include "xran_lib_mlog_tasks_id.h"
54 #include "xran_timer.h"
55 #include "xran_common.h"
56 #include "xran_printf.h"
57
58 #ifndef MLOG_ENABLED
59 #include "mlog_lnx_xRAN.h"
60 #else
61 #include "mlog_lnx.h"
62 #endif
63
64 #define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) )
65
66 #define XranOffsetSym(offSym, otaSym, numSymTotal)  (((int32_t)offSym > (int32_t)otaSym) ? \
67                             ((int32_t)otaSym + ((int32_t)numSymTotal) - (uint32_t)offSym) : \
68                             (((int32_t)otaSym - (int32_t)offSym) >= numSymTotal) ?  \
69                                     (((int32_t)otaSym - (int32_t)offSym) - numSymTotal) : \
70                                     ((int32_t)otaSym - (int32_t)offSym))
71
72 #define MAX_NUM_OF_XRAN_CTX       (2)
73 #define XranIncrementCtx(ctx)                             ((ctx >= (MAX_NUM_OF_XRAN_CTX-1)) ? 0 : (ctx+1))
74 #define XranDecrementCtx(ctx)                             ((ctx == 0) ? (MAX_NUM_OF_XRAN_CTX-1) : (ctx-1))
75
76 struct xran_timer_ctx {
77     uint32_t    tti_to_process;
78 };
79
80 static XranLibHandleInfoStruct DevHandle;
81 static struct xran_lib_ctx g_xran_lib_ctx = { 0 };
82
83 struct xran_timer_ctx timer_ctx[MAX_NUM_OF_XRAN_CTX];
84
85 static struct rte_timer tti_to_phy_timer[10];
86 static struct rte_timer tti_timer;
87 static struct rte_timer sym_timer;
88 static struct rte_timer tx_cp_dl_timer;
89 static struct rte_timer tx_cp_ul_timer;
90 static struct rte_timer tx_up_timer;
91
92 static long interval_us = 125;
93
94 uint32_t xran_lib_ota_tti        = 0; /* [0:7999] */
95 uint32_t xran_lib_ota_sym        = 0; /* [0:7] */
96 uint32_t xran_lib_ota_sym_idx    = 0; /* [0 : 14*8*1000-1] */
97
98 uint64_t xran_lib_gps_second = 0;
99
100 static uint8_t xran_cp_seq_id_num[XRAN_MAX_CELLS_PER_PORT][XRAN_DIR_MAX][XRAN_MAX_ANTENNA_NR];
101 static uint8_t xran_section_id_curslot[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR];
102 static uint16_t xran_section_id[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR];
103
104 void xran_timer_arm(struct rte_timer *tim, void* arg);
105 int xran_process_tx_sym(void *arg);
106
107 int xran_process_rx_sym(void *arg,
108                         void *iq_data_start,
109                         uint16_t size,
110                         uint8_t CC_ID,
111                         uint8_t Ant_ID,
112                         uint8_t frame_id,
113                         uint8_t subframe_id,
114                         uint8_t slot_id,
115                         uint8_t symb_id);
116
117 void tti_ota_cb(struct rte_timer *tim, void *arg);
118 void tti_to_phy_cb(struct rte_timer *tim, void *arg);
119 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore);
120
121 struct xran_lib_ctx *xran_lib_get_ctx(void)
122 {
123     return &g_xran_lib_ctx;
124 }
125
126 static inline XRANFHCONFIG *xran_lib_get_ctx_fhcfg(void)
127 {
128     return (&(xran_lib_get_ctx()->xran_fh_cfg));
129 }
130
131 inline uint16_t xran_get_beamid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id)
132 {
133     return (0);     // NO BEAMFORMING
134 }
135
136 int xran_init_sectionid(void *pHandle)
137 {
138   int cell, dir, ant;
139
140     for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {
141         for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) {
142             xran_section_id[cell][ant] = 0;
143             xran_section_id_curslot[cell][ant] = 255;
144             }
145         }
146
147     return (0);
148 }
149
150 int xran_init_seqid(void *pHandle)
151 {
152   int cell, dir, ant;
153
154     for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) {
155         for(dir=0; dir < XRAN_DIR_MAX; dir++) {
156             for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) {
157                 xran_cp_seq_id_num[cell][dir][ant] = 0;
158                 }
159             }
160         }
161
162     return (0);
163 }
164
165 inline uint16_t xran_alloc_sectionid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id)
166 {
167     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {
168         print_err("Invalid CC ID - %d", cc_id);
169         return (0);
170         }
171     if(ant_id >= XRAN_MAX_ANTENNA_NR) {
172         print_err("Invalid antenna ID - %d", ant_id);
173         return (0);
174         }
175
176     /* if new slot has been started,
177      * then initializes section id again for new start */
178     if(xran_section_id_curslot[cc_id][ant_id] != slot_id) {
179         xran_section_id[cc_id][ant_id] = 0;
180         xran_section_id_curslot[cc_id][ant_id] = slot_id;
181         }
182   
183     return(xran_section_id[cc_id][ant_id]++);
184 }
185
186 inline uint8_t xran_get_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id)
187 {
188     if(dir >= XRAN_DIR_MAX) {
189         print_err("Invalid direction - %d", dir);
190         return (0);
191         }
192     if(cc_id >= XRAN_MAX_CELLS_PER_PORT) {
193         print_err("Invalid CC ID - %d", cc_id);
194         return (0);
195         }
196     if(ant_id >= XRAN_MAX_ANTENNA_NR) {
197         print_err("Invalid antenna ID - %d", ant_id);
198         return (0);
199         }
200
201     return(xran_cp_seq_id_num[cc_id][dir][ant_id]++);
202 }
203
204 inline int xran_update_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id, uint8_t seq_id)
205 {
206     return (0);
207 }
208
209 //////////////////////////////////////////
210 // For RU emulation
211 static struct xran_section_gen_info cpSections[255];
212 static struct xran_cp_gen_params cpInfo;
213 int process_cplane(struct rte_mbuf *pkt)
214 {
215   int xran_parse_cp_pkt(struct rte_mbuf *mbuf, struct xran_cp_gen_params *result);
216
217     cpInfo.sections = cpSections;
218     xran_parse_cp_pkt(pkt, &cpInfo);
219
220     return (0);
221 }
222 //////////////////////////////////////////
223
224 void sym_ota_cb(struct rte_timer *tim, void *arg)
225 {
226     uint8_t offset = 0;
227     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
228     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;
229     long t1 = MLogTick();
230
231     if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 0){
232         tti_ota_cb(NULL, arg);
233     }
234
235     if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 1){
236         if(p_xran_lib_ctx->phy_tti_cb_done == 0){
237             uint64_t t3 = MLogTick();
238             /* rearm timer to deliver TTI event to PHY */
239             p_xran_lib_ctx->phy_tti_cb_done = 0;
240             xran_timer_arm_ex(&tti_to_phy_timer[xran_lib_ota_tti % 10], tti_to_phy_cb, (void*)pTCtx, p_xran_lib_ctx->xran_init_cfg.io_cfg.pkt_proc_core);
241             MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
242         }
243     }
244
245     xran_process_tx_sym(timer_ctx);
246     /* check if there is call back to do something else on this symbol */
247     if(p_xran_lib_ctx->pSymCallback[0][xran_lib_ota_sym])
248         p_xran_lib_ctx->pSymCallback[0][xran_lib_ota_sym](&tx_cp_dl_timer, p_xran_lib_ctx->pSymCallbackTag[0][xran_lib_ota_sym]);
249
250     xran_lib_ota_sym++;
251     if(xran_lib_ota_sym >= N_SYM_PER_SLOT){
252         xran_lib_ota_sym=0;
253     }
254     MLogTask(PID_SYM_OTA_CB, t1, MLogTick());
255 }
256
257 void tti_ota_cb(struct rte_timer *tim, void *arg)
258 {
259     uint32_t    frame_id    = 0;
260     uint32_t    subframe_id = 0;
261     uint32_t    slot_id     = 0;
262     uint32_t    next_tti    = 0;
263
264     uint32_t mlogVar[10];
265     uint32_t mlogVarCnt = 0;
266     uint64_t t1 = MLogTick();
267     uint64_t t3 = 0;
268     uint32_t reg_tti  = 0;
269     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;
270     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
271
272     MLogTask(PID_TTI_TIMER, t1, MLogTick());
273
274     /* To match TTbox */
275     if(xran_lib_ota_tti == 0)
276         reg_tti = 8000-1;
277     else
278         reg_tti = xran_lib_ota_tti -1;
279     MLogIncrementCounter();
280     /* subframe and slot */
281     MLogRegisterFrameSubframe(((reg_tti/SLOTNUM_PER_SUBFRAME) % SUBFRAMES_PER_SYSTEMFRAME),
282         reg_tti % (SLOTNUM_PER_SUBFRAME));
283     MLogMark(1, t1);
284
285     slot_id     = XranGetSlotNum(xran_lib_ota_tti, SLOTNUM_PER_SUBFRAME);
286     subframe_id = XranGetSubFrameNum(xran_lib_ota_tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
287     frame_id    = XranGetFrameNum(xran_lib_ota_tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
288
289     pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process = xran_lib_ota_tti;
290
291     mlogVar[mlogVarCnt++] = 0x11111111;
292     mlogVar[mlogVarCnt++] = xran_lib_ota_tti;
293     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx;
294     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx / 14;
295     mlogVar[mlogVarCnt++] = frame_id;
296     mlogVar[mlogVarCnt++] = subframe_id;
297     mlogVar[mlogVarCnt++] = slot_id;
298     mlogVar[mlogVarCnt++] = 0;
299     MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
300
301     if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == ID_LLS_CU)
302         next_tti = xran_lib_ota_tti + 1;
303     else
304         next_tti = xran_lib_ota_tti;
305
306     if(next_tti>= SLOTNUM_PER_SUBFRAME*1000){
307         print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id);
308         next_tti=0;
309     }
310     /* [0 - 7] */
311     slot_id     = XranGetSlotNum(next_tti, SLOTNUM_PER_SUBFRAME);
312     /* sf [0 - 9] */
313     subframe_id = XranGetSubFrameNum(next_tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
314     /* frame [0 - 99] for now */
315     frame_id    = XranGetFrameNum(next_tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
316
317     print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id);
318
319     if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == ID_LLS_CU){
320         pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = next_tti;
321     } else {
322         pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = pTCtx[(xran_lib_ota_tti & 1)^1].tti_to_process;
323     }
324
325     t3 = MLogTick();
326     p_xran_lib_ctx->phy_tti_cb_done = 0;
327     xran_timer_arm_ex(&tti_to_phy_timer[xran_lib_ota_tti % 10], tti_to_phy_cb, (void*)pTCtx, p_xran_lib_ctx->xran_init_cfg.io_cfg.pkt_proc_core);
328     MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick());
329
330     xran_lib_ota_tti++;
331     /* within 1 sec we have 8000 TTIs as 1000ms/0.125ms where TTI is 125us*/
332     if(xran_lib_ota_tti >= SLOTNUM_PER_SUBFRAME*1000){
333         print_dbg("[%d]SFN %d sf %d slot %d\n",xran_lib_ota_tti, frame_id, subframe_id, slot_id);
334         xran_lib_ota_tti=0;
335     }
336     MLogTask(PID_TTI_CB, t1, MLogTick());
337 }
338
339 void xran_timer_arm(struct rte_timer *tim, void* arg)
340 {
341     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
342     if (xran_if_current_state == XRAN_RUNNING){
343         rte_timer_cb_t fct = (rte_timer_cb_t)arg;
344         rte_timer_reset_sync(tim, 0, SINGLE, p_xran_lib_ctx->xran_init_cfg.io_cfg.pkt_proc_core, fct, timer_ctx);
345     }
346 }
347
348 void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore)
349 {
350     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
351     if (xran_if_current_state == XRAN_RUNNING){
352         rte_timer_cb_t fct = (rte_timer_cb_t)CbFct;
353         rte_timer_init(tim);
354         rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, CbArg);
355     }
356 }
357
358 void tx_cp_dl_cb(struct rte_timer *tim, void *arg)
359 {
360   long t1 = MLogTick();
361   int tti, sym;
362   uint32_t slot_id, subframe_id, frame_id;
363   int ant_id;
364   int32_t cc_id = 0;
365   uint16_t beam_id;
366   uint8_t num_eAxc, num_CCPorts;
367   void *pHandle;
368
369   struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
370   struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;
371
372
373     pHandle = NULL;     // TODO: temp implemantation
374     num_eAxc    = xran_get_num_eAxc(pHandle);
375     num_CCPorts = xran_get_num_cc(pHandle);
376
377     if(p_xran_lib_ctx->enableCP) {
378
379         tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process;
380
381         slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);
382         subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
383         frame_id    = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
384
385         print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);
386
387         for(ant_id = 0; ant_id < num_eAxc; ++ant_id) {
388             for(cc_id = 0; cc_id < num_CCPorts; cc_id++ ) {
389                  // start new section information list
390                 xran_cp_reset_section_info(pHandle, XRAN_DIR_DL, cc_id, ant_id);
391
392                 beam_id = xran_get_beamid(pHandle, XRAN_DIR_DL, cc_id, ant_id, slot_id);
393
394                 send_cpmsg_dlul(pHandle, XRAN_DIR_DL,
395                                 frame_id, subframe_id, slot_id,
396                                 0, N_SYM_PER_SLOT, NUM_OF_PRB_IN_FULL_BAND,
397                                 beam_id, cc_id, ant_id,
398                                 xran_get_seqid(pHandle, XRAN_DIR_DL, cc_id, ant_id, slot_id));
399                 }
400             }
401         }
402     MLogTask(PID_CP_DL_CB, t1, MLogTick());
403 }
404
405 void rx_ul_deadline_half_cb(struct rte_timer *tim, void *arg)
406 {
407     long t1 = MLogTick();
408     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
409     XranStatusInt32 status;
410     /* half of RX for current TTI as measured against current OTA time */
411     int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
412
413     if(p_xran_lib_ctx->xran2phy_mem_ready == 0)
414         return;
415
416     if(p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] == 0){
417         status = (rx_tti << 16) | 0; /* base on PHY side implementation first 7 sym of slot */
418         if(p_xran_lib_ctx->pCallback[0])
419            p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status);
420     } else {
421         p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] = 0;
422     }
423     MLogTask(PID_UP_UL_HALF_DEAD_LINE_CB, t1, MLogTick());
424 }
425
426 void rx_ul_deadline_full_cb(struct rte_timer *tim, void *arg)
427 {
428     long t1 = MLogTick();
429     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
430     XranStatusInt32 status;
431     int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
432
433     if(rx_tti >= 8000-1)
434        rx_tti = 0;
435     else
436        rx_tti -= 1; /* end of RX for prev TTI as measured against current OTA time */
437
438     if(p_xran_lib_ctx->xran2phy_mem_ready == 0)
439         return;
440
441     if(p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] == 0){
442         status = (rx_tti << 16) | 7; /* last 7 sym means full slot of Symb */
443         if(p_xran_lib_ctx->pCallback[0])
444            p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status);
445     } else {
446         p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] = 0;
447     }
448
449     MLogTask(PID_UP_UL_FULL_DEAD_LINE_CB, t1, MLogTick());
450 }
451
452
453 void tx_cp_ul_cb(struct rte_timer *tim, void *arg)
454 {
455     long t1 = MLogTick();
456     int sym, tti;
457     uint32_t    frame_id    = 0;
458     uint32_t    subframe_id = 0;
459     uint32_t    slot_id     = 0;
460
461     int32_t cc_id;
462     int ant_id, prach_port_id;
463     uint16_t beam_id;
464     uint8_t num_eAxc, num_CCPorts;
465
466     void *pHandle;
467
468     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
469     xRANPrachCPConfigStruct *pPrachCPConfig = &(p_xran_lib_ctx->PrachCPConfig);
470     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;
471
472     pHandle     = NULL;     // TODO: temp implemantation
473     num_eAxc    = xran_get_num_eAxc(pHandle);
474     num_CCPorts = xran_get_num_cc(pHandle);
475
476     if (p_xran_lib_ctx->enableCP){
477         tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process;
478         slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);
479         subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
480         frame_id    = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
481         print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);
482
483
484         for(ant_id = 0; ant_id < num_eAxc; ++ant_id) {
485             for(cc_id = 0; cc_id < num_CCPorts; cc_id++ ) {
486                 // start new section information list
487                 xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, ant_id);
488
489                 beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, ant_id, slot_id);
490                 send_cpmsg_dlul(pHandle, XRAN_DIR_UL,
491                                 frame_id, subframe_id, slot_id,
492                                 0, N_SYM_PER_SLOT, NUM_OF_PRB_IN_FULL_BAND,
493                                 beam_id, cc_id, ant_id,
494                                 xran_get_seqid(pHandle, XRAN_DIR_UL, cc_id, ant_id, slot_id));
495             }
496         }
497
498         if ((frame_id % pPrachCPConfig->x == pPrachCPConfig->y[0]) && (pPrachCPConfig->isPRACHslot[slot_id]==1))  //is prach slot
499         {
500             for(ant_id = 0; ant_id < num_eAxc; ant_id++) {
501                 for(cc_id = 0; cc_id < num_CCPorts; cc_id++) {
502 #if !defined(PRACH_USES_SHARED_PORT)
503                     prach_port_id = ant_id + num_eAxc;
504                     // start new section information list
505                     xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, prach_port_id);
506 #else
507                     prach_port_id = ant_id;
508 #endif
509                     beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);
510                     send_cpmsg_prach(pHandle,
511                                     frame_id, subframe_id, slot_id,
512                                     beam_id, cc_id, prach_port_id,
513                                     xran_get_seqid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id));
514                 }
515             }
516         }
517
518     }
519     MLogTask(PID_CP_UL_CB, t1, MLogTick());
520 }
521
522 void ul_up_full_slot_cb(struct rte_timer *tim, void *arg)
523 {
524     long t1 = MLogTick();
525     rte_pause();
526     MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick());
527 }
528
529 void tti_to_phy_cb(struct rte_timer *tim, void *arg)
530 {
531     long t1 = MLogTick();
532     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
533
534     static int first_call = 0;
535     p_xran_lib_ctx->phy_tti_cb_done = 1; /* DPDK called CB */
536     if (first_call){
537         if(p_xran_lib_ctx->ttiCb[XRAN_CB_TTI]){
538             if(p_xran_lib_ctx->SkipTti[XRAN_CB_TTI] <= 0){
539                 p_xran_lib_ctx->ttiCb[XRAN_CB_TTI](p_xran_lib_ctx->TtiCbParam[XRAN_CB_TTI]);
540             }else{
541                 p_xran_lib_ctx->SkipTti[XRAN_CB_TTI]--;
542             }
543         }
544     } else {
545         if(p_xran_lib_ctx->ttiCb[XRAN_CB_TTI]){
546             int32_t tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
547             if(tti == 8000-1)
548                 first_call = 1;
549         }
550     }
551
552
553     MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick());
554 }
555
556 int xran_timing_source_thread(void *args)
557 {
558     cpu_set_t cpuset;
559     int32_t   do_reset = 0;
560     uint64_t  t1 = 0;
561     uint64_t  delta;
562     int32_t   result1;
563     uint32_t delay_cp_dl;
564     uint32_t delay_cp_ul;
565     uint32_t delay_up;
566     uint32_t delay_up_ul;
567     uint32_t delay_cp2up;
568     uint32_t sym_cp_dl;
569     uint32_t sym_cp_ul;
570     uint32_t sym_up_ul;
571     int32_t sym_up;
572     struct sched_param sched_param;
573     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
574
575     /* ToS = Top of Second start +- 1.5us */
576     struct timespec ts;
577
578     char buff[100];
579
580     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());
581
582     /* set main thread affinity mask to CPU2 */
583     sched_param.sched_priority = 98;
584
585     CPU_ZERO(&cpuset);
586     CPU_SET(p_xran_lib_ctx->xran_init_cfg.io_cfg.timing_core, &cpuset);
587     if (result1 = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset))
588     {
589         printf("pthread_setaffinity_np failed: coreId = 2, result1 = %d\n",result1);
590     }
591     if ((result1 = pthread_setschedparam(pthread_self(), 1, &sched_param)))
592     {
593         printf("priority is not changed: coreId = 2, result1 = %d\n",result1);
594     }
595
596     if (p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU) {
597         do {
598            timespec_get(&ts, TIME_UTC);
599         }while (ts.tv_nsec >1500);
600         struct tm * ptm = gmtime(&ts.tv_sec);
601         if(ptm){
602             strftime(buff, sizeof buff, "%D %T", ptm);
603             printf("lls-CU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us);
604         }
605
606         delay_cp_dl = p_xran_lib_ctx->xran_init_cfg.ttiPeriod - p_xran_lib_ctx->xran_init_cfg.T1a_max_cp_dl;
607         delay_cp_ul = p_xran_lib_ctx->xran_init_cfg.ttiPeriod - p_xran_lib_ctx->xran_init_cfg.T1a_max_cp_ul;
608         delay_up    = p_xran_lib_ctx->xran_init_cfg.T1a_max_up;
609         delay_up_ul = p_xran_lib_ctx->xran_init_cfg.Ta4_max;
610
611         delay_cp2up = delay_up-delay_cp_dl;
612
613         sym_cp_dl = delay_cp_dl*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;
614         sym_cp_ul = delay_cp_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;
615         sym_up_ul = delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT);
616         p_xran_lib_ctx->sym_up = sym_up = -(delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT)+1);
617         p_xran_lib_ctx->sym_up_ul = sym_up_ul = (delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1);
618
619         printf("Start C-plane DL %d us after TTI  [trigger on sym %d]\n", delay_cp_dl, sym_cp_dl);
620         printf("Start C-plane UL %d us after TTI  [trigger on sym %d]\n", delay_cp_ul, sym_cp_ul);
621         printf("Start U-plane DL %d us before OTA [offset  in sym %d]\n", delay_up, sym_up);
622         printf("Start U-plane UL %d us OTA        [offset  in sym %d]\n", delay_up_ul, sym_up_ul);
623
624         printf("C-plane to U-plane delay %d us after TTI\n", delay_cp2up);
625         printf("Start Sym timer %ld ns\n", TX_TIMER_INTERVAL/N_SYM_PER_SLOT);
626
627         p_xran_lib_ctx->pSymCallback[0][sym_cp_dl]    = xran_timer_arm;
628         p_xran_lib_ctx->pSymCallbackTag[0][sym_cp_dl] = tx_cp_dl_cb;
629
630         p_xran_lib_ctx->pSymCallback[0][sym_cp_ul]    = xran_timer_arm;
631         p_xran_lib_ctx->pSymCallbackTag[0][sym_cp_ul] = tx_cp_ul_cb;
632
633         /* Full slot UL OTA + delay_up_ul */
634         p_xran_lib_ctx->pSymCallback[0][sym_up_ul]    = xran_timer_arm;
635         p_xran_lib_ctx->pSymCallbackTag[0][sym_up_ul] = rx_ul_deadline_full_cb;
636
637         /* Half slot UL OTA + delay_up_ul*/
638         p_xran_lib_ctx->pSymCallback[0][sym_up_ul + N_SYM_PER_SLOT/2]    = xran_timer_arm;
639         p_xran_lib_ctx->pSymCallbackTag[0][sym_up_ul + N_SYM_PER_SLOT/2] = rx_ul_deadline_half_cb;
640
641     } else {    // APP_RU
642         /* calcualte when to send UL U-plane */
643         delay_up = p_xran_lib_ctx->xran_init_cfg.Ta3_min;
644         p_xran_lib_ctx->sym_up = sym_up = delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT)+1;
645         printf("Start UL U-plane %d us after OTA [offset in sym %d]\n", delay_up, sym_up);
646         do {
647            timespec_get(&ts, TIME_UTC);
648         }while (ts.tv_nsec >1500);
649         struct tm * ptm = gmtime(&ts.tv_sec);
650         if(ptm){
651             strftime(buff, sizeof buff, "%D %T", ptm);
652             printf("RU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us);
653         }
654     }
655
656     do {
657        timespec_get(&ts, TIME_UTC);
658     }while (ts.tv_nsec == 0);
659
660     while(1) {
661         delta = poll_next_tick(interval_us*1000L/N_SYM_PER_SLOT);
662         if (XRAN_STOPPED == xran_if_current_state)
663             break;
664         sym_ota_cb(&sym_timer, timer_ctx);
665     }
666     printf("Closing timing source thread...\n");
667
668     return 0;
669 }
670
671 /* Handle ecpri format. */
672 int handle_ecpri_ethertype(struct rte_mbuf *pkt, uint64_t rx_time)
673 {
674     const struct xran_ecpri_hdr *ecpri_hdr;
675     unsigned long t1;
676
677     if (rte_pktmbuf_data_len(pkt) < sizeof(struct xran_ecpri_hdr)) {
678         wlog("Packet too short - %d bytes", rte_pktmbuf_data_len(pkt));
679         return 0;
680     }
681
682     /* check eCPRI header. */
683     ecpri_hdr = rte_pktmbuf_mtod(pkt, struct xran_ecpri_hdr *);
684     if(ecpri_hdr == NULL)
685         return MBUF_FREE;
686
687     switch(ecpri_hdr->ecpri_mesg_type) {
688         case ECPRI_IQ_DATA:
689             t1 = MLogTick();
690             process_mbuf(pkt);
691             MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick());
692             break;
693         // For RU emulation
694         case ECPRI_RT_CONTROL_DATA:
695             t1 = MLogTick();
696             if(xran_lib_get_ctx()->xran_init_cfg.io_cfg.id == APP_RU) {
697                 process_cplane(pkt);
698             } else {
699                 print_err("LLS-CU recevied CP message!");
700             }
701             MLogTask(PID_PROCESS_CP_PKT, t1, MLogTick());
702             break;
703         default:
704             wlog("Invalid eCPRI message type - %d", ecpri_hdr->ecpri_mesg_type);
705         }
706 #if 0
707 //def DEBUG
708     return MBUF_KEEP;
709 #else
710     return MBUF_FREE;
711 #endif
712 }
713
714 int xran_process_rx_sym(void *arg,
715                         void *iq_data_start,
716                         uint16_t size,
717                         uint8_t CC_ID,
718                         uint8_t Ant_ID,
719                         uint8_t frame_id,
720                         uint8_t subframe_id,
721                         uint8_t slot_id,
722                         uint8_t symb_id)
723 {
724     char        *pos = NULL;
725     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
726     uint32_t tti=0;
727     XranStatusInt32 status;
728     void *pHandle = NULL;
729
730     if(p_xran_lib_ctx->xran2phy_mem_ready == 0)
731         return 0;
732
733     tti = frame_id * SLOTS_PER_SYSTEMFRAME + subframe_id * SLOTNUM_PER_SUBFRAME + slot_id;
734
735     status = tti << 16 | symb_id;
736
737     if(tti < 8000 && CC_ID < XRAN_MAX_SECTOR_NR &&  CC_ID == 0 && Ant_ID < XRAN_MAX_ANTENNA_NR && symb_id < XRAN_NUM_OF_SYMBOL_PER_SLOT){
738         pos = (char*) p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData;
739         if(pos && iq_data_start && size){
740 #ifdef XRAN_BYTE_ORDER_SWAP
741             int idx = 0;
742             uint16_t *restrict psrc = (uint16_t *)iq_data_start;
743             uint16_t *restrict pdst = (uint16_t *)pos;
744             /* network byte (be) order of IQ to CPU byte order (le) */
745             for (idx = 0; idx < size/sizeof(int16_t); idx++){
746                 pdst[idx]  = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_be_to_cpu_16(psrc[idx]);
747             }
748 #else
749 #error xran spec is network byte order
750             /* for debug */
751             rte_memcpy(pdst, psrc, size);
752 #endif
753 #ifdef DEBUG_XRAN_BUFFERS
754             if (pos[0] != tti % XRAN_N_FE_BUF_LEN ||
755                 pos[1] != CC_ID  ||
756                 pos[2] != Ant_ID ||
757                 pos[3] != symb_id){
758                     printf("%d %d %d %d\n", pos[0], pos[1], pos[2], pos[3]);
759             }
760 #endif
761         } else {
762             print_err("pos %p iq_data_start %p size %d\n",pos, iq_data_start, size);
763         }
764     } else {
765         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);
766     }
767     if (symb_id == 7 || symb_id == 13){
768         p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id]++;
769
770         if(p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] >= xran_get_num_eAxc(pHandle)){
771             if(p_xran_lib_ctx->pCallback[0])
772                p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status);
773             p_xran_lib_ctx->rx_packet_callback_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID] = 1;
774             p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] = 0;
775         }
776     }
777     return size;
778 }
779
780
781 int xran_process_tx_sym(void *arg)
782 {
783     uint32_t    tti=0;
784     uint32_t    mlogVar[10];
785     uint32_t    mlogVarCnt = 0;
786     unsigned long t1 = MLogTick();
787
788     void        *pHandle = NULL;
789     int32_t     ant_id;
790     int32_t     cc_id = 0;
791     uint8_t     num_eAxc = 0;
792     uint8_t     num_CCPorts = 0;
793
794     uint32_t    frame_id    = 0;
795     uint32_t    subframe_id = 0;
796     uint32_t    slot_id     = 0;
797     uint32_t    sym_id      = 0;
798     uint32_t    sym_idx     = 0;
799
800     char        *pos = NULL;
801     int         prb_num = 0;
802
803     struct xran_section_info *sectinfo;
804     uint32_t next;
805
806     enum xran_pkt_dir  direction;
807
808     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
809     struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg;
810
811
812     if(p_xran_lib_ctx->xran2phy_mem_ready == 0)
813         return 0;
814
815     if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU) {
816         direction = XRAN_DIR_DL; /* lls-CU */
817         prb_num = NUM_OF_PRB_IN_FULL_BAND;
818         }
819     else {
820         direction = XRAN_DIR_UL; /* RU */
821         prb_num = NUM_OF_PRB_IN_FULL_BAND; /*TODO: simulation on D-1541 @ 2.10GHz has issue with performace. reduce copy size */
822         }
823
824     /* RU: send symb after OTA time with delay (UL) */
825     /* lls-CU:send symb in advance of OTA time (DL) */
826     sym_idx     = XranOffsetSym(p_xran_lib_ctx->sym_up, xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT*SLOTNUM_PER_SUBFRAME*1000);
827
828     tti         = XranGetTtiNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
829     slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);
830     subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
831     frame_id    = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
832     sym_id      = XranGetSymNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
833
834     print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id);
835
836     mlogVar[mlogVarCnt++] = 0xAAAAAAAA;
837     mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx;
838     mlogVar[mlogVarCnt++] = sym_idx;
839     mlogVar[mlogVarCnt++] = abs(p_xran_lib_ctx->sym_up);
840     mlogVar[mlogVarCnt++] = tti;
841     mlogVar[mlogVarCnt++] = frame_id;
842     mlogVar[mlogVarCnt++] = subframe_id;
843     mlogVar[mlogVarCnt++] = slot_id;
844     mlogVar[mlogVarCnt++] = sym_id;
845     MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
846
847     if(frame_id > 99) {
848         print_err("OTA %d: TX:[sym_idx %d: TTI %d] fr %d sf %d slot %d sym %d\n",xran_lib_ota_sym_idx,  sym_idx, tti, frame_id, subframe_id, slot_id, sym_id);
849         xran_if_current_state =XRAN_STOPPED;
850         }
851
852     num_eAxc    = xran_get_num_eAxc(pHandle);
853     num_CCPorts = xran_get_num_cc(pHandle);
854
855     /* U-Plane */
856     for(ant_id = 0; ant_id < num_eAxc; ant_id++) {
857         for(cc_id = 0; cc_id < num_CCPorts; cc_id++) {
858             if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU && p_xran_lib_ctx->enableCP) {
859                 next = 0;
860                 while(next < xran_cp_getsize_section_info(pHandle, direction, cc_id, ant_id)) {
861                     sectinfo = xran_cp_iterate_section_info(pHandle, direction,
862                                         cc_id, ant_id, subframe_id, slot_id, &next);
863                     if(sectinfo == NULL)
864                         break;
865
866                     /* pointer to IQs input */
867                     /* TODO: need to implement the case of partial RB assignment */
868                     pos = (char*) p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
869                     print_dbg(">>> [%d] type%d, id %d, startPrbc=%d, numPrbc=%d, numSymbol=%d\n", next,
870                             sectinfo->type, sectinfo->id, sectinfo->startPrbc,
871                             sectinfo->numPrbc, sectinfo->numSymbol);
872
873                     if(sectinfo->type != XRAN_CP_SECTIONTYPE_1) {
874                         print_err("Invalid section type in section DB - %d", sectinfo->type);
875                         continue;
876                         }
877
878                     send_symbol_ex(direction, sectinfo->id,
879                                     (struct rb_map *)pos,
880                                     frame_id, subframe_id, slot_id, sym_id,
881                                     sectinfo->startPrbc, sectinfo->numPrbc,
882                                     cc_id, ant_id,
883                                     xran_get_seqid(pHandle, direction, cc_id, ant_id, slot_id));
884                     }
885                 }
886
887             else {  /* if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU && p_xran_lib_ctx->enableCP) */
888                 /* pointer to IQs input */
889                 pos = (char*) p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
890 #ifdef DEBUG_XRAN_BUFFERS
891                 if (pos[0] != tti % XRAN_N_FE_BUF_LEN ||
892                     pos[1] != cc_id ||
893                     pos[2] != ant_id ||
894                     pos[3] != sym_id)
895                         printf("%d %d %d %d\n", pos[0], pos[1], pos[2], pos[3]);
896 #endif
897                 send_symbol_ex(direction,
898                                 xran_alloc_sectionid(pHandle, direction, cc_id, ant_id, slot_id),
899                                 (struct rb_map *)pos,
900                                 frame_id, subframe_id, slot_id, sym_id,
901                                 0, prb_num,
902                                 cc_id, ant_id,
903                                 xran_get_seqid(pHandle, direction, cc_id, ant_id, slot_id));
904                 }
905             }
906         }
907
908     MLogTask(PID_PROCESS_TX_SYM, t1, MLogTick());
909     return 0;
910 }
911
912 int xran_packet_and_dpdk_timer_thread(void *args)
913 {
914     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
915
916     uint64_t prev_tsc = 0;
917     uint64_t cur_tsc = rte_rdtsc();
918     uint64_t diff_tsc = cur_tsc - prev_tsc;
919     cpu_set_t cpuset;
920     struct sched_param sched_param;
921     int res = 0;
922     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());
923
924     sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;
925
926     if ((res  = pthread_setschedparam(pthread_self(), 1, &sched_param)))
927     {
928         printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);
929     }
930
931     while(1){
932
933         cur_tsc  = rte_rdtsc();
934         diff_tsc = cur_tsc - prev_tsc;
935         if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
936             rte_timer_manage();
937             prev_tsc = cur_tsc;
938         }
939
940         if (XRAN_STOPPED == xran_if_current_state)
941             break;
942     }
943
944     printf("Closing pkts timer thread...\n");
945     return 0;
946 }
947
948
949 int32_t xran_init(int argc, char *argv[], PXRANFHINIT p_xran_fh_init, char *appName, void ** pHandle)
950 {
951     int i;
952     int j;
953
954     struct xran_io_loop_cfg *p_io_cfg = (struct xran_io_loop_cfg *)&p_xran_fh_init->io_cfg;
955     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
956
957     int  lcore_id = 0;
958     char filename[64];
959
960     memset(p_xran_lib_ctx, 0, sizeof(struct xran_lib_ctx));
961     /* copy init */
962     p_xran_lib_ctx->xran_init_cfg = *p_xran_fh_init;
963
964     xran_if_current_state = XRAN_RUNNING;
965     interval_us =  p_xran_fh_init->ttiPeriod;
966
967     p_xran_lib_ctx->llscu_id = p_xran_fh_init->llscuId;
968     memcpy(&(p_xran_lib_ctx->eAxc_id_cfg), &(p_xran_fh_init->eAxCId_conf), sizeof(XRANEAXCIDCONFIG));
969
970     p_xran_lib_ctx->enableCP = p_xran_fh_init->enableCP;
971
972     xran_register_ethertype_handler(ETHER_TYPE_ECPRI, handle_ecpri_ethertype);
973     if (p_io_cfg->id == 0)
974         xran_ethdi_init_dpdk_io(basename(appName),
975                            p_io_cfg,
976                            &lcore_id,
977                            (struct ether_addr *)p_xran_fh_init->p_lls_cu_addr,
978                            (struct ether_addr *)p_xran_fh_init->p_ru_addr,
979                            p_xran_fh_init->cp_vlan_tag,
980                            p_xran_fh_init->up_vlan_tag);
981     else
982         xran_ethdi_init_dpdk_io(basename(appName),
983                            p_io_cfg,
984                            &lcore_id,
985                            (struct ether_addr *)p_xran_fh_init->p_ru_addr,
986                            (struct ether_addr *)p_xran_fh_init->p_lls_cu_addr,
987                            p_xran_fh_init->cp_vlan_tag,
988                            p_xran_fh_init->up_vlan_tag);
989
990     for(i = 0; i < 10; i++ )
991         rte_timer_init(&tti_to_phy_timer[i]);
992
993     rte_timer_init(&tti_timer);
994     rte_timer_init(&sym_timer);
995     rte_timer_init(&tx_cp_dl_timer);
996     rte_timer_init(&tx_cp_ul_timer);
997     rte_timer_init(&tx_up_timer);
998
999     for(i = 0; i < XRAN_MAX_SECTOR_NR;  i++ ){
1000         unsigned n = snprintf(&p_xran_lib_ctx->ring_name[0][i][0], RTE_RING_NAMESIZE, "dl_sym_ring_%u", i);
1001         p_xran_lib_ctx->dl_sym_idx_ring[i]   = rte_ring_create(&p_xran_lib_ctx->ring_name[0][i][0], XRAN_RING_SIZE,
1002                                                rte_lcore_to_socket_id(lcore_id), RING_F_SP_ENQ | RING_F_SC_DEQ);
1003     }
1004
1005
1006     lcore_id = rte_get_next_lcore(lcore_id, 0, 0);
1007     PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()");
1008
1009     /* Start packet processing thread */
1010     if (rte_eal_remote_launch(ring_processing_thread, NULL, lcore_id))
1011         rte_panic("ring_processing_thread() failed to start\n");
1012
1013     if(p_io_cfg->pkt_aux_core > 0){
1014         lcore_id = rte_get_next_lcore(lcore_id, 0, 0);
1015         PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()");
1016
1017         /* Start packet processing thread */
1018         if (rte_eal_remote_launch(xran_packet_and_dpdk_timer_thread, NULL, lcore_id))
1019             rte_panic("ring_processing_thread() failed to start\n");
1020     }
1021
1022     lcore_id = rte_get_next_lcore(lcore_id, 0, 0);
1023     PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()");
1024
1025     /* Start packet processing thread */
1026     if (rte_eal_remote_launch(xran_timing_source_thread, xran_lib_get_ctx(), lcore_id))
1027         rte_panic("thread_run() failed to start\n");
1028
1029     printf("Set debug stop %d\n", p_xran_fh_init->debugStop);
1030     timing_set_debug_stop(p_xran_fh_init->debugStop);
1031
1032     memset(&DevHandle, 0, sizeof(XranLibHandleInfoStruct));
1033
1034     *pHandle = &DevHandle;
1035
1036     return 0;
1037 }
1038
1039 int32_t xran_sector_get_instances (void * pHandle, uint16_t nNumInstances,
1040                XranCcInstanceHandleVoidP * pSectorInstanceHandles)
1041 {
1042     int i;
1043
1044     /* only one handle as only one CC is currently supported */
1045     for(i = 0; i < nNumInstances; i++ )
1046         pSectorInstanceHandles[i] = pHandle;
1047
1048     return 0;
1049 }
1050
1051 int32_t xran_mm_init (void * pHandle, uint64_t nMemorySize,
1052             uint32_t nMemorySegmentSize)
1053 {
1054     /* we use mbuf from dpdk memory */
1055     return 0;
1056 }
1057
1058 int32_t xran_bm_init (void * pHandle, uint32_t * pPoolIndex, uint32_t nNumberOfBuffers, uint32_t nBufferSize)
1059 {
1060     XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle;
1061
1062     char pool_name[RTE_MEMPOOL_NAMESIZE];
1063
1064     snprintf(pool_name, RTE_MEMPOOL_NAMESIZE, "bm_mempool_%ld", pPoolIndex);
1065
1066     pXran->p_bufferPool[pXran->nBufferPoolIndex] = rte_pktmbuf_pool_create(pool_name, nNumberOfBuffers,
1067            MBUF_CACHE, 0, XRAN_MAX_MBUF_LEN, rte_socket_id());
1068
1069     pXran->bufferPoolElmSz[pXran->nBufferPoolIndex]  = nBufferSize;
1070     pXran->bufferPoolNumElm[pXran->nBufferPoolIndex] = nNumberOfBuffers;
1071
1072     print_dbg("[nPoolIndex %d] mb pool %p \n", pXran->nBufferPoolIndex,  pXran->p_bufferPool[pXran->nBufferPoolIndex]);
1073
1074     *pPoolIndex = pXran->nBufferPoolIndex++;
1075
1076     return 0;
1077 }
1078
1079 int32_t xran_bm_allocate_buffer(void * pHandle, uint32_t nPoolIndex, void **ppVirtAddr)
1080 {
1081     XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle;
1082     *ppVirtAddr = NULL;
1083
1084     struct rte_mbuf * mb =  rte_pktmbuf_alloc(pXran->p_bufferPool[nPoolIndex]);
1085
1086     if(mb){
1087         *ppVirtAddr = rte_pktmbuf_append(mb, pXran->bufferPoolElmSz[nPoolIndex]);
1088
1089     }else {
1090         print_err("[nPoolIndex %d] mb alloc failed \n", nPoolIndex );
1091         return -1;
1092     }
1093
1094     if (*ppVirtAddr ==  NULL){
1095         print_err("[nPoolIndex %d] rte_pktmbuf_append for %d failed \n", nPoolIndex, pXran->bufferPoolElmSz[nPoolIndex]);
1096         return -1;
1097     }
1098
1099     return 0;
1100 }
1101
1102 int32_t xran_bm_free_buffer(void * pHandle, void *pVirtAddr)
1103 {
1104     XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle;
1105     rte_pktmbuf_free(pVirtAddr);
1106
1107     return 0;
1108 }
1109
1110 int32_t xran_5g_fronthault_config (void * pHandle,
1111                 XRANBufferListStruct *pSrcBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],
1112                 XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],
1113                 XranTransportBlockCallbackFn pCallback,
1114                 void *pCallbackTag)
1115 {
1116     XranLibHandleInfoStruct *pInfo = (XranLibHandleInfoStruct *) pHandle;
1117     XranStatusInt32 nStatus = XRAN_STATUS_SUCCESS;
1118     int j, i = 0, z, k;
1119     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
1120
1121     print_dbg("%s\n", __FUNCTION__);
1122
1123     if(NULL == pHandle)
1124     {
1125         printf("Handle is NULL!\n");
1126         return XRAN_STATUS_FAIL;
1127     }
1128     if (pCallback == NULL)
1129     {
1130         printf ("no callback\n");
1131         return XRAN_STATUS_FAIL;
1132     }
1133
1134     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
1135     {
1136         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
1137            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0;
1138            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
1139            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
1140            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
1141            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
1142            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFrontHaulTxBuffers[j][i][z][0];
1143
1144            p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList =   *pSrcBuffer[z][j];
1145
1146            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0;
1147            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
1148            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
1149            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
1150            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
1151            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFrontHaulRxBuffers[j][i][z][0];
1152            p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList =   *pDstBuffer[z][j];
1153         }
1154     }
1155
1156 #if 0
1157     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
1158         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
1159             printf("TTI:TX 0x%02x Sec %d Ant%d\n",j,i,z);
1160             for(k = 0; k <XRAN_NUM_OF_SYMBOL_PER_SLOT; k++){
1161                 uint8_t *ptr = p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData;
1162                 printf("    sym: %2d %p 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", k, ptr, ptr[0],ptr[1], ptr[2], ptr[3], ptr[4]);
1163             }
1164         }
1165
1166     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
1167         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
1168             printf("TTI:RX 0x%02x Sec %d Ant%d\n",j,i,z);
1169             for(k = 0; k <XRAN_NUM_OF_SYMBOL_PER_SLOT; k++){
1170                 uint8_t *ptr = p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData;
1171                 printf("    sym: %2d %p 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", k, ptr, ptr[0],ptr[1], ptr[2], ptr[3], ptr[4]);
1172             }
1173         }
1174 #endif
1175
1176     p_xran_lib_ctx->pCallback[i]    = pCallback;
1177     p_xran_lib_ctx->pCallbackTag[i] = pCallbackTag;
1178
1179     p_xran_lib_ctx->xran2phy_mem_ready = 1;
1180
1181     return nStatus;
1182 }
1183
1184 int32_t xran_5g_prach_req (void *  pHandle,
1185                 XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN],
1186                 XranTransportBlockCallbackFn pCallback,
1187                 void *pCallbackTag)
1188 {
1189     XranLibHandleInfoStruct *pInfo = (XranLibHandleInfoStruct *) pHandle;
1190     XranStatusInt32 nStatus = XRAN_STATUS_SUCCESS;
1191     int j, i = 0, z;
1192     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
1193
1194     if(NULL == pHandle)
1195     {
1196         printf("Handle is NULL!\n");
1197         return XRAN_STATUS_FAIL;
1198     }
1199     if (pCallback == NULL)
1200     {
1201         printf ("no callback\n");
1202         return XRAN_STATUS_FAIL;
1203     }
1204
1205     for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
1206     {
1207         for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
1208            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0;
1209            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
1210            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
1211            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
1212            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number.
1213            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFHPrachRxBuffers[j][i][z][0];
1214            p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList =   *pDstBuffer[z][j];
1215         }
1216     }
1217
1218     p_xran_lib_ctx->pPrachCallback[i]    = pCallback;
1219     p_xran_lib_ctx->pPrachCallbackTag[i] = pCallbackTag;
1220
1221     return 0;
1222 }
1223
1224 int32_t xran_5g_pre_compenstor_cfg(void* pHandle,
1225                 uint32_t nTxPhaseCps,
1226                 uint32_t nRxPhaseCps,
1227                 uint8_t nSectorId)
1228 {
1229     /* functionality is not yet implemented */
1230     return 0;
1231 }
1232
1233 int32_t xran_open(void *pHandle, PXRANFHCONFIG pConf)
1234 {
1235     int i;
1236     uint8_t slotNr;
1237     XRANFHCONFIG *pFhCfg;
1238     xRANPrachCPConfigStruct *pPrachCPConfig = &(xran_lib_get_ctx()->PrachCPConfig);
1239     pFhCfg = &(xran_lib_get_ctx()->xran_fh_cfg);
1240     memcpy(pFhCfg, pConf, sizeof(XRANFHCONFIG));
1241     PXRANPRACHCONFIG pPRACHConfig = &pFhCfg->prach_conf;
1242     uint8_t nPrachConfIdx = pPRACHConfig->nPrachConfIdx;
1243     const xRANPrachConfigTableStruct *pxRANPrachConfigTable = &gxranPrachDataTable_mmw[nPrachConfIdx];
1244     uint8_t preambleFmrt = pxRANPrachConfigTable->preambleFmrt[0];
1245     const xRANPrachPreambleLRAStruct *pxranPreambleforLRA = &gxranPreambleforLRA[preambleFmrt - FORMAT_A1];
1246     memset(pPrachCPConfig, 0, sizeof(xRANPrachCPConfigStruct));
1247
1248     //setup PRACH configuration for C-Plane
1249     pPrachCPConfig->filterIdx = XRAN_FILTERINDEX_PRACH_ABC;         // 3, PRACH preamble format A1~3, B1~4, C0, C2
1250     pPrachCPConfig->startSymId = pxRANPrachConfigTable->startingSym;
1251     pPrachCPConfig->startPrbc = pPRACHConfig->nPrachFreqStart;
1252     pPrachCPConfig->numPrbc = (preambleFmrt >= FORMAT_A1)? 12 : 70;
1253     pPrachCPConfig->numSymbol = pxRANPrachConfigTable->duration;
1254     pPrachCPConfig->timeOffset = pxranPreambleforLRA->nRaCp;
1255     pPrachCPConfig->freqOffset = xran_get_freqoffset(pPRACHConfig->nPrachFreqOffset, pPRACHConfig->nPrachSubcSpacing);
1256     pPrachCPConfig->occassionsInPrachSlot = pxRANPrachConfigTable->occassionsInPrachSlot;
1257     pPrachCPConfig->x = pxRANPrachConfigTable->x;
1258     pPrachCPConfig->y[0] = pxRANPrachConfigTable->y[0];
1259     pPrachCPConfig->y[1] = pxRANPrachConfigTable->y[1];
1260
1261     pPrachCPConfig->isPRACHslot[pxRANPrachConfigTable->slotNr[0]] = 1;
1262     for (i=1; i < XRAN_PRACH_CANDIDATE_SLOT; i++)
1263     {
1264         slotNr = pxRANPrachConfigTable->slotNr[i];
1265         if (slotNr > 0)
1266             pPrachCPConfig->isPRACHslot[slotNr] = 1;
1267     }
1268
1269     xran_cp_init_sectiondb(pHandle);
1270     xran_init_sectionid(pHandle);
1271     xran_init_seqid(pHandle);
1272
1273     return 0;
1274 }
1275
1276 int32_t xran_start(void *pHandle)
1277 {
1278     xran_if_current_state = XRAN_RUNNING;
1279     return 0;
1280 }
1281
1282 int32_t xran_stop(void *pHandle)
1283 {
1284     xran_if_current_state = XRAN_STOPPED;
1285     return 0;
1286 }
1287
1288 int32_t xran_close(void *pHandle)
1289 {
1290     xran_if_current_state = XRAN_STOPPED;
1291     xran_cp_free_sectiondb(pHandle);
1292     rte_eal_mp_wait_lcore();
1293     return 0;
1294 }
1295
1296 int32_t xran_mm_destroy (void * pHandle)
1297 {
1298     /* functionality is not yet implemented */
1299     return -1;
1300 }
1301
1302 int32_t xran_reg_sym_cb(void *pHandle, XRANFHSYMPROCCB symCb, void * symCbParam, uint8_t symb,  uint8_t ant)
1303 {
1304     /* functionality is not yet implemented */
1305     return -1;
1306 }
1307
1308 int32_t xran_reg_physide_cb(void *pHandle, XRANFHTTIPROCCB Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id id)
1309 {
1310     struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx();
1311
1312     p_xran_lib_ctx->ttiCb[id]      = Cb;
1313     p_xran_lib_ctx->TtiCbParam[id] = cbParam;
1314     p_xran_lib_ctx->SkipTti[id]    = skipTtiNum;
1315
1316     return 0;
1317 }
1318
1319 int32_t xran_get_slot_idx (uint32_t *nFrameIdx, uint32_t *nSubframeIdx,  uint32_t *nSlotIdx, uint64_t *nSecond)
1320 {
1321     int32_t tti = 0;
1322
1323     tti           = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT);
1324     *nSlotIdx     = (uint32_t)XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME);
1325     *nSubframeIdx = (uint32_t)XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME,  SUBFRAMES_PER_SYSTEMFRAME);
1326     *nFrameIdx    = (uint32_t)XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME);
1327     *nSecond      = timing_get_current_second();
1328
1329     return tti;
1330 }
1331
1332 /**
1333  * @brief Get supported maximum number of sections
1334  *
1335  * @return maximum number of sections
1336  */
1337 inline uint8_t xran_get_max_sections(void *pHandle)
1338 {
1339     return (XRAN_MAX_NUM_SECTIONS);
1340 }
1341
1342 /**
1343  * @brief Get the configuration of eAxC ID
1344  *
1345  * @return the pointer of configuration
1346  */
1347 inline XRANEAXCIDCONFIG *xran_get_conf_eAxC(void *pHandle)
1348 {
1349     return (&(xran_lib_get_ctx()->eAxc_id_cfg));
1350 }
1351
1352 /**
1353  * @brief Get the configuration of subcarrier spacing for PRACH
1354  *
1355  * @return subcarrier spacing value for PRACH
1356  */
1357 inline uint8_t xran_get_conf_prach_scs(void *pHandle)
1358 {
1359     return (xran_lib_get_ctx_fhcfg()->prach_conf.nPrachSubcSpacing);
1360 }
1361
1362 /**
1363  * @brief Get the configuration of FFT size for RU
1364  *
1365  * @return FFT size value for RU
1366  */
1367 inline uint8_t xran_get_conf_fftsize(void *pHandle)
1368 {
1369     return (xran_lib_get_ctx_fhcfg()->ru_conf.fftSize);
1370 }
1371
1372 /**
1373  * @brief Get the configuration of nummerology
1374  *
1375  * @return subcarrier spacing value for PRACH
1376  */
1377 inline uint8_t xran_get_conf_numerology(void *pHandle)
1378 {
1379     return (xran_lib_get_ctx_fhcfg()->frame_conf.nNumerology);
1380 }
1381
1382 /**
1383  * @brief Get the configuration of IQ bit width for RU
1384  *
1385  * @return IQ bit width for RU
1386  */
1387 inline uint8_t xran_get_conf_iqwidth(void *pHandle)
1388 {
1389   XRANFHCONFIG *pFhCfg;
1390
1391     pFhCfg = xran_lib_get_ctx_fhcfg();
1392     return ((pFhCfg->ru_conf.iqWidth==16)?0:pFhCfg->ru_conf.iqWidth);
1393 }
1394
1395 /**
1396  * @brief Get the configuration of compression method for RU
1397  *
1398  * @return Compression method for RU
1399  */
1400 inline uint8_t xran_get_conf_compmethod(void *pHandle)
1401 {
1402     return (xran_lib_get_ctx_fhcfg()->ru_conf.compMeth);
1403 }
1404
1405 /**
1406  * @brief Get the configuration of lls-cu ID
1407  *
1408  * @return Configured lls-cu ID
1409  */
1410 inline uint8_t xran_get_llscuid(void *pHandle)
1411 {
1412     return (xran_lib_get_ctx()->llscu_id);
1413 }
1414
1415 /**
1416  * @brief Get the configuration of lls-cu ID
1417  *
1418  * @return Configured lls-cu ID
1419  */
1420 inline uint8_t xran_get_sectorid(void *pHandle)
1421 {
1422     return (xran_lib_get_ctx()->sector_id);
1423 }
1424
1425 /**
1426  * @brief Get the configuration of the number of component carriers
1427  *
1428  * @return Configured the number of componen carriers
1429  */
1430 inline uint8_t xran_get_num_cc(void *pHandle)
1431 {
1432     return (xran_lib_get_ctx_fhcfg()->nCC);
1433 }
1434
1435 /**
1436  * @brief Get the configuration of the number of antenna
1437  *
1438  * @return Configured the number of antenna
1439  */
1440 inline uint8_t xran_get_num_eAxc(void *pHandle)
1441 {
1442     return (xran_lib_get_ctx_fhcfg()->neAxc);
1443 }
1444
1445