Front Haul Interface Library first seed code contribution
[o-du/phy.git] / fhi_lib / lib / src / xran_common.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 #ifndef _XRAN_COMMON_
20 #define _XRAN_COMMON_
21
22 /**
23  * @brief XRAN layer common functionality for both lls-CU and RU as well as C-plane and
24  *    U-plane
25  * @file xran_common.c
26  * @ingroup group_source_xran
27  * @author Intel Corporation
28  **/
29
30 #include <assert.h>
31 #include <err.h>
32 #include <arpa/inet.h>
33 #include <sys/time.h>
34 #include <time.h>
35
36 #include "xran_common.h"
37 #include "ethdi.h"
38 #include "xran_pkt.h"
39 #include "xran_pkt_up.h"
40 #include "xran_cp_api.h"
41 #include "xran_up_api.h"
42 #include "../src/xran_printf.h"
43
44 #ifndef MLOG_ENABLED
45 #include "mlog_lnx_xRAN.h"
46 #else
47 #include "mlog_lnx.h"
48 #endif
49
50 #define MBUFS_CNT 256
51
52 extern int xran_process_rx_sym(void *arg,
53                         void *iq_data_start,
54                         uint16_t size,
55                         uint8_t CC_ID,
56                         uint8_t Ant_ID,
57                         uint8_t frame_id,
58                         uint8_t subframe_id,
59                         uint8_t slot_id,
60                         uint8_t symb_id);
61
62
63 int process_mbuf(struct rte_mbuf *pkt)
64 {
65     void *iq_samp_buf;
66     struct ecpri_seq_id seq;
67     static int symbol_total_bytes = 0;
68     int num_bytes = 0;
69     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
70     uint8_t CC_ID = 0;
71     uint8_t Ant_ID = 0;
72     uint8_t frame_id = 0;
73     uint8_t subframe_id = 0;
74     uint8_t slot_id = 0;
75     uint8_t symb_id = 0;
76
77     num_bytes = xran_extract_iq_samples(pkt,
78                                         &iq_samp_buf,
79                                         &CC_ID,
80                                         &Ant_ID,
81                                         &frame_id,
82                                         &subframe_id,
83                                         &slot_id,
84                                         &symb_id,
85                                         &seq);
86     if (num_bytes <= 0)
87         return -1;
88
89     symbol_total_bytes += num_bytes;
90
91     if (seq.e_bit == 1) {
92         print_dbg("Completed receiving symbol %d, size=%d bytes\n",
93             symb_id, symbol_total_bytes);
94
95         if (symbol_total_bytes)
96             xran_process_rx_sym(NULL,
97                             iq_samp_buf,
98                             symbol_total_bytes,
99                             CC_ID,
100                             Ant_ID,
101                             frame_id,
102                             subframe_id,
103                             slot_id,
104                             symb_id);
105         symbol_total_bytes = 0;
106     }
107
108     return 0;
109 }
110
111 static int set_iq_bit_width(uint8_t iq_bit_width, struct data_section_compression_hdr *compr_hdr)
112 {
113     if (iq_bit_width == MAX_IQ_BIT_WIDTH)
114         compr_hdr->ud_comp_hdr.ud_iq_width = (uint8_t) 0;
115     else
116         compr_hdr->ud_comp_hdr.ud_iq_width = iq_bit_width;
117
118     return  0;
119
120 }
121
122 /* Send a single 5G symbol over multiple packets */
123 int send_symbol_ex(enum xran_pkt_dir direction,
124                 uint16_t section_id,
125                 struct rb_map *data,
126                 uint8_t frame_id,
127                 uint8_t subframe_id,
128                 uint8_t slot_id,
129                 uint8_t symbol_no,
130                 int prb_start,
131                 int prb_num,
132                 uint8_t CC_ID,
133                 uint8_t RU_Port_ID,
134                 uint8_t seq_id)
135 {
136     const int n_bytes = prb_num * N_SC_PER_PRB * sizeof(struct rb_map);
137     int sent;
138     uint32_t off;
139     struct xran_up_pkt_gen_no_compression_params xp = { 0 };
140
141     /* radio app header */
142     xp.app_params.data_direction = direction;
143     xp.app_params.payl_ver       = 1;
144     xp.app_params.filter_id      = 0;
145     xp.app_params.frame_id       = frame_id;
146     xp.app_params.sf_slot_sym.subframe_id    = subframe_id;
147     xp.app_params.sf_slot_sym.slot_id        = slot_id;
148     xp.app_params.sf_slot_sym.symb_id        = symbol_no;
149
150     /* convert to network byte order */
151     xp.app_params.sf_slot_sym.value = rte_cpu_to_be_16(xp.app_params.sf_slot_sym.value);
152
153     xp.sec_hdr.fields.sect_id    = section_id;
154     xp.sec_hdr.fields.num_prbu   = (uint8_t)prb_num;
155     xp.sec_hdr.fields.start_prbu = (uint8_t)prb_start;
156     xp.sec_hdr.fields.sym_inc    = 0;
157     xp.sec_hdr.fields.rb         = 0;
158
159     /* network byte order */
160     xp.sec_hdr.fields.all_bits  = rte_cpu_to_be_32(xp.sec_hdr.fields.all_bits);
161
162     struct rte_mbuf *mb = xran_ethdi_mbuf_alloc();
163
164     if (mb == NULL){
165         MLogPrint(NULL);
166         errx(1, "out of mbufs after %d packets", 1);
167     }
168
169     sent = xran_prepare_iq_symbol_portion_no_comp(mb,
170                                                   data,
171                                                   n_bytes,
172                                                   &xp,
173                                                   CC_ID,
174                                                   RU_Port_ID,
175                                                   seq_id);
176     if (sent <= 0)
177         errx(1, "failed preparing symbol");
178
179     xran_ethdi_mbuf_send(mb, ETHER_TYPE_ECPRI);
180
181 #ifdef DEBUG
182     printf("Symbol %2d sent (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
183 #endif
184
185     return sent;
186 }
187
188 int send_cpmsg_dlul(void *pHandle, enum xran_pkt_dir dir,
189                 uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
190                 uint8_t startsym, uint8_t numsym, int prb_num,
191                 uint16_t beam_id,
192                 uint8_t cc_id, uint8_t ru_port_id,
193                 uint8_t seq_id)
194 {
195   struct xran_cp_gen_params params;
196   struct xran_section_gen_info sect_geninfo[XRAN_MAX_NUM_SECTIONS];
197   struct rte_mbuf *mbuf;
198   int ret, nsection, i;
199
200
201     params.dir                  = dir;
202     params.sectionType          = XRAN_CP_SECTIONTYPE_1;     // Most DL/UL Radio Channels
203     params.hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;
204     params.hdr.frameId          = frame_id;
205     params.hdr.subframeId       = subframe_id;
206     params.hdr.slotId           = slot_id;
207     params.hdr.startSymId       = startsym;                 // start Symbol ID
208     params.hdr.iqWidth          = xran_get_conf_iqwidth(pHandle);
209     params.hdr.compMeth         = xran_get_conf_compmethod(pHandle);
210
211     nsection = 0;
212     sect_geninfo[nsection].info.type        = params.sectionType;
213     sect_geninfo[nsection].info.id          = xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id);
214     sect_geninfo[nsection].info.rb          = XRAN_RBIND_EVERY;
215     sect_geninfo[nsection].info.symInc      = XRAN_SYMBOLNUMBER_NOTINC;
216     sect_geninfo[nsection].info.startPrbc   = 0;
217     sect_geninfo[nsection].info.numPrbc     = NUM_OF_PRB_IN_FULL_BAND,
218     sect_geninfo[nsection].info.numSymbol   = numsym;
219     sect_geninfo[nsection].info.reMask      = 0xfff;
220     sect_geninfo[nsection].info.beamId      = beam_id;
221
222     sect_geninfo[nsection].info.ef          = 0;      // no extension
223     sect_geninfo[nsection].exDataSize       = 0;
224     sect_geninfo[nsection].exData           = NULL;
225     nsection++;
226
227     params.numSections          = nsection;
228     params.sections             = sect_geninfo;
229
230     mbuf = xran_ethdi_mbuf_alloc();
231     if(unlikely(mbuf == NULL)) {
232         print_err("Alloc fail!\n");
233         return (-1);
234         }
235
236     ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id);
237     if(ret < 0) {
238         print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
239                     frame_id, subframe_id, slot_id, dir);
240         }
241     else {
242         xran_ethdi_mbuf_send_cp(mbuf, ETHER_TYPE_ECPRI);
243         for(i=0; i<nsection; i++)
244             xran_cp_add_section_info(pHandle,
245                     dir, cc_id, ru_port_id, subframe_id, slot_id,
246                     &sect_geninfo[i].info);
247         }
248
249     return (ret);
250 }
251
252 int send_cpmsg_prach(void *pHandle,
253                 uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
254                 uint16_t beam_id, uint8_t cc_id, uint8_t prach_port_id,
255                 uint8_t seq_id)
256 {
257     struct xran_cp_gen_params params;
258     struct xran_section_gen_info sect_geninfo[8];
259     struct rte_mbuf *mbuf;
260     int i, nsection, ret;
261     struct xran_lib_ctx *pxran_lib_ctx = xran_lib_get_ctx();
262     xRANPrachCPConfigStruct *pPrachCPConfig = &(pxran_lib_ctx->PrachCPConfig);
263
264 #if 0
265     printf("%d:%d:%d:%d - filter=%d, startSym=%d[%d:%d], numSym=%d, occasions=%d, freqOff=%d\n",
266                 frame_id, subframe_id, slot_id, prach_port_id,
267                 pPrachCPConfig->filterIdx,
268                 pPrachCPConfig->startSymId,
269                 pPrachCPConfig->startPrbc,
270                 pPrachCPConfig->numPrbc,
271                 pPrachCPConfig->numSymbol,
272                 pPrachCPConfig->occassionsInPrachSlot,
273                 pPrachCPConfig->freqOffset);
274 #endif
275
276     params.dir                  = XRAN_DIR_UL;
277     params.sectionType          = XRAN_CP_SECTIONTYPE_3;
278     params.hdr.filterIdx        = pPrachCPConfig->filterIdx;
279     params.hdr.frameId          = frame_id;
280     params.hdr.subframeId       = subframe_id;
281     params.hdr.slotId           = slot_id;
282     params.hdr.startSymId       = pPrachCPConfig->startSymId;
283     params.hdr.iqWidth          = xran_get_conf_iqwidth(pHandle);
284     params.hdr.compMeth         = xran_get_conf_compmethod(pHandle);
285         /* use timeOffset field for the CP length value for prach sequence */
286     params.hdr.timeOffset       = pPrachCPConfig->timeOffset;
287     params.hdr.fftSize          = xran_get_conf_fftsize(pHandle);
288     params.hdr.scs              = xran_get_conf_prach_scs(pHandle);
289     params.hdr.cpLength         = 0;
290
291     nsection = 0;
292     sect_geninfo[nsection].info.type      = params.sectionType;
293     sect_geninfo[nsection].info.id        = xran_alloc_sectionid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);
294     sect_geninfo[nsection].info.rb        = XRAN_RBIND_EVERY;
295     sect_geninfo[nsection].info.symInc    = XRAN_SYMBOLNUMBER_NOTINC;
296     sect_geninfo[nsection].info.startPrbc = pPrachCPConfig->startPrbc;
297     sect_geninfo[nsection].info.numPrbc   = pPrachCPConfig->numPrbc,
298     sect_geninfo[nsection].info.numSymbol = pPrachCPConfig->numSymbol*pPrachCPConfig->occassionsInPrachSlot;
299     sect_geninfo[nsection].info.reMask    = 0xfff;
300     sect_geninfo[nsection].info.beamId    = beam_id;
301     sect_geninfo[nsection].info.freqOffset= pPrachCPConfig->freqOffset;
302
303     sect_geninfo[nsection].info.ef        = 0;      // no extension
304     sect_geninfo[nsection].exDataSize     = 0;
305     sect_geninfo[nsection].exData         = NULL;
306     nsection++;
307
308     params.numSections          = nsection;
309     params.sections             = sect_geninfo;
310
311     mbuf = xran_ethdi_mbuf_alloc();
312     if(unlikely(mbuf == NULL)) {
313         print_err("Alloc fail!\n");
314         return (-1);
315         }
316
317     ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, prach_port_id, seq_id);
318     if(ret < 0) {
319         print_err("Fail to build prach control packet - [%d:%d:%d]\n", frame_id, subframe_id, slot_id);
320         return (ret);
321         }
322     else {
323         xran_ethdi_mbuf_send_cp(mbuf, ETHER_TYPE_ECPRI);
324         for(i=0; i < nsection; i++)
325             xran_cp_add_section_info(pHandle,
326                     XRAN_DIR_UL, cc_id, prach_port_id, subframe_id, slot_id,
327                     &sect_geninfo[i].info);
328         }
329
330     return (ret);
331 }
332
333
334 int process_ring(struct rte_ring *r)
335 {
336     assert(r);
337
338     struct rte_mbuf *mbufs[MBUFS_CNT];
339     int i;
340     uint32_t remaining;
341     const uint16_t dequeued = rte_ring_dequeue_burst(r, (void **)mbufs,
342         RTE_DIM(mbufs), &remaining);
343
344     if (!dequeued)
345         return 0;
346     for (i = 0; i < dequeued; ++i) {
347         if (xran_ethdi_filter_packet(mbufs[i], 0) == MBUF_FREE)
348             rte_pktmbuf_free(mbufs[i]);
349     }
350
351     return remaining;
352 }
353
354 int ring_processing_thread(void *args)
355 {
356     struct timespec tv = {0};
357     int64_t prev_nsec = 0;
358     uint8_t is_timer_set = 0;
359     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
360     struct sched_param sched_param;
361     int res = 0;
362
363     printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__,  rte_lcore_id(), getpid());
364     sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;
365     if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param)))
366     {
367         printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);
368     }
369     for (;;) {
370         if (!is_timer_set) {
371             if (clock_gettime(CLOCK_REALTIME, &tv) != 0)
372                 err(1, "gettimeofday() failed");
373             if (tv.tv_nsec % 125000 < prev_nsec % 125000) { /* crossed an 125ms boundary */
374                 rte_timer_manage();     /* timers only run on IO core */
375                 is_timer_set = 1;
376             }
377             prev_nsec = tv.tv_nsec;
378         } else {
379             rte_timer_manage();
380         }
381
382         /* UP first */
383         if (process_ring(ctx->rx_ring[ETHDI_UP_VF]))
384             continue;
385         /* CP next */
386         if (process_ring(ctx->rx_ring[ETHDI_CP_VF]))
387             continue;
388
389         if (XRAN_STOPPED == xran_if_current_state)
390             break;
391     }
392
393     puts("Pkt processing thread finished.");
394     return 0;
395 }
396
397 #endif /* _XRAN_COMMON_ */