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 lls-CU and 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,
82 extern int32_t xran_pkt_validate(void *arg,
83 struct rte_mbuf *mbuf,
92 struct ecpri_seq_id *seq_id,
102 int process_mbuf(struct rte_mbuf *pkt)
105 struct ecpri_seq_id seq;
106 static int symbol_total_bytes = 0;
108 struct xran_device_ctx * p_x_ctx = xran_dev_get_ctx();
112 uint8_t frame_id = 0;
113 uint8_t subframe_id = 0;
122 void *pHandle = NULL;
123 uint8_t num_eAxc = xran_get_num_eAxc(pHandle);
125 uint32_t mb_free = 0;
126 int32_t valid_res = 0;
129 if(p_x_ctx->xran2phy_mem_ready == 0)
132 num_bytes = xran_extract_iq_samples(pkt,
148 print_err("num_bytes is wrong [%d]\n", num_bytes);
152 valid_res = xran_pkt_validate(NULL,
170 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);
174 if (Ant_ID >= num_eAxc && p_x_ctx->fh_init.prachEnable) // PRACH packet has ruportid = num_eAxc + ant_id
177 if (seq.e_bit == 1) {
179 print_dbg("Completed receiving PRACH symbol %d, size=%d bytes\n",
182 xran_process_prach_sym(NULL,
199 print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
202 symbol_total_bytes += num_bytes;
204 if (seq.e_bit == 1) {
205 print_dbg("Completed receiving symbol %d, size=%d bytes\n",
206 symb_id, symbol_total_bytes);
208 if (symbol_total_bytes){
209 int res = xran_process_rx_sym(NULL,
225 if(res == symbol_total_bytes)
228 print_err("res != symbol_total_bytes\n");
230 symbol_total_bytes = 0;
233 print_dbg("Transport layer fragmentation (eCPRI) is not supported\n");
240 static int set_iq_bit_width(uint8_t iq_bit_width, struct data_section_compression_hdr *compr_hdr)
242 if (iq_bit_width == MAX_IQ_BIT_WIDTH)
243 compr_hdr->ud_comp_hdr.ud_iq_width = (uint8_t) 0;
245 compr_hdr->ud_comp_hdr.ud_iq_width = iq_bit_width;
251 /* Send a single 5G symbol over multiple packets */
252 int32_t prepare_symbol_ex(enum xran_pkt_dir direction,
256 const enum xran_input_byte_order iq_buf_byte_order,
268 int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
272 int16_t nPktSize = sizeof(struct ether_hdr) + sizeof(struct xran_ecpri_hdr) +
273 sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes;
275 struct xran_up_pkt_gen_no_compression_params xp = { 0 };
277 n_bytes = RTE_MIN(n_bytes, XRAN_MAX_MBUF_LEN);
279 /* radio app header */
280 xp.app_params.data_direction = direction;
281 xp.app_params.payl_ver = 1;
282 xp.app_params.filter_id = 0;
283 xp.app_params.frame_id = frame_id;
284 xp.app_params.sf_slot_sym.subframe_id = subframe_id;
285 xp.app_params.sf_slot_sym.slot_id = slot_id;
286 xp.app_params.sf_slot_sym.symb_id = symbol_no;
288 /* convert to network byte order */
289 xp.app_params.sf_slot_sym.value = rte_cpu_to_be_16(xp.app_params.sf_slot_sym.value);
291 xp.sec_hdr.fields.sect_id = section_id;
292 xp.sec_hdr.fields.num_prbu = (uint8_t)prb_num;
293 xp.sec_hdr.fields.start_prbu = (uint8_t)prb_start;
294 xp.sec_hdr.fields.sym_inc = 0;
295 xp.sec_hdr.fields.rb = 0;
297 /* network byte order */
298 xp.sec_hdr.fields.all_bits = rte_cpu_to_be_32(xp.sec_hdr.fields.all_bits);
302 errx(1, "out of mbufs after %d packets", 1);
305 prep_bytes = xran_prepare_iq_symbol_portion_no_comp(mb,
315 errx(1, "failed preparing symbol");
317 rte_pktmbuf_pkt_len(mb) = nPktSize;
318 rte_pktmbuf_data_len(mb) = nPktSize;
321 printf("Symbol %2d prep_bytes (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
327 /* Send a single 5G symbol over multiple packets */
328 int send_symbol_ex(enum xran_pkt_dir direction,
332 const enum xran_input_byte_order iq_buf_byte_order,
343 uint32_t do_copy = 0;
344 int32_t n_bytes = ((prb_num == 0) ? MAX_N_FULLBAND_SC : prb_num) * N_SC_PER_PRB * sizeof(struct rb_map);
348 mb = xran_ethdi_mbuf_alloc(); /* will be freede by ETH */
351 errx(1, "out of mbufs after %d packets", 1);
353 pChar = rte_pktmbuf_append(mb, sizeof(struct xran_ecpri_hdr)+ sizeof(struct radio_app_common_hdr)+ sizeof(struct data_section_hdr) + n_bytes);
356 errx(1, "incorrect mbuf size %d packets", 1);
358 pChar = rte_pktmbuf_prepend(mb, sizeof(struct ether_hdr));
361 errx(1, "incorrect mbuf size %d packets", 1);
363 do_copy = 1; /* new mbuf hence copy of IQs */
365 rte_pktmbuf_refcnt_update(mb, 1); /* make sure eth won't free our mbuf */
368 int32_t sent = prepare_symbol_ex(direction,
386 xran_ethdi_mbuf_send(mb, ETHER_TYPE_ECPRI);
394 printf("Symbol %2d sent (%d packets, %d bytes)\n", symbol_no, i, n_bytes);
400 int send_cpmsg(void *pHandle, struct rte_mbuf *mbuf,struct xran_cp_gen_params *params,
401 struct xran_section_gen_info *sect_geninfo, uint8_t cc_id, uint8_t ru_port_id, uint8_t seq_id)
403 int ret = 0, nsection, i;
404 uint8_t frame_id = params->hdr.frameId;
405 uint8_t subframe_id = params->hdr.subframeId;
406 uint8_t slot_id = params->hdr.slotId;
407 uint8_t dir = params->dir;
409 nsection = params->numSections;
411 /* add in the ethernet header */
412 struct ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
413 xran_ethdi_mbuf_send_cp(mbuf, ETHER_TYPE_ECPRI);
415 for(i=0; i<nsection; i++)
416 xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id,
417 (slot_id + subframe_id*SLOTNUM_PER_SUBFRAME)%XRAN_MAX_SECTIONDB_CTX,
418 §_geninfo[i].info);
423 int generate_cpmsg_dlul(void *pHandle, struct xran_cp_gen_params *params, struct xran_section_gen_info *sect_geninfo, struct rte_mbuf *mbuf,
424 enum xran_pkt_dir dir, uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
425 uint8_t startsym, uint8_t numsym, uint16_t prb_start, uint16_t prb_num,
426 uint16_t beam_id, uint8_t cc_id, uint8_t ru_port_id, uint8_t comp_method, uint8_t seq_id, uint8_t symInc)
428 int ret = 0, nsection, i;
432 params->sectionType = XRAN_CP_SECTIONTYPE_1; // Most DL/UL Radio Channels
433 params->hdr.filterIdx = XRAN_FILTERINDEX_STANDARD;
434 params->hdr.frameId = frame_id;
435 params->hdr.subframeId = subframe_id;
436 params->hdr.slotId = slot_id;
437 params->hdr.startSymId = startsym; // start Symbol ID
438 params->hdr.iqWidth = xran_get_conf_iqwidth(pHandle);
439 params->hdr.compMeth = comp_method;
442 sect_geninfo[nsection].info.type = params->sectionType; // for database
443 sect_geninfo[nsection].info.startSymId = params->hdr.startSymId; // for database
444 sect_geninfo[nsection].info.iqWidth = params->hdr.iqWidth; // for database
445 sect_geninfo[nsection].info.compMeth = params->hdr.compMeth; // for database
446 sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id);
447 sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY;
448 sect_geninfo[nsection].info.symInc = symInc;
449 sect_geninfo[nsection].info.startPrbc = prb_start;
450 sect_geninfo[nsection].info.numPrbc = prb_num;
451 sect_geninfo[nsection].info.numSymbol = numsym;
452 sect_geninfo[nsection].info.reMask = 0xfff;
453 sect_geninfo[nsection].info.beamId = beam_id;
455 sect_geninfo[nsection].info.ef = 0;
456 sect_geninfo[nsection].exDataSize = 0;
457 // sect_geninfo[nsection].exData = NULL;
460 params->numSections = nsection;
461 params->sections = sect_geninfo;
463 if(unlikely(mbuf == NULL)) {
464 print_err("Alloc fail!\n");
468 ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, ru_port_id, seq_id);
470 print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
471 frame_id, subframe_id, slot_id, dir);
472 rte_pktmbuf_free(mbuf);
478 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,
479 uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id,
480 uint16_t beam_id, uint8_t cc_id, uint8_t prach_port_id, uint8_t seq_id)
482 int i, nsection, ret;
483 xRANPrachCPConfigStruct *pPrachCPConfig = &(pxran_lib_ctx->PrachCPConfig);
485 uint16_t nNumerology = pxran_lib_ctx->fh_cfg.frame_conf.nNumerology;
487 if(unlikely(mbuf == NULL)) {
488 print_err("Alloc fail!\n");
492 printf("%d:%d:%d:%d - filter=%d, startSym=%d[%d:%d], numSym=%d, occasions=%d, freqOff=%d\n",
493 frame_id, subframe_id, slot_id, prach_port_id,
494 pPrachCPConfig->filterIdx,
495 pPrachCPConfig->startSymId,
496 pPrachCPConfig->startPrbc,
497 pPrachCPConfig->numPrbc,
498 pPrachCPConfig->numSymbol,
499 pPrachCPConfig->occassionsInPrachSlot,
500 pPrachCPConfig->freqOffset);
502 timeOffset = pPrachCPConfig->timeOffset; //this is the CP value per 38.211 tab 6.3.3.1-1&2
503 timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu
504 if (pPrachCPConfig->startSymId > 0)
506 timeOffset += (pPrachCPConfig->startSymId * 2048) >> nNumerology;
507 if ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME >> 1)))
510 params->dir = XRAN_DIR_UL;
511 params->sectionType = XRAN_CP_SECTIONTYPE_3;
512 params->hdr.filterIdx = pPrachCPConfig->filterIdx;
513 params->hdr.frameId = frame_id;
514 params->hdr.subframeId = subframe_id;
515 params->hdr.slotId = slot_id;
516 params->hdr.startSymId = pPrachCPConfig->startSymId;
517 params->hdr.iqWidth = xran_get_conf_iqwidth(pHandle);
518 params->hdr.compMeth = xran_get_conf_compmethod(pHandle);
519 /* use timeOffset field for the CP length value for prach sequence */
520 params->hdr.timeOffset = timeOffset;
521 params->hdr.fftSize = xran_get_conf_fftsize(pHandle);
522 params->hdr.scs = xran_get_conf_prach_scs(pHandle);
523 params->hdr.cpLength = 0;
526 sect_geninfo[nsection].info.type = params->sectionType; // for database
527 sect_geninfo[nsection].info.startSymId = params->hdr.startSymId; // for database
528 sect_geninfo[nsection].info.iqWidth = params->hdr.iqWidth; // for database
529 sect_geninfo[nsection].info.compMeth = params->hdr.compMeth; // for database
530 sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id);
531 sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY;
532 sect_geninfo[nsection].info.symInc = XRAN_SYMBOLNUMBER_NOTINC;
533 sect_geninfo[nsection].info.startPrbc = pPrachCPConfig->startPrbc;
534 sect_geninfo[nsection].info.numPrbc = pPrachCPConfig->numPrbc,
535 sect_geninfo[nsection].info.numSymbol = pPrachCPConfig->numSymbol*pPrachCPConfig->occassionsInPrachSlot;
536 sect_geninfo[nsection].info.reMask = 0xfff;
537 sect_geninfo[nsection].info.beamId = beam_id;
538 sect_geninfo[nsection].info.freqOffset = pPrachCPConfig->freqOffset;
540 pxran_lib_ctx->prach_last_symbol[cc_id] = sect_geninfo[nsection].info.startSymId + sect_geninfo[nsection].info.numSymbol - 1;
542 sect_geninfo[nsection].info.ef = 0;
543 sect_geninfo[nsection].exDataSize = 0;
544 // sect_geninfo[nsection].exData = NULL;
547 params->numSections = nsection;
548 params->sections = sect_geninfo;
550 ret = xran_prepare_ctrl_pkt(mbuf, params, cc_id, prach_port_id, seq_id);
552 print_err("Fail to build prach control packet - [%d:%d:%d]\n", frame_id, subframe_id, slot_id);
553 rte_pktmbuf_free(mbuf);
559 int process_ring(struct rte_ring *r)
563 struct rte_mbuf *mbufs[MBUFS_CNT];
567 const uint16_t dequeued = rte_ring_dequeue_burst(r, (void **)mbufs,
568 RTE_DIM(mbufs), &remaining);
574 for (i = 0; i < dequeued; ++i) {
575 if (xran_ethdi_filter_packet(mbufs[i], 0) == MBUF_FREE)
576 rte_pktmbuf_free(mbufs[i]);
578 MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick());
583 int32_t ring_processing_func(void)
585 struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
586 struct xran_device_ctx *const pxran_lib_ctx = xran_dev_get_ctx();
591 if (process_ring(ctx->rx_ring[ETHDI_UP_VF]))
594 if (process_ring(ctx->rx_ring[ETHDI_CP_VF]))
597 if (pxran_lib_ctx->bbdev_dec)
598 pxran_lib_ctx->bbdev_dec();
600 if (pxran_lib_ctx->bbdev_enc)
601 pxran_lib_ctx->bbdev_enc();
603 if (XRAN_STOPPED == xran_if_current_state)
609 int ring_processing_thread(void *args)
611 struct sched_param sched_param;
614 printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid());
615 sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO;
616 if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param))){
617 printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res);
621 if(ring_processing_func() != 0)
624 puts("Pkt processing thread finished.");