1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
20 * @brief XRAN layer common functionality for both O-DU and O-RU as well as C-plane and
23 * @ingroup group_source_xran
24 * @author Intel Corporation
29 #include <arpa/inet.h>
33 #include "xran_common.h"
36 #include "xran_pkt_up.h"
37 #include "xran_up_api.h"
38 #include "xran_lib_mlog_tasks_id.h"
40 #include "../src/xran_printf.h"
42 #include "xran_mlog_lnx.h"
46 extern long interval_us;
48 extern int xran_process_rx_sym(void *arg,
49 struct rte_mbuf *mbuf,
66 extern int xran_process_prach_sym(void *arg,
67 struct rte_mbuf *mbuf,
83 extern int32_t xran_process_srs_sym(void *arg,
84 struct rte_mbuf *mbuf,
100 extern int32_t xran_pkt_validate(void *arg,
101 struct rte_mbuf *mbuf,
110 struct ecpri_seq_id *seq_id,
119 long tx_bytes_counter = 0;
120 long rx_bytes_counter = 0;
121 long tx_bytes_per_sec = 0;
122 long rx_bytes_per_sec = 0;
125 struct cb_elem_entry *xran_create_cb(XranSymCallbackFn cb_fn, void *cb_data)
127 struct cb_elem_entry * cb_elm = (struct cb_elem_entry *)malloc(sizeof(struct cb_elem_entry));
129 cb_elm->pSymCallback = cb_fn;
130 cb_elm->pSymCallbackTag = cb_data;
136 int xran_destroy_cb(struct cb_elem_entry * cb_elm)
143 int process_mbuf(struct rte_mbuf *pkt)
146 struct ecpri_seq_id seq;
147 static int symbol_total_bytes = 0;
149 struct xran_device_ctx * p_x_ctx = xran_dev_get_ctx();
153 uint8_t frame_id = 0;
154 uint8_t subframe_id = 0;
164 uint8_t compMeth = 0;
167 void *pHandle = NULL;
168 uint8_t num_eAxc = xran_get_num_eAxc(pHandle);
170 uint32_t mb_free = 0;
171 int32_t valid_res = 0;
172 int expect_comp = (p_x_ctx->fh_cfg.ru_conf.compMeth != XRAN_COMPMETHOD_NONE);
175 if(p_x_ctx->xran2phy_mem_ready == 0)
178 num_bytes = xran_extract_iq_samples(pkt,
196 print_err("num_bytes is wrong [%d]\n", num_bytes);
200 valid_res = xran_pkt_validate(NULL,
218 print_err("valid_res is wrong [%d] ant %u (%u : %u : %u : %u) seq %u num_bytes %d\n", valid_res, Ant_ID, frame_id, subframe_id, slot_id, symb_id, seq.seq_id, num_bytes);
222 if (Ant_ID >= p_x_ctx->srs_cfg.eAxC_offset && p_x_ctx->fh_init.srsEnable) {
223 /* SRS packet has ruportid = 2*num_eAxc + ant_id */
224 Ant_ID -= p_x_ctx->srs_cfg.eAxC_offset;
225 symbol_total_bytes += num_bytes;
227 if (seq.e_bit == 1) {
228 print_dbg("Completed receiving symbol %d, size=%d bytes\n",
229 symb_id, symbol_total_bytes);
231 if (symbol_total_bytes) {
232 int16_t res = xran_process_srs_sym(NULL,
249 if(res == symbol_total_bytes) {
252 print_err("res != symbol_total_bytes\n");
255 symbol_total_bytes = 0;
258 print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
261 } else if (Ant_ID >= p_x_ctx->PrachCPConfig.eAxC_offset && p_x_ctx->fh_init.prachEnable) {
262 /* PRACH packet has ruportid = num_eAxc + ant_id */
263 Ant_ID -= p_x_ctx->PrachCPConfig.eAxC_offset;
264 symbol_total_bytes += num_bytes;
265 if (seq.e_bit == 1) {
266 print_dbg("Completed receiving PRACH symbol %d, size=%d bytes\n",
269 if (symbol_total_bytes) {
270 int16_t res = xran_process_prach_sym(NULL,
286 if(res == symbol_total_bytes) {
289 print_err("res != symbol_total_bytes\n");
292 symbol_total_bytes = 0;
294 print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
298 symbol_total_bytes += num_bytes;
300 if (seq.e_bit == 1) {
301 print_dbg("Completed receiving symbol %d, size=%d bytes\n",
302 symb_id, symbol_total_bytes);
304 if (symbol_total_bytes) {
305 int res = xran_process_rx_sym(NULL,
321 if(res == symbol_total_bytes) {
324 print_err("res != symbol_total_bytes\n");
327 symbol_total_bytes = 0;
329 print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
336 static int set_iq_bit_width(uint8_t iq_bit_width, struct data_section_compression_hdr *compr_hdr)
338 if (iq_bit_width == MAX_IQ_BIT_WIDTH)
339 compr_hdr->ud_comp_hdr.ud_iq_width = (uint8_t) 0;
341 compr_hdr->ud_comp_hdr.ud_iq_width = iq_bit_width;
347 /* Send a single 5G symbol over multiple packets */
348 int32_t prepare_symbol_ex(enum xran_pkt_dir direction,
354 const enum xran_input_byte_order iq_buf_byte_order,
366 int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
368 n_bytes = ((iqWidth == 0) || (iqWidth == 16)) ? n_bytes : ((3 * iqWidth + 1 ) * prb_num);
372 int16_t nPktSize = sizeof(struct ether_hdr) + sizeof(struct xran_ecpri_hdr) +
373 sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes;
375 struct xran_up_pkt_gen_params xp = { 0 };
377 if(compMeth != XRAN_COMPMETHOD_NONE)
378 nPktSize += sizeof(struct data_section_compression_hdr);
380 n_bytes = RTE_MIN(n_bytes, XRAN_MAX_MBUF_LEN);
382 /* radio app header */
383 xp.app_params.data_direction = direction;
384 xp.app_params.payl_ver = 1;
385 xp.app_params.filter_id = 0;
386 xp.app_params.frame_id = frame_id;
387 xp.app_params.sf_slot_sym.subframe_id = subframe_id;
388 xp.app_params.sf_slot_sym.slot_id = slot_id;
389 xp.app_params.sf_slot_sym.symb_id = symbol_no;
391 /* convert to network byte order */
392 xp.app_params.sf_slot_sym.value = rte_cpu_to_be_16(xp.app_params.sf_slot_sym.value);
394 xp.sec_hdr.fields.sect_id = section_id;
395 xp.sec_hdr.fields.num_prbu = (uint8_t)prb_num;
396 xp.sec_hdr.fields.start_prbu = (uint8_t)prb_start;
397 xp.sec_hdr.fields.sym_inc = 0;
398 xp.sec_hdr.fields.rb = 0;
401 xp.compr_hdr_param.ud_comp_hdr.ud_comp_meth = compMeth;
402 xp.compr_hdr_param.ud_comp_hdr.ud_iq_width = iqWidth;
403 xp.compr_hdr_param.rsrvd = 0;
405 /* network byte order */
406 xp.sec_hdr.fields.all_bits = rte_cpu_to_be_32(xp.sec_hdr.fields.all_bits);
410 errx(1, "out of mbufs after %d packets", 1);
413 prep_bytes = xran_prepare_iq_symbol_portion(mb,
423 errx(1, "failed preparing symbol");
425 rte_pktmbuf_pkt_len(mb) = nPktSize;
426 rte_pktmbuf_data_len(mb) = nPktSize;
429 printf("Symbol %2d prep_bytes (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
435 /* Send a single 5G symbol over multiple packets */
436 int send_symbol_ex(enum xran_pkt_dir direction,
440 const enum xran_input_byte_order iq_buf_byte_order,
451 uint32_t do_copy = 0;
452 int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
453 struct xran_device_ctx *p_x_ctx = xran_dev_get_ctx();
457 mb = xran_ethdi_mbuf_alloc(); /* will be freede by ETH */
460 errx(1, "out of mbufs after %d packets", 1);
462 pChar = rte_pktmbuf_append(mb, sizeof(struct xran_ecpri_hdr)+ sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes);
465 errx(1, "incorrect mbuf size %d packets", 1);
467 pChar = rte_pktmbuf_prepend(mb, sizeof(struct ether_hdr));
470 errx(1, "incorrect mbuf size %d packets", 1);
472 do_copy = 1; /* new mbuf hence copy of IQs */
474 rte_pktmbuf_refcnt_update(mb, 1); /* make sure eth won't free our mbuf */
477 int32_t sent = prepare_symbol_ex(direction,
497 tx_bytes_counter += rte_pktmbuf_pkt_len(mb);
498 p_x_ctx->send_upmbuf2ring(mb, ETHER_TYPE_ECPRI);
504 printf("Symbol %2d sent (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
510 int send_cpmsg(void *pHandle, struct rte_mbuf *mbuf,struct xran_cp_gen_params *params,
511 struct xran_section_gen_info *sect_geninfo, uint8_t cc_id, uint8_t ru_port_id, uint8_t seq_id)
513 int ret = 0, nsection, i;
514 uint8_t frame_id = params->hdr.frameId;
515 uint8_t subframe_id = params->hdr.subframeId;
516 uint8_t slot_id = params->hdr.slotId;
517 uint8_t dir = params->dir;
518 struct xran_device_ctx *p_x_ctx = xran_dev_get_ctx();
520 nsection = params->numSections;
522 /* add in the ethernet header */
523 struct ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
525 tx_bytes_counter += rte_pktmbuf_pkt_len(mbuf);
526 p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI);
527 for(i=0; i<nsection; i++)
528 xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id,
529 (slot_id + subframe_id*SLOTNUM_PER_SUBFRAME)%XRAN_MAX_SECTIONDB_CTX,
530 §_geninfo[i].info);
535 int generate_cpmsg_dlul(void *pHandle, struct xran_cp_gen_params *params, struct xran_section_gen_info *sect_geninfo, struct rte_mbuf *mbuf,
536 enum xran_pkt_dir dir, uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
537 uint8_t startsym, uint8_t numsym, uint16_t prb_start, uint16_t prb_num,int16_t iq_buffer_offset, int16_t iq_buffer_len,
538 uint16_t beam_id, uint8_t cc_id, uint8_t ru_port_id, uint8_t comp_method, uint8_t iqWidth, uint8_t seq_id, uint8_t symInc)
540 int ret = 0, nsection, i, loc_sym;
544 params->sectionType = XRAN_CP_SECTIONTYPE_1; // Most DL/UL Radio Channels
545 params->hdr.filterIdx = XRAN_FILTERINDEX_STANDARD;
546 params->hdr.frameId = frame_id;
547 params->hdr.subframeId = subframe_id;
548 params->hdr.slotId = slot_id;
549 params->hdr.startSymId = startsym; // start Symbol ID
550 params->hdr.iqWidth = iqWidth;
551 params->hdr.compMeth = comp_method;
554 sect_geninfo[nsection].info.type = params->sectionType; // for database
555 sect_geninfo[nsection].info.startSymId = params->hdr.startSymId; // for database
556 sect_geninfo[nsection].info.iqWidth = params->hdr.iqWidth; // for database
557 sect_geninfo[nsection].info.compMeth = params->hdr.compMeth; // for database
558 sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id);
559 sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY;
560 sect_geninfo[nsection].info.symInc = symInc;
561 sect_geninfo[nsection].info.startPrbc = prb_start;
562 sect_geninfo[nsection].info.numPrbc = prb_num;
563 sect_geninfo[nsection].info.numSymbol = numsym;
564 sect_geninfo[nsection].info.reMask = 0xfff;
565 sect_geninfo[nsection].info.beamId = beam_id;
567 for (loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) {
568 sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_offset = iq_buffer_offset;
569 sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_len = iq_buffer_len;
572 sect_geninfo[nsection].info.ef = 0;
573 sect_geninfo[nsection].exDataSize = 0;
574 // sect_geninfo[nsection].exData = NULL;
577 params->numSections = nsection;
578 params->sections = sect_geninfo;
580 if(unlikely(mbuf == NULL)) {
581 print_err("Alloc fail!\n");
585 ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, ru_port_id, seq_id);
587 print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
588 frame_id, subframe_id, slot_id, dir);
589 rte_pktmbuf_free(mbuf);
595 int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struct xran_section_gen_info *sect_geninfo, struct rte_mbuf *mbuf, struct xran_device_ctx *pxran_lib_ctx,
596 uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
597 uint16_t beam_id, uint8_t cc_id, uint8_t prach_port_id, uint8_t seq_id)
599 int i, nsection, ret;
600 struct xran_prach_cp_config *pPrachCPConfig = &(pxran_lib_ctx->PrachCPConfig);
602 uint16_t nNumerology = pxran_lib_ctx->fh_cfg.frame_conf.nNumerology;
604 if(unlikely(mbuf == NULL)) {
605 print_err("Alloc fail!\n");
609 printf("%d:%d:%d:%d - filter=%d, startSym=%d[%d:%d], numSym=%d, occasions=%d, freqOff=%d\n",
610 frame_id, subframe_id, slot_id, prach_port_id,
611 pPrachCPConfig->filterIdx,
612 pPrachCPConfig->startSymId,
613 pPrachCPConfig->startPrbc,
614 pPrachCPConfig->numPrbc,
615 pPrachCPConfig->numSymbol,
616 pPrachCPConfig->occassionsInPrachSlot,
617 pPrachCPConfig->freqOffset);
619 timeOffset = pPrachCPConfig->timeOffset; //this is the CP value per 38.211 tab 6.3.3.1-1&2
620 timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu
621 if (pPrachCPConfig->startSymId > 0)
623 timeOffset += (pPrachCPConfig->startSymId * 2048) >> nNumerology;
624 if ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME >> 1)))
627 params->dir = XRAN_DIR_UL;
628 params->sectionType = XRAN_CP_SECTIONTYPE_3;
629 params->hdr.filterIdx = pPrachCPConfig->filterIdx;
630 params->hdr.frameId = frame_id;
631 params->hdr.subframeId = subframe_id;
632 params->hdr.slotId = slot_id;
633 params->hdr.startSymId = pPrachCPConfig->startSymId;
634 params->hdr.iqWidth = xran_get_conf_iqwidth(pHandle);
635 params->hdr.compMeth = xran_get_conf_compmethod(pHandle);
636 /* use timeOffset field for the CP length value for prach sequence */
637 params->hdr.timeOffset = timeOffset;
638 params->hdr.fftSize = xran_get_conf_fftsize(pHandle);
639 params->hdr.scs = xran_get_conf_prach_scs(pHandle);
640 params->hdr.cpLength = 0;
643 sect_geninfo[nsection].info.type = params->sectionType; // for database
644 sect_geninfo[nsection].info.startSymId = params->hdr.startSymId; // for database
645 sect_geninfo[nsection].info.iqWidth = params->hdr.iqWidth; // for database
646 sect_geninfo[nsection].info.compMeth = params->hdr.compMeth; // for database
647 sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);
648 sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY;
649 sect_geninfo[nsection].info.symInc = XRAN_SYMBOLNUMBER_NOTINC;
650 sect_geninfo[nsection].info.startPrbc = pPrachCPConfig->startPrbc;
651 sect_geninfo[nsection].info.numPrbc = pPrachCPConfig->numPrbc,
652 sect_geninfo[nsection].info.numSymbol = pPrachCPConfig->numSymbol*pPrachCPConfig->occassionsInPrachSlot;
653 sect_geninfo[nsection].info.reMask = 0xfff;
654 sect_geninfo[nsection].info.beamId = beam_id;
655 sect_geninfo[nsection].info.freqOffset = pPrachCPConfig->freqOffset;
657 pxran_lib_ctx->prach_last_symbol[cc_id] = sect_geninfo[nsection].info.startSymId + sect_geninfo[nsection].info.numSymbol - 1;
659 sect_geninfo[nsection].info.ef = 0;
660 sect_geninfo[nsection].exDataSize = 0;
661 // sect_geninfo[nsection].exData = NULL;
664 params->numSections = nsection;
665 params->sections = sect_geninfo;
667 ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, prach_port_id, seq_id);
669 print_err("Fail to build prach control packet - [%d:%d:%d]\n", frame_id, subframe_id, slot_id);
670 rte_pktmbuf_free(mbuf);
676 int process_ring(struct rte_ring *r)
680 struct rte_mbuf *mbufs[MBUFS_CNT];
684 const uint16_t dequeued = rte_ring_dequeue_burst(r, (void **)mbufs,
685 RTE_DIM(mbufs), &remaining);
691 for (i = 0; i < dequeued; ++i) {
692 if (xran_ethdi_filter_packet(mbufs[i], 0) == MBUF_FREE)
693 rte_pktmbuf_free(mbufs[i]);
695 MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick());
700 int32_t ring_processing_func(void)
702 struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
703 struct xran_device_ctx *const pxran_lib_ctx = xran_dev_get_ctx();
710 if (process_ring(ctx->rx_ring[ETHDI_UP_VF]))
713 if (process_ring(ctx->rx_ring[ETHDI_CP_VF]))
716 if (pxran_lib_ctx->bbdev_dec) {
718 retPoll = pxran_lib_ctx->bbdev_dec();
722 MLogTask(PID_XRAN_BBDEV_UL_POLL + retPoll, t1, t2);
726 if (pxran_lib_ctx->bbdev_enc) {
728 retPoll = pxran_lib_ctx->bbdev_enc();
732 MLogTask(PID_XRAN_BBDEV_DL_POLL + retPoll, t1, t2);
736 if (XRAN_STOPPED == xran_if_current_state)
742 int ring_processing_thread(void *args)
744 struct sched_param sched_param;
747 printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid());
748 sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;
749 if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param))){
750 printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);
754 if(ring_processing_func() != 0)
757 puts("Pkt processing thread finished.");