From: Luis Farias Date: Thu, 25 Jul 2019 21:51:42 +0000 (-0700) Subject: Front Haul Interface Library first seed code contribution X-Git-Tag: ORAN-seedcode_v1.1 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=commitdiff_plain;h=4745e5c88ba931c6d71cb6d8c681f76cf364eac5 Front Haul Interface Library first seed code contribution This first version supports only mmWave per 5G NR and it is not yet optimized and it is a first draft prior to the November 2019 Release A The following mandatory features of the ORAN FH interface are not yet supported in this initial release: 1) RU Category: Support of CAT-B RU (i.e. precoding in RU) 2) Beamforming: Beam Index Based and Real Time BF weights 3) Transport Features: QoS over FrontHaul and Application Fragmentation Additional Information available in the readme.txt file xran root refers to the o-du/phy/fhi_lib folder Issue-Id: ODUPHY-1 Change-Id: I9c801f99bfbc3911514c4e7ff51ea7c52c5666c5 Signed-off-by: luis farias --- diff --git a/fhi_lib/Licenses.txt b/fhi_lib/Licenses.txt new file mode 100644 index 0000000..6aee987 --- /dev/null +++ b/fhi_lib/Licenses.txt @@ -0,0 +1,31 @@ +Copyright (c) 2019 Intel. + +Unless otherwise specified, all software contained herein is licensed +under the Apache License, Version 2.0 (the "Software License"); +you may not use this software except in compliance with the Software +License. You may obtain a copy of the Software License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the Software License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the Software License for the specific language governing permissions +and limitations under the Software License. + + + +Unless otherwise specified, all documentation contained herein is licensed +under the Creative Commons License, Attribution 4.0 Intl. (the +"Documentation License"); you may not use this documentation except in +compliance with the Documentation License. You may obtain a copy of the +Documentation License at + +https://creativecommons.org/licenses/by/4.0/ + +Unless required by applicable law or agreed to in writing, documentation +distributed under the Documentation License is distributed on an "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the Documentation License for the specific language governing +permissions and limitations under the Documentation License. + diff --git a/fhi_lib/app/Makefile b/fhi_lib/app/Makefile new file mode 100644 index 0000000..ebad9b9 --- /dev/null +++ b/fhi_lib/app/Makefile @@ -0,0 +1,28 @@ +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ + +PHONY: all + +all: + cd lls-cu && make #DEBUG=1 + cd ru && make #DEBUG=1 + +clean: + cd lls-cu && make clean #DEBUG=1 + cd ru && make clean #DEBUG=1 + diff --git a/fhi_lib/app/ant_0.bin b/fhi_lib/app/ant_0.bin new file mode 100644 index 0000000..4d9fb4b Binary files /dev/null and b/fhi_lib/app/ant_0.bin differ diff --git a/fhi_lib/app/ant_1.bin b/fhi_lib/app/ant_1.bin new file mode 100644 index 0000000..6cb4fe7 Binary files /dev/null and b/fhi_lib/app/ant_1.bin differ diff --git a/fhi_lib/app/ant_2.bin b/fhi_lib/app/ant_2.bin new file mode 100644 index 0000000..d761f95 Binary files /dev/null and b/fhi_lib/app/ant_2.bin differ diff --git a/fhi_lib/app/ant_3.bin b/fhi_lib/app/ant_3.bin new file mode 100644 index 0000000..6962e60 Binary files /dev/null and b/fhi_lib/app/ant_3.bin differ diff --git a/fhi_lib/app/common/common.c b/fhi_lib/app/common/common.c new file mode 100644 index 0000000..818914e --- /dev/null +++ b/fhi_lib/app/common/common.c @@ -0,0 +1,202 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +#ifndef _XRAN_APP_COMMON_ +#define _XRAN_APP_COMMON_ + +#include +#include +#include +#include +#include + +#include "../common/common.h" +#include "xran_pkt.h" +#include "xran_pkt_up.h" +#include "xran_cp_api.h" +#include "xran_up_api.h" +#include "../src/xran_printf.h" + + +#define MBUFS_CNT 256 + +extern enum app_state state; + +uint8_t numCCPorts = 1; +/* Number of antennas supported by front-end */ + +uint8_t num_eAxc = 4; +/* Number of CPRI ports supported by front-end */ + +int16_t *p_tx_play_buffer[MAX_ANT_CARRIER_SUPPORTED]; +int32_t tx_play_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +int32_t tx_play_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +int16_t *p_rx_log_buffer[MAX_ANT_CARRIER_SUPPORTED]; +int32_t rx_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +int32_t rx_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +int16_t *p_prach_log_buffer[MAX_ANT_CARRIER_SUPPORTED]; +int32_t prach_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +int32_t prach_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +int16_t *p_tx_buffer[MAX_ANT_CARRIER_SUPPORTED]; +int32_t tx_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; + +int16_t *p_rx_buffer[MAX_ANT_CARRIER_SUPPORTED]; +int32_t rx_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; + +void sys_save_buf_to_file(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num) +{ + if (size) + { + if (filename && bufname) + { + FILE *file; + printf("Storing %s to file %s: ", bufname, filename); + file = fopen(filename, "wb"); + if (file == NULL) + { + print_err("can't open file %s!!!", filename); + } + else + { + uint32_t num; + num = fwrite(pBuffer, buffers_num, size, file); + fflush(file); + fclose(file); + printf("from addr (0x%lx) size (%d) bytes num (%d)", (uint64_t)pBuffer, size, num); + } + printf(" \n"); + } + else + { + print_err(" the file name, buffer name are not set!!!"); + } + } + else + { + print_err(" the %s is free: size = %d bytes!!!", bufname, size); + } +} + +int sys_load_file_to_buff(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num) +{ + unsigned int file_size = 0; + int num= 0; + + if (size) + { + if (filename && bufname) + { + FILE *file; + printf("Loading file %s to %s: ", filename, bufname); + file = fopen(filename, "rb"); + + + if (file == NULL) + { + print_err("can't open file %s!!!", filename); + exit(-1); + } + else + { + fseek(file, 0, SEEK_END); + file_size = ftell(file); + fseek(file, 0, SEEK_SET); + + if ((file_size > size) || (file_size == 0)) + file_size = size; + + printf("Reading IQ samples from file: File Size: %d [Buffer Size: %d]\n", file_size, size); + + num = fread(pBuffer, buffers_num, size, file); + fflush(file); + fclose(file); + printf("from addr (0x%lx) size (%d) bytes num (%d)", (uint64_t)pBuffer, file_size, num); + } + printf(" \n"); + + } + else + { + print_err(" the file name, buffer name are not set!!!"); + } + } + else + { + print_err(" the %s is free: size = %d bytes!!!", bufname, size); + } + return num; +} + + +void sys_save_buf_to_file_txt(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num) +{ + unsigned int i; + int ret = 0; + if (pBuffer == NULL) + return; + + if (size) + { + if (filename && bufname) + { + FILE *file; + printf("Storing %s to file %s: ", bufname, filename); + file = fopen(filename, "w"); + if (file == NULL) + { + print_err("can't open file %s!!!", filename); + exit(-1); + } + else + { + uint32_t num = 0; + + signed short *ptr = (signed short*)pBuffer; + for (i = 0; i < (size/((unsigned int)sizeof(signed short) /** 2 * 2 * 2*/)); i = i + 2) + { + ret = fprintf(file,"%d %d\n", ptr[i], ptr[i + 1]); + if (ret < 0) + { + printf("fprintf %d\n", ret); + fclose(file); + break; + } + num++; + } + fflush(file); + fclose(file); + printf("from addr (0x%lx) size (%d) IQ num (%d)", (uint64_t)pBuffer, size, num); + } + printf(" \n"); + } + else + { + print_err(" the file name, buffer name are not set!!!"); + } + } + else + { + print_err(" the %s is free: size = %d bytes!!!", bufname, size); + } +} + + +#endif /* _XRAN_APP_COMMON_ */ diff --git a/fhi_lib/app/common/common.h b/fhi_lib/app/common/common.h new file mode 100644 index 0000000..fb4400d --- /dev/null +++ b/fhi_lib/app/common/common.h @@ -0,0 +1,99 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +#include +#include + +#include "xran_pkt_up.h" + +#include +#include + +#define APP_LLS_CU 0 +#define APP_RU 1 + +enum app_state +{ + APP_RUNNING, + APP_STOPPED +}; + +#define NUM_OF_PRB_IN_FULL_BAND (66) +#define N_SC_PER_PRB 12 +#define N_SYM_PER_SLOT 14 +#define N_FULLBAND_SC (NUM_OF_PRB_IN_FULL_BAND*N_SC_PER_PRB) +#define MAX_ANT_CARRIER_SUPPORTED 16 +// 0.125, just for testing +#define SLOTNUM_PER_SUBFRAME 8 +#define SUBFRAMES_PER_SYSTEMFRAME 10 +#define PDSCH_PAYLOAD_SIZE (N_FULLBAND_SC*4) +#define NUM_OF_SLOT_IN_TDD_LOOP (80) +#define IQ_PLAYBACK_BUFFER_BYTES (NUM_OF_SLOT_IN_TDD_LOOP*N_SYM_PER_SLOT*N_FULLBAND_SC*4L) +/* PRACH data samples are 32 bits wide, 16bits for I and 16bits for Q. Each packet contains 839 samples. The payload length is 3356 octets.*/ +#define PRACH_PLAYBACK_BUFFER_BYTES (10*839*4L) + +#ifdef _DEBUG +#define iAssert(p) if(!(p)){fprintf(stderr,\ + "Assertion failed: %s, file %s, line %d, val %d\n",\ + #p, __FILE__, __LINE__, p);exit(-1);} +#else /* _DEBUG */ +#define iAssert(p) +#endif /* _DEBUG */ + +struct send_symbol_cb_args +{ + struct rb_map *samp_buf; + uint8_t *symb_id; +}; + +struct pkt_dump +{ + int num_samp; + int num_bytes; + uint8_t symb; + struct ecpri_seq_id seq; +} __rte_packed; + +extern uint8_t numCCPorts; +/* Number of antennas supported by front-end */ + +extern uint8_t num_eAxc; +/* Number of antennas supported by front-end */ +extern int16_t *p_tx_play_buffer[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t tx_play_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t tx_play_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +/* Number of antennas supported by front-end */ +extern int16_t *p_rx_log_buffer[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t rx_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t rx_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +extern int16_t *p_prach_log_buffer[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t prach_log_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t prach_log_buffer_position[MAX_ANT_CARRIER_SUPPORTED]; + +extern int16_t *p_tx_buffer[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t tx_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; + +extern int16_t *p_rx_buffer[MAX_ANT_CARRIER_SUPPORTED]; +extern int32_t rx_buffer_size[MAX_ANT_CARRIER_SUPPORTED]; + +void sys_save_buf_to_file_txt(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num); +void sys_save_buf_to_file(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num); +int sys_load_file_to_buff(char *filename, char *bufname, unsigned char *pBuffer, unsigned int size, unsigned int buffers_num); + diff --git a/fhi_lib/app/config_file_lls_cu.dat b/fhi_lib/app/config_file_lls_cu.dat new file mode 100644 index 0000000..7a17943 --- /dev/null +++ b/fhi_lib/app/config_file_lls_cu.dat @@ -0,0 +1,92 @@ +####################################################################### +# +# +# +####################################################################### + +# This is simple configuration file. Use '#' sign for comments +appMode=0 # lls-CU(0) | RU(1) +xranMode=0 # Category A (0) (precoder in lls-CU) | Category B (1) (precoder in RU) +ccNum=1 # Number of Componnent Carriers (CC) per ETH port with XRAN protocol (default:1 max: 4) +##Numerology +mu=3 #mmWave 120Khz Sub Carrier Spacing +antNum=4 # Number of Antennas per CC (default: 4) +ttiPeriod=125 # in us TTI period (mmWave default 125us) +llsCUMac=00:11:22:33:44:66 # asigned MAC of lls-CU VF +ruMac=00:11:22:33:44:55 #RU VF for RU app +#ruMac=3c:fd:fe:b1:d8:98 #RU PF for tcpdump +#56:1e:4b:0c:f5:9b # RU MAC +antC0=./ant_0.bin #CC0 +antC1=./ant_1.bin #CC0 +antC2=./ant_2.bin #CC0 +antC3=./ant_3.bin #CC0 +antC4=./ant_4.bin #CC1 +antC5=./ant_5.bin #CC1 +antC6=./ant_6.bin #CC1 +antC7=./ant_7.bin #CC1 +antC8=./ant_8.bin #CC2 +antC9=./ant_9.bin #CC2 +antC10=./ant_10.bin #CC2 +antC11=./ant_11.bin #CC2 +antC12=./ant_12.bin #CC3 +antC13=./ant_13.bin #CC3 +antC14=./ant_14.bin #CC3 +antC15=./ant_15.bin #CC3 + +## RACH TODO: update for PRACH +#rachEanble=1 # Enable (1)| disable (0) PRACH configuration +#rachOffset=43 # RB offset for prach detection (see RIU spec) +#rachCfgIdx=14 # PRACH config index as per TS36.211 - Table 5.7.1-2 : PRACH Configuration Index + +## control of IQ byte order +iqswap=0 #do swap of IQ before send buffer to eth +nebyteorderswap=0 #do swap of byte order for each I and Q from CPU byte order to network byte order + +##Debug +debugStop=0 #stop app on 1pps boundary (gps_second % 30) + +CPenable=1 #(1) C-Plane is enabled| (0) C-Plane is disabled +c_plane_vlan_tag=1 #VLAN Tag used for C-Plane +u_plane_vlan_tag=2 #VLAN Tag used for U-Plane + +##RU Settings +Tadv_cp_dl=25 #in us TODO: update per RU implementation + #C-Plane messages must arrive at the RU some amount of time in advance (Tcp_adv_dl) of the corresponding U-Plane messages + +#Reception Window C-plane DL +T2a_min_cp_dl=50 #in us TODO: update per RU implementation +T2a_max_cp_dl=140 #in us TODO: update per RU implementation + +#Reception Window C-plane UL +T2a_min_cp_ul=50 #in us TODO: update per RU implementation +T2a_max_cp_ul=140 #in us TODO: update per RU implementation + +#Reception Window U-plane +T2a_min_up=25 #in us +T2a_max_up=140 #in us + +#Transmission Window +Ta3_min=20 #in us +Ta3_max=32 #in us + +########################################################### +##lls-CU Settings +#C-plane +#Transmission Window Fast C-plane DL +T1a_min_cp_dl=70 +T1a_max_cp_dl=100 + +##Transmission Window Fast C-plane UL +T1a_min_cp_ul=70 +T1a_max_cp_ul=80 + +#U-plane +##Transmission Window +T1a_min_up=35 +T1a_max_up=50 + +#Reception Window +Ta4_min=0 +Ta4_max=45 +########################################################### + diff --git a/fhi_lib/app/config_file_ru.dat b/fhi_lib/app/config_file_ru.dat new file mode 100644 index 0000000..d1edf90 --- /dev/null +++ b/fhi_lib/app/config_file_ru.dat @@ -0,0 +1,92 @@ +####################################################################### +# +# +# +####################################################################### + +# This is simple configuration file. Use '#' sign for comments +appMode=1 # lls-CU(0) | RU(1) +xranMode=0 # Category A (0) (precoder in lls-CU) | Category B (1) (precoder in RU) +ccNum=1 # Number of Componnent Carriers (CC) per ETH port with XRAN protocol (default:1 max: 4) +##Numerology +mu=3 #mmWave 120Khz Sub Carrier Spacing +antNum=4 # Number of Antennas per CC (default: 4) +ttiPeriod=125 # in us TTI period (mmWave default 125us) +llsCUMac=00:11:22:33:44:66 # asigned MAC of lls-CU VF +#llsCUMac=3c:fd:fe:9e:93:68 # PF for tcpdump +ruMac=00:11:22:33:44:55 +#56:1e:4b:0c:f5:9b # RU MAC +antC0=./ant_0.bin #CC0 +antC1=./ant_1.bin #CC0 +antC2=./ant_2.bin #CC0 +antC3=./ant_3.bin #CC0 +antC4=./ant_4.bin #CC1 +antC5=./ant_5.bin #CC1 +antC6=./ant_6.bin #CC1 +antC7=./ant_7.bin #CC1 +antC8=./ant_8.bin #CC2 +antC9=./ant_9.bin #CC2 +antC10=./ant_10.bin #CC2 +antC11=./ant_11.bin #CC2 +antC12=./ant_12.bin #CC3 +antC13=./ant_13.bin #CC3 +antC14=./ant_14.bin #CC3 +antC15=./ant_15.bin #CC3 + +## RACH TODO: update for PRACH +#rachEanble=1 # Enable (1)| disable (0) PRACH configuration +#rachOffset=43 # RB offset for prach detection (see RIU spec) +#rachCfgIdx=14 # PRACH config index as per TS36.211 - Table 5.7.1-2 : PRACH Configuration Index + +## control of IQ byte order +iqswap=0 #do swap of IQ before send buffer to eth +nebyteorderswap=0 #do swap of byte order for each I and Q from CPU byte order to network byte order + +##Debug +debugStop=0 #stop app on 1pps boundary (gps_second % 30) + +CPenable=0 #(1) C-Plane is enabled| 0 C-Plane is disabled +c_plane_vlan_tag=1 #VLAN Tag used for C-Plane +u_plane_vlan_tag=2 #VLAN Tag used for U-Plane + +##RU Settings +Tadv_cp_dl=25 #in us TODO: update per RU implementation + #C-Plane messages must arrive at the RU some amount of time in advance (Tcp_adv_dl) of the corresponding U-Plane messages + +#Reception Window C-plane DL +T2a_min_cp_dl=50 #in us TODO: update per RU implementation +T2a_max_cp_dl=140 #in us TODO: update per RU implementation + +#Reception Window C-plane UL +T2a_min_cp_ul=50 #in us TODO: update per RU implementation +T2a_max_cp_ul=140 #in us TODO: update per RU implementation + +#Reception Window U-plane +T2a_min_up=25 #in us +T2a_max_up=140 #in us + +#Transmission Window +Ta3_min=20 #in us +Ta3_max=32 #in us + +########################################################### +##lls-CU Settings +#C-plane +#Transmission Window Fast C-plane DL +T1a_min_cp_dl=70 +T1a_max_cp_dl=100 + +##Transmission Window Fast C-plane UL +T1a_min_cp_ul=70 +T1a_max_cp_ul=80 + +#U-plane +##Transmission Window +T1a_min_up=35 +T1a_max_up=50 + +#Reception Window +Ta4_min=10 +Ta4_max=100 +########################################################### + diff --git a/fhi_lib/app/dpdk.sh b/fhi_lib/app/dpdk.sh new file mode 100644 index 0000000..96bb84f --- /dev/null +++ b/fhi_lib/app/dpdk.sh @@ -0,0 +1,97 @@ +#! /bin/bash + +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ + +export RTE_SDK=/home/turner/dpdk +export RTE_TARGET=x86_64-native-linuxapp-icc + +# +# Unloads igb_uio.ko. +# +remove_igb_uio_module() +{ + echo "Unloading any existing DPDK UIO module" + /sbin/lsmod | grep -s igb_uio > /dev/null + if [ $? -eq 0 ] ; then + sudo /sbin/rmmod igb_uio + fi +} + +# +# Loads new igb_uio.ko (and uio module if needed). +# +load_igb_uio_module() +{ + if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko ];then + echo "## ERROR: Target does not have the DPDK UIO Kernel Module." + echo " To fix, please try to rebuild target." + return + fi + + remove_igb_uio_module + + /sbin/lsmod | grep -s uio > /dev/null + if [ $? -ne 0 ] ; then + if [ -f /lib/modules/$(uname -r)/kernel/drivers/uio/uio.ko ] ; then + echo "Loading uio module" + sudo /sbin/modprobe uio + fi + fi + + # UIO may be compiled into kernel, so it may not be an error if it can't + # be loaded. + + echo "Loading DPDK UIO module" + sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko + if [ $? -ne 0 ] ; then + echo "## ERROR: Could not load kmod/igb_uio.ko." + quit + fi +} + +load_igb_uio_module + +CPU_FEATURES_DETECT=`cat /proc/cpuinfo |grep hypervisor | wc -l` + +if [ "$CPU_FEATURES_DETECT" -eq "0" ] +then +VM_DETECT='HOST' +echo ${VM_DETECT} +else +VM_DETECT='VM' +echo ${VM_DETECT} +fi + +$RTE_SDK/usertools/dpdk-devbind.py --status +if [ ${VM_DETECT} == 'HOST' ]; then + #HOST + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:d8:02.0 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:d8:02.1 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:07:02.0 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:07:02.1 +else + #VM + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:00:04.0 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:00:05.0 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:00:06.0 + $RTE_SDK/usertools/dpdk-devbind.py --bind=igb_uio 0000:00:07.0 +fi + +$RTE_SDK/usertools/dpdk-devbind.py --status + diff --git a/fhi_lib/app/gen_test.m b/fhi_lib/app/gen_test.m new file mode 100644 index 0000000..b93736c --- /dev/null +++ b/fhi_lib/app/gen_test.m @@ -0,0 +1,130 @@ +%/****************************************************************************** +%* +%* Copyright (c) 2019 Intel. +%* +%* Licensed under the Apache License, Version 2.0 (the "License"); +%* you may not use this file except in compliance with the License. +%* You may obtain a copy of the License at +%* +%* http://www.apache.org/licenses/LICENSE-2.0 +%* +%* Unless required by applicable law or agreed to in writing, software +%* distributed under the License is distributed on an "AS IS" BASIS, +%* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%* See the License for the specific language governing permissions and +%* limitations under the License. +%* +%*******************************************************************************/ + +%Matlab: read bin +%fileID_c = fopen('ant_7.bin','r'); +%ant7_c= fread(fileID_c, [2, 792*14*80], 'integer*2'); +%ant7_c; +%ant7_c=ant7_c.'; + +close all; +clear all; + +ifft_in = load('ifft_in.txt') +ant_c = ifft_in; +for (i=1:1:80*14-1) + ant_c = [ant_c; ifft_in]; +end + +ant0=ant_c; +ant1=ant_c*10; +ant2=ant_c*20; +ant3=ant_c*30; +ant4=ant_c*40; +ant5=ant_c*50; +ant6=ant_c*60; +ant7=ant_c*70; +ant8=ant_c*80; +ant9=ant_c*90; +ant10=ant_c*100; +ant11=ant_c*110; +ant12=ant_c*120; +ant13=ant_c*130; +ant14=ant_c*140; +ant15=ant_c*150; + + +ant0_16=int16(ant0.'); +fileID = fopen('ant_0.bin','w'); +fwrite(fileID,ant0_16, 'int16'); +fclose(fileID); + +ant1_16=int16(ant1.'); +fileID = fopen('ant_1.bin','w'); +fwrite(fileID,ant1_16, 'int16'); +fclose(fileID); + +ant2_16=int16(ant2.'); +fileID = fopen('ant_2.bin','w'); +fwrite(fileID,ant2_16, 'int16'); +fclose(fileID); + +ant3_16=int16(ant3.'); +fileID = fopen('ant_3.bin','w'); +fwrite(fileID,ant3_16, 'int16'); +fclose(fileID); + +ant4_16=int16(ant4.'); +fileID = fopen('ant_4.bin','w'); +fwrite(fileID,ant4_16, 'int16'); +fclose(fileID); + +ant5_16=int16(ant5.'); +fileID = fopen('ant_5.bin','w'); +fwrite(fileID,ant5_16, 'int16'); +fclose(fileID); + +ant6_16=int16(ant6.'); +fileID = fopen('ant_6.bin','w'); +fwrite(fileID,ant6_16, 'int16'); +fclose(fileID); + +ant7_16=int16(ant7.'); +fileID = fopen('ant_7.bin','w'); +fwrite(fileID,ant7_16, 'int16'); +fclose(fileID); + +ant8_16=int16(ant8.'); +fileID = fopen('ant_8.bin','w'); +fwrite(fileID,ant8_16, 'int16'); +fclose(fileID); + +ant9_16=int16(ant9.'); +fileID = fopen('ant_9.bin','w'); +fwrite(fileID,ant9_16, 'int16'); +fclose(fileID); + +ant10_16=int16(ant10.'); +fileID = fopen('ant_10.bin','w'); +fwrite(fileID,ant10_16, 'int16'); +fclose(fileID); + +ant11_16=int16(ant11.'); +fileID = fopen('ant_11.bin','w'); +fwrite(fileID,ant11_16, 'int16'); +fclose(fileID); + +ant12_16=int16(ant12.'); +fileID = fopen('ant_12.bin','w'); +fwrite(fileID,ant12_16, 'int16'); +fclose(fileID); + +ant13_16=int16(ant13.'); +fileID = fopen('ant_13.bin','w'); +fwrite(fileID,ant13_16, 'int16'); +fclose(fileID); + +ant14_16=int16(ant14.'); +fileID = fopen('ant_14.bin','w'); +fwrite(fileID,ant14_16, 'int16'); +fclose(fileID); + +ant15_16=int16(ant15.'); +fileID = fopen('ant_15.bin','w'); +fwrite(fileID,ant15_16, 'int16'); +fclose(fileID); diff --git a/fhi_lib/app/lls-cu/Makefile b/fhi_lib/app/lls-cu/Makefile new file mode 100644 index 0000000..86aa9cc --- /dev/null +++ b/fhi_lib/app/lls-cu/Makefile @@ -0,0 +1,90 @@ +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ +CC := icc + +ifeq ($(RTE_SDK),) + $(error "Please define RTE_SDK environment variable") +endif + +RTE_TARGET := x86_64-native-linuxapp-icc +RTE_INC := $(RTE_SDK)/$(RTE_TARGET)/include +#include $(RTE_SDK)/mk/rte.vars.mk + +ifeq ($(XRAN_DIR),) + XRAN_DIR=$(PWD)/../.. +endif + +COMMON_SRC=$(XRAN_DIR)/app/common +SRC_SRC=$(XRAN_DIR)/app/src + +ifeq ($(MLOG_DIR),) + MLOG_DIR=$(XRAN_DIR)/../mlog +endif + +APP = sample-lls-cu +SRC = $(COMMON_SRC)/common.c \ + ./sample-lls-cu.c \ + $(SRC_SRC)/config.c + +CFLAGS += -std=gnu11 -Wall -wd9 -Wextra -Werror -I$(XRAN_DIR)/lib/api -I$(COMMON_SRC) -I$(SRC_SRC) -I$(MLOG_DIR)/source -I$(RTE_INC) +ifeq ($(ME),1) + CFLAGS += -DMLOG_ENABLED +endif +ifeq ($(NB),1) + CFLAGS += -DNightly_build +endif + +ifeq ($(DEBUG),1) + CFLAGS += -DDEBUG -O0 -g +else + CFLAGS += -O3 +endif + +ifeq ($(MULTI_SECTION),1) + CFLAGS += -DMULTI_SECTION +endif + +LDFLAGS += -pthread -lrt + +RTE_LIBS = -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,-lrte_flow_classify -Wl,--whole-archive -Wl,-lrte_pipeline -Wl,--no-whole-archive -Wl,--whole-archive -Wl,-lrte_table -Wl,--no-whole-archive -Wl,--whole-archive -Wl,-lrte_port -Wl,--no-whole-archive -Wl,-lrte_pdump -Wl,-lrte_distributor -Wl,-lrte_ip_frag -Wl,-lrte_meter -Wl,-lrte_lpm -Wl,--whole-archive -Wl,-lrte_acl -Wl,--no-whole-archive -Wl,-lrte_jobstats -Wl,-lrte_metrics -Wl,-lrte_bitratestats -Wl,-lrte_latencystats -Wl,-lrte_power -Wl,-lrte_efd -Wl,-lrte_bpf -Wl,--whole-archive -Wl,-lrte_cfgfile -Wl,-lrte_gro -Wl,-lrte_gso -Wl,-lrte_hash -Wl,-lrte_member -Wl,-lrte_vhost -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_net -Wl,-lrte_ethdev -Wl,-lrte_bbdev -Wl,-lrte_cryptodev -Wl,-lrte_security -Wl,-lrte_compressdev -Wl,-lrte_eventdev -Wl,-lrte_rawdev -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_reorder -Wl,-lrte_sched -Wl,-lrte_kni -Wl,-lrte_common_octeontx -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_bus_dpaa -Wl,-lrte_bus_fslmc -Wl,-lrte_mempool_bucket -Wl,-lrte_mempool_stack -Wl,-lrte_mempool_dpaa -Wl,-lrte_mempool_dpaa2 -Wl,-lrte_pmd_af_packet -Wl,-lrte_pmd_ark -Wl,-lrte_pmd_avf -Wl,-lrte_pmd_avp -Wl,-lrte_pmd_axgbe -Wl,-lrte_pmd_bnxt -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_cxgbe -Wl,-lrte_pmd_dpaa -Wl,-lrte_pmd_dpaa2 -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ena -Wl,-lrte_pmd_enic -Wl,-lrte_pmd_fm10k -Wl,-lrte_pmd_failsafe -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_kni -Wl,-lrte_pmd_lio -Wl,-lrte_pmd_nfp -Wl,-lrte_pmd_null -Wl,-lrte_pmd_qede -Wl,-lrte_pmd_ring -Wl,-lrte_pmd_softnic -Wl,-lrte_pmd_tap -Wl,-lrte_pmd_thunderx_nicvf -Wl,-lrte_pmd_vdev_netvsc -Wl,-lrte_pmd_virtio -Wl,-lrte_pmd_vhost -Wl,-lrte_pmd_ifc -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_bus_vmbus -Wl,-lrte_pmd_netvsc -Wl,-lrte_pmd_bbdev_null -Wl,-lrte_pmd_null_crypto -Wl,-lrte_pmd_crypto_scheduler -Wl,-lrte_pmd_dpaa2_sec -Wl,-lrte_pmd_dpaa_sec -Wl,-lrte_pmd_virtio_crypto -Wl,-lrte_pmd_octeontx_zip -Wl,-lrte_pmd_qat -Wl,-lrte_pmd_skeleton_event -Wl,-lrte_pmd_sw_event -Wl,-lrte_pmd_octeontx_ssovf -Wl,-lrte_pmd_dpaa_event -Wl,-lrte_pmd_dpaa2_event -Wl,-lrte_mempool_octeontx -Wl,-lrte_pmd_octeontx -Wl,-lrte_pmd_opdl_event -Wl,-lrte_pmd_skeleton_rawdev -Wl,-lrte_pmd_dpaa2_cmdif -Wl,-lrte_pmd_dpaa2_qdma -Wl,-lrte_bus_ifpga -Wl,-lrte_pmd_ifpga_rawdev -Wl,--no-whole-archive -Wl,-lrt -Wl,-lm -Wl,-lnuma -Wl,-ldl -Wl, + +XRAN_LIB_DIR=$(XRAN_DIR)/lib/bin +LDFLAGS += -L$(XRAN_LIB_DIR) -Wl, -lxran -Wl, -L$(MLOG_DIR)/bin -Wl, $(RTE_LIBS) +ifeq ($(ME),1) + LDFLAGS += -Wl,-lmlog +endif + +OBJ = $(foreach file,$(SRC),$(file:.c=.o)) + + +all: $(APP) install + +$(OBJ): %.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(APP): $(OBJ) + $(CC) -o $(APP) $(CFLAGS) $(OBJ) $(LDFLAGS) + +install: $(APP) + @mkdir -p bin + @cp $(APP) ./bin + +clean: + @rm -rf $(APP) $(OBJ) ./bin/$(APP) + +#include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/fhi_lib/app/lls-cu/sample-lls-cu.c b/fhi_lib/app/lls-cu/sample-lls-cu.c new file mode 100644 index 0000000..31ffb4b --- /dev/null +++ b/fhi_lib/app/lls-cu/sample-lls-cu.c @@ -0,0 +1,1165 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "config.h" + +#ifndef MLOG_ENABLED +#include "../../lib/src/mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif + + +#include "xran_fh_lls_cu.h" +//#include "xran_pkt.h" +//#include "xran_up_api.h" +#include "xran_cp_api.h" +#include "xran_sync_api.h" +#include "xran_mlog_task_id.h" + +#define SW_FPGA_TOTAL_BUFFER_LEN 4*1024*1024*1024 +#define SW_FPGA_SEGMENT_BUFFER_LEN 1*1024*1024*1024 +#define SW_FPGA_FH_TOTAL_BUFFER_LEN 1*1024*1024*1024 +#define FPGA_TO_SW_PRACH_RX_BUFFER_LEN (8192) + +#define NSEC_PER_SEC 1000000000 + +#define MAX_PKT_BURST (448+4) // 4x14x8 +#define N_MAX_BUFFER_SEGMENT MAX_PKT_BURST + +#define MAIN_PRIORITY 98 +#define NUM_OF_SUBFRAME_PER_FRAME (10) + +enum app_state state; + +uint64_t tick_per_usec; +static volatile uint64_t timer_last_irq_tick = 0; +static uint64_t tsc_resolution_hz = 0; + +RuntimeConfig startupConfiguration = {0}; + +//FH FPGA buffer +uint32_t nFpgaToSW_FTH_RxBufferLen; +uint32_t nFpgaToSW_PRACH_RxBufferLen; +uint32_t nSW_ToFpga_FTH_TxBufferLen; + +static XRANFHINIT xranInit; +void * xranHandle = NULL; + +XRANFHCONFIG xranConf; +PXRANFHCONFIG pXranConf = NULL; + +typedef struct +{ + uint32_t phaseFlag :1; + uint32_t NRARFCN :22; + uint32_t SULFreShift :1; + uint32_t SULFlag :1; + uint32_t rsv :7; +}FPGAPhaseCompCfg; + +typedef struct XranLibConfig +{ + uint32_t nDriverCoreId; + uint32_t nTimingAdvance; + uint32_t nFhConfig; + uint32_t nFhBufIntFlag; + uint32_t nSectorNum; + uint32_t nNrOfSlotInSf; + uint32_t nNrofSfInFrame; + void * pFthInstanceHandles; +}XranLibConfigStruct; +typedef enum { + XRANFTHTX_OUT = 0, + XRANFTHRX_IN, + XRANFTHRACH_IN, + MAX_SW_XRAN_INTERFACE_NUM +}SWXRANInterfaceTypeEnum; + +/* + * manage one cell's all Ethernet frames for one DL or UL LTE subframe + */ +typedef struct { + /* -1-this subframe is not used in current frame format + 0-this subframe can be transmitted, i.e., data is ready + 1-this subframe is waiting transmission, i.e., data is not ready + 10 - DL transmission missing deadline. When FE needs this subframe data but bValid is still 1, + set bValid to 10. + */ + int32_t bValid ; // when UL rx, it is subframe index. + int32_t nSegToBeGen; + int32_t nSegGenerated; // how many date segment are generated by DL LTE processing or received from FE + // -1 means that DL packet to be transmitted is not ready in BS + int32_t nSegTransferred; // number of data segments has been transmitted or received + struct rte_mbuf *pData[N_MAX_BUFFER_SEGMENT]; // point to DPDK allocated memory pool + XRANBufferListStruct sBufferList; +} BbuIoBufCtrlStruct; + +typedef struct { + uint64_t nCoreMask; + int16_t cpuSocketId; + uint8_t nDriverCoreId; + uint8_t nFHCoreId; + + struct rte_mempool *bbuio_buf_pool; + + /* io struct */ + BbuIoBufCtrlStruct sFrontHaulTxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + BbuIoBufCtrlStruct sFrontHaulRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + BbuIoBufCtrlStruct sFHPrachRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + + /* buffers lists */ + XRANFlatBufferStruct sFrontHaulTxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + XRANFlatBufferStruct sFrontHaulRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + XRANFlatBufferStruct sFHPrachRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + + void* nInstanceHandle[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; // instance per sector + uint32_t nBufPoolIndex[XRAN_MAX_SECTOR_NR][MAX_SW_XRAN_INTERFACE_NUM]; // every api owns unique buffer pool + uint16_t nInstanceNum; + + /*subframe type for this TTI: + 0: DL control + DL data + 1: DL control + DL data + UL control + 2: DL control + UL data + 3: DL control + UL data + UL control + */ + uint8_t nSubframeType; + + uint64_t nTscTiming[XRAN_N_FE_BUF_LEN]; // records the TSC when a timing packet is received. +} BbuXranIoIfStruct; + +static BbuXranIoIfStruct gsXranIoIf; +static XranLibConfigStruct *gpXranLibConfig = NULL; + +#define CPU_HZ tick_per_usec //us + +/* Application User space functions */ +void xran_fh_rx_callback(void *pCallbackTag, int32_t status); +void xran_fh_rx_prach_callback(void *pCallbackTag, int32_t status); + +static BbuXranIoIfStruct *xran_get_ctx(void) +{ + return &gsXranIoIf; +} + +static void print_menu() +{ + puts("+---------------------------------------+"); + puts("| Press 1 to start 5G NR XRAN traffic |"); + puts("| Press 2 reserved for future use |"); + puts("| Press 3 to quit |"); + puts("+---------------------------------------+"); +} + +void xran_fh_rx_callback(void *pCallbackTag, XranStatusInt32 status) +{ + uint64_t t1 = MLogTick(); + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + + mlogVar[mlogVarCnt++] = 0xCCCCCCCC; + mlogVar[mlogVarCnt++] = status >> 16; /* tti */ + mlogVar[mlogVarCnt++] = status & 0xFF; /* sym */ + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + rte_pause(); + + MLogTask(PID_GNB_SYM_CB, t1, MLogTick()); + return; +} + +void xran_fh_rx_prach_callback(void *pCallbackTag, XranStatusInt32 status) +{ + uint64_t t1 = MLogTick(); + rte_pause(); + MLogTask(PID_GNB_PRACH_CB, t1, MLogTick()); +} + +//------------------------------------------------------------------------------------------- +/** @ingroup group_nbiot_source_auxlib_timer + * + * @param void + * + * @return Ticks + * + * @description + * This function reads the rtdsc clock and returns the current value in there. + * +**/ +//------------------------------------------------------------------------------------------- +unsigned long timer_get_ticks(void) +{ + unsigned long ret; + union + { + unsigned long tsc_64; + struct + { + uint32_t lo_32; + uint32_t hi_32; + }; + } tsc; + + __asm volatile("rdtsc" : + "=a" (tsc.lo_32), + "=d" (tsc.hi_32)); + + ret = ((unsigned long)tsc.tsc_64); + return ret; +} + +//------------------------------------------------------------------------------------------- +/** @ingroup group_lte_source_auxlib_timer + * + * @param void + * + * @return 0 if SUCCESS + * + * @description + * This function gets the clock speed of the core and figures out number of ticks per usec. + * It is used by l1app and testmac applications to initialize the mlog utility + * +**/ +//------------------------------------------------------------------------------------------- +int timer_set_tsc_freq_from_clock(void) +{ +#define NS_PER_SEC 1E9 + struct timespec sleeptime = {.tv_nsec = 5E8 }; /* 1/2 second */ + struct timespec t_start, t_end; + uint64_t tsc_resolution_hz = 0; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0) + { + unsigned long ns, end, start = timer_get_ticks(); + nanosleep(&sleeptime,NULL); + clock_gettime(CLOCK_MONOTONIC_RAW, &t_end); + end = timer_get_ticks(); + ns = ((t_end.tv_sec - t_start.tv_sec) * NS_PER_SEC); + ns += (t_end.tv_nsec - t_start.tv_nsec); + + double secs = (double)ns/NS_PER_SEC; + tsc_resolution_hz = (unsigned long)((end - start)/secs); + + tick_per_usec = (tsc_resolution_hz / 1000000); + printf("System clock (rdtsc) resolution %lu [Hz]\n", tsc_resolution_hz); + printf("Ticks per us %lu\n", tick_per_usec); + return 0; + } + + return -1; +} + +int physide_dl_tti_call_back(void * param) +{ + uint64_t t1 = MLogTick(); + rte_pause(); + MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick()); + return 0; +} + +int physide_ul_half_slot_call_back(void * param) +{ + uint64_t t1 = MLogTick(); + rte_pause(); + MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick()); + return 0; +} + +int physide_ul_full_slot_call_back(void * param) +{ + uint64_t t1 = MLogTick(); + rte_pause(); + MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick()); + return 0; +} + +int32_t init_xran(void) +{ + BbuXranIoIfStruct *psBbuIo = xran_get_ctx(); + XranStatusInt32 status; + int32_t nSectorIndex[XRAN_MAX_SECTOR_NR]; + int32_t nSectorNum; + int32_t i, j, k, z; + + void *ptr; + uint32_t *u32dptr; + uint16_t *u16dptr; + uint8_t *u8dptr; + + SWXRANInterfaceTypeEnum eInterfaceType; + + XranLibConfigStruct *ptrLibConfig; + + XRANBufferListStruct *pFthTxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; + XRANBufferListStruct *pFthRxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; + XRANBufferListStruct *pFthRxRachBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; + + FPGAPhaseCompCfg *pPhaseCompDl = NULL; + FPGAPhaseCompCfg *pPhaseCompUl = NULL; + uint32_t nPhaseCompDl,nPhaseCompUl; + + +#if 0 + printf("init_xran: nFpgaProbe[%d] nSecNum[%d] nUENum[%d] nTimeAdvance[%d] nEthPorts[%d] nPhaseCompFlag[%d]\n", + psFPGAInitPara->nFpgaProbe, psFPGAInitPara->nSecNum, psFPGAInitPara->nUENum, psFPGAInitPara->nTimeAdvance, psFPGAInitPara->nEthPorts, psFPGAInitPara->nPhaseCompFlag); + for (i = 0; i < nSectorNum; i ++) + { + printf(" [%d]: nDlArfcn[%d] nUlArfcn[%d]\n", i, psFPGAInitPara->nDlArfcn[i], psFPGAInitPara->nUlArfcn[i]); + } +#endif + for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++) + { + nSectorIndex[nSectorNum] = nSectorNum; + } + + nSectorNum = numCCPorts; + printf ("XRAN front haul xran_mm_init \n"); + status = xran_mm_init (xranHandle, (uint64_t) SW_FPGA_FH_TOTAL_BUFFER_LEN, SW_FPGA_SEGMENT_BUFFER_LEN); + if (status != XRAN_STATUS_SUCCESS) + { + printf ("Failed at XRAN front haul xran_mm_init \n"); + exit(-1); + } + + psBbuIo->nInstanceNum = numCCPorts; + + for (k = 0; k < XRAN_PORTS_NUM; k++) { + status = xran_sector_get_instances (xranHandle, psBbuIo->nInstanceNum,psBbuIo->nInstanceHandle[k]); + if (status != XRAN_STATUS_SUCCESS) + { + printf ("get sector instance failed %d for XRAN nInstanceNum %d\n",k, psBbuIo->nInstanceNum); + exit(-1); + } + } + + printf("Sucess xran_mm_init \n"); + gpXranLibConfig = (XranLibConfigStruct*)malloc(sizeof(XranLibConfigStruct)); + ptrLibConfig = gpXranLibConfig; + if (ptrLibConfig) + { + #if 0 + ptrLibConfig->nDriverCoreId = psBbuIo->nDriverCoreId; + ptrLibConfig->pFecInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FEC][0]); + ptrLibConfig->pFthInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FRONTHAUL][0]); + ptrLibConfig->nTimingAdvance = psFPGAInitPara->nTimeAdvance; + ptrLibConfig->nFhConfig = psFPGAInitPara->nEthPorts; + ptrLibConfig->nFhBufIntFlag = 0; //need init fronthaul buffer, then set to 1. + ptrLibConfig->nNrofSfInFrame = NUM_OF_SUBFRAME_PER_FRAME; + ptrLibConfig->nNrOfSlotInSf = pConfigParams->nNumOfSlotPerSubframe; + if (pConfigParams->nNumerology < 3) + { + ptrLibConfig->nSectorNum = psFPGAInitPara->nSecNum; + } + #endif + } + else + { + printf ("could not allocate ptrLibConfig in init_xran\n"); + exit(-1); + } + + printf("nSectorNum %d\n", nSectorNum); + + /* Init Memory */ + for(i = 0; inBufPoolIndex[nSectorIndex[i]][eInterfaceType], + XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_bm_init , status %d\n", status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + for(j = 0; j < XRAN_N_FE_BUF_LEN; j++) + { + for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){ + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulTxBuffers[j][i][z][0]; + + for(k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; k++) + { + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nSW_ToFpga_FTH_TxBufferLen; // 14 symbols 3200bytes/symbol + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1; + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0; + status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_bm_allocate_buffer , status %d\n",status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr; + + if(ptr){ + u32dptr = (uint32_t*)(ptr); + uint8_t *ptr_temp = (uint8_t *)ptr; + memset(u32dptr, 0xCC, nSW_ToFpga_FTH_TxBufferLen); + ptr_temp[0] = j; // TTI + ptr_temp[1] = i; // Sec + ptr_temp[2] = z; // Ant + ptr_temp[3] = k; // sym + } + } + } + } + } + + for(i = 0; inBufPoolIndex[nSectorIndex[i]][eInterfaceType], XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_bm_init, status %d\n", status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + + for(j = 0;j < XRAN_N_FE_BUF_LEN; j++) + { + for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){ + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulRxBuffers[j][i][z][0]; + for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++) + { + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nFpgaToSW_FTH_RxBufferLen; // 1 symbols 3200bytes + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1; + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0; + status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at cpa_bb_bm_allocate_buffer , status %d\n",status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr; + if(ptr){ + u32dptr = (uint32_t*)(ptr); + uint8_t *ptr_temp = (uint8_t *)ptr; + memset(u32dptr, 0xCC, nFpgaToSW_FTH_RxBufferLen); + ptr_temp[0] = j; // TTI + ptr_temp[1] = i; // Sec + ptr_temp[2] = z; // Ant + ptr_temp[3] = k; // sym + } + } + } + } + } + + // add prach rx buffer + for(i = 0; inBufPoolIndex[nSectorIndex[i]][eInterfaceType],XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, FPGA_TO_SW_PRACH_RX_BUFFER_LEN); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_bm_init, status %d\n", status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + for(j = 0;j < XRAN_N_FE_BUF_LEN; j++) + { + for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){ + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number. + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFHPrachRxBuffers[j][i][z][0]; + //for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++) + k = 0; // one PRACH buffer per antenna per slot + { + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = FPGA_TO_SW_PRACH_RX_BUFFER_LEN; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1; + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0; + status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr); + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_bm_allocate_buffer, status %d\n",status); + iAssert(status == XRAN_STATUS_SUCCESS); + } + psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr; + if(ptr){ + u32dptr = (uint32_t*)(ptr); + memset(u32dptr, 0xCC, FPGA_TO_SW_PRACH_RX_BUFFER_LEN); + } + } + } + } + } + + for(i=0; isFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList); + pFthRxBuffer[i][z][j] = &(psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList); + pFthRxRachBuffer[i][z][j] = &(psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList); + } + } + } + + if(NULL != psBbuIo->nInstanceHandle[0]) + { + for (i = 0; inInstanceHandle[0][i], + pFthTxBuffer[i], + pFthRxBuffer[i], + xran_fh_rx_callback, &pFthRxBuffer[i][0]); + } + + // add prach callback here + for (i = 0; inInstanceHandle[0][i], pFthRxRachBuffer[i], + xran_fh_rx_prach_callback,&pFthRxRachBuffer[i][0]); + } + ptrLibConfig->nFhBufIntFlag = 1; + } + + /*config phase compensation*/ + /* TODO: add phase compensation handling */ + for(i=0; iNRARFCN = 0;//psFPGAInitPara->nDlArfcn[i]; + pPhaseCompDl->phaseFlag = 0;//psFPGAInitPara->nPhaseCompFlag; + pPhaseCompDl->SULFlag = 0; + pPhaseCompDl->SULFreShift = 0; + pPhaseCompDl->rsv = 0; + + pPhaseCompUl = (FPGAPhaseCompCfg *)(&nPhaseCompUl); + pPhaseCompUl->NRARFCN = 0;//psFPGAInitPara->nUlArfcn[i]; + pPhaseCompUl->phaseFlag = 0;// psFPGAInitPara->nPhaseCompFlag; + pPhaseCompUl->SULFlag = 0; + pPhaseCompUl->SULFreShift = 0; + pPhaseCompUl->rsv = 0; + + xran_5g_pre_compenstor_cfg(psBbuIo->nInstanceHandle[0][i],nPhaseCompDl,nPhaseCompUl,i); + + printf("@@@ NB cell %d DL NR-ARFCN %d,DL phase comp flag %d UL NR-ARFCN %d,UL phase comp flag %d \n", + i,pPhaseCompDl->NRARFCN,pPhaseCompDl->phaseFlag, + pPhaseCompUl->NRARFCN,pPhaseCompUl->phaseFlag); + } + return status; +} + +int init_xran_iq_content(void) +{ + BbuXranIoIfStruct *psBbuIo = xran_get_ctx(); + XranStatusInt32 status; + int32_t nSectorIndex[XRAN_MAX_SECTOR_NR]; + int32_t nSectorNum; + int32_t cc_id, ant_id, sym_id, tti; + int32_t flowId; + + uint8_t frame_id = 0; + uint8_t subframe_id = 0; + uint8_t slot_id = 0; + uint8_t sym = 0; + + void *ptr; + uint32_t *u32dptr; + uint16_t *u16dptr; + uint8_t *u8dptr; + + char *pos = NULL; + + for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++) + { + nSectorIndex[nSectorNum] = nSectorNum; + } + nSectorNum = numCCPorts; + printf ("init_xran_iq_content\n"); + + /* Init Memory */ + for(cc_id = 0; cc_id sFrontHaulTxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData; + + if(ptr){ + u32dptr = (uint32_t*)(ptr); + rte_memcpy(u32dptr, pos, PDSCH_PAYLOAD_SIZE); +#ifdef DEBUG_XRAN_BUFFERS + uint8_t *ptr_temp = (uint8_t *)ptr; + ptr_temp[0] = tti; // TTI + ptr_temp[1] = cc_id; // Sec + ptr_temp[2] = ant_id; // Ant + ptr_temp[3] = sym_id; // sym +#endif + }else + printf("ptr ==NULL\n"); + + tx_play_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE; + + if(tx_play_buffer_position[flowId] >= tx_play_buffer_size[flowId]) + tx_play_buffer_position[flowId] = 0; + } else { + //printf("flowId %d\n", flowId); + } + } + } + } + + } + + return 0; +} + +void stop_xran(void) +{ + XranStatusInt32 status = 0; + SWXRANInterfaceTypeEnum eInterfaceType; + + free(gpXranLibConfig); + gpXranLibConfig = NULL; + + status += xran_mm_destroy(xranHandle)*2; + + if(XRAN_STATUS_SUCCESS != status) + { + printf("Failed at xran_mm_destroy, status %d\n",status); + iAssert(status == XRAN_STATUS_SUCCESS); + } +} + +int32_t get_xran_sfidx(uint8_t nNrOfSlotInSf) +{ + int32_t nSfIdx = -1; + uint32_t nFrameIdx; + uint32_t nSubframeIdx; + uint32_t nSlotIdx; + uint64_t nSecond; + + uint32_t nXranTime = xran_get_slot_idx(&nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond); + nSfIdx = nFrameIdx*NUM_OF_SUBFRAME_PER_FRAME*nNrOfSlotInSf + + nSubframeIdx*nNrOfSlotInSf + + nSlotIdx; +#if 0 + printf("\nxranTime is %d, return is %d, radio frame is %d, subframe is %d slot is %d tsc is %llu us", + nXranTime, + nSfIdx, + nFrameIdx, + nSubframeIdx, + nSlotIdx, + __rdtsc()/CPU_HZ); +#endif + + return nSfIdx; +} + +int get_xran_iq_content(void) +{ + BbuXranIoIfStruct *psBbuIo = xran_get_ctx(); + XranStatusInt32 status; + int32_t nSectorIndex[XRAN_MAX_SECTOR_NR]; + int32_t nSectorNum; + int32_t cc_id, ant_id, sym_id, tti; + int32_t flowId; + + uint8_t frame_id = 0; + uint8_t subframe_id = 0; + uint8_t slot_id = 0; + uint8_t sym = 0; + + void *ptr; + uint32_t *u32dptr; + uint16_t *u16dptr; + uint8_t *u8dptr; + + char *pos = NULL; + + for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++) + { + nSectorIndex[nSectorNum] = nSectorNum; + } + nSectorNum = numCCPorts; + printf ("get_xran_iq_content\n"); + + /* Init Memory */ + for(cc_id = 0; cc_id sFrontHaulRxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData; + if(ptr){ + u32dptr = (uint32_t*)(ptr); + rte_memcpy(pos, u32dptr, PDSCH_PAYLOAD_SIZE); +#ifdef DEBUG_XRAN_BUFFERS + if (pos[0] != tti|| + pos[1] != cc_id || + pos[2] != ant_id || + pos[3] != sym_id){ + printf("[flowId %d] %d %d %d %d\n", flowId, pos[0], pos[1], pos[2], pos[3]); + } +#endif + }else + printf("ptr ==NULL\n"); + + rx_log_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE; + + if(rx_log_buffer_position[flowId] >= rx_log_buffer_size[flowId]) + rx_log_buffer_position[flowId] = 0; + } else { + //printf("flowId %d\n", flowId); + } + } + } + } + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + int j; + int lcore_id = 0; + char filename[64]; + + if (argc == 3) + errx(2, "Need two argument - the PCI address of the network port"); + + if (xran_is_synchronized() != 0) + printf("Machine is not synchronized using PTP!\n"); + else + printf("Machine is synchronized using PTP!\n"); + + memset(&startupConfiguration, 0, sizeof(RuntimeConfig)); + + if (parseConfigFile(argv[1], &startupConfiguration) != 0) { + printf("Configuration file error.\n"); + return 0; + } + + if(startupConfiguration.ant_file[0] == NULL){ + printf("it looks like test vector for antennas were not provided\n"); + exit(-1); + } + + numCCPorts = startupConfiguration.numCC; + num_eAxc = startupConfiguration.numAxc; + + printf("numCCPorts %d num_eAxc%d\n", numCCPorts, num_eAxc); + + /* Numerology 3 */ + nFpgaToSW_FTH_RxBufferLen = 3328; //3200 * 14; + nFpgaToSW_PRACH_RxBufferLen = 8192; + nSW_ToFpga_FTH_TxBufferLen = 3328; //3200; * 14; + + memset(&xranInit, 0, sizeof(XRANFHINIT)); + + if(startupConfiguration.appMode == APP_LLS_CU) { + printf("set lls-CU\n"); + xranInit.io_cfg.id = 0;//ID_LLS_CU; + xranInit.io_cfg.core = 4+1; + xranInit.io_cfg.system_core = 0; + xranInit.io_cfg.pkt_proc_core = 4+2; + xranInit.io_cfg.pkt_aux_core = 0; /* do not start*/ + xranInit.io_cfg.timing_core = 4+3; + } else { + printf("set RU\n"); + xranInit.io_cfg.id = 1; /* ID_LLS_CU;*/ + xranInit.io_cfg.core = 1; + xranInit.io_cfg.system_core = 0; + xranInit.io_cfg.pkt_proc_core = 2; + xranInit.io_cfg.pkt_aux_core = 0; /* do not start */ + xranInit.io_cfg.timing_core = 3; + } + + xranInit.llscuId = 0; // for ecpriRtcid/ecpriPcid + xranInit.nSec = 1; // shall be one + + xranInit.eAxCId_conf.mask_cuPortId = 0xf000; + xranInit.eAxCId_conf.mask_bandSectorId = 0x0f00; + xranInit.eAxCId_conf.mask_ccId = 0x00f0; + xranInit.eAxCId_conf.mask_ruPortId = 0x000f; + xranInit.eAxCId_conf.bit_cuPortId = 12; + xranInit.eAxCId_conf.bit_bandSectorId = 8; + xranInit.eAxCId_conf.bit_ccId = 4; + xranInit.eAxCId_conf.bit_ruPortId = 0; + + xranInit.io_cfg.dpdk_dev[XRAN_UP_VF] = argv[2]; + xranInit.io_cfg.dpdk_dev[XRAN_CP_VF] = argv[3]; + xranInit.p_lls_cu_addr = (int8_t*)&startupConfiguration.lls_cu_addr; + xranInit.p_ru_addr = (int8_t*)&startupConfiguration.ru_addr; + xranInit.ttiPeriod = startupConfiguration.ttiPeriod; + + xranInit.Tadv_cp_dl = startupConfiguration.Tadv_cp_dl; + xranInit.T2a_min_cp_dl = startupConfiguration.T2a_min_cp_dl; + xranInit.T2a_max_cp_dl = startupConfiguration.T2a_max_cp_dl; + xranInit.T2a_min_cp_ul = startupConfiguration.T2a_min_cp_ul; + xranInit.T2a_max_cp_ul = startupConfiguration.T2a_max_cp_ul; + xranInit.T2a_min_up = startupConfiguration.T2a_min_up; + xranInit.T2a_max_up = startupConfiguration.T2a_max_up; + xranInit.Ta3_min = startupConfiguration.Ta3_min; + xranInit.Ta3_max = startupConfiguration.Ta3_max; + xranInit.T1a_min_cp_dl = startupConfiguration.T1a_min_cp_dl; + xranInit.T1a_max_cp_dl = startupConfiguration.T1a_max_cp_dl; + xranInit.T1a_min_cp_ul = startupConfiguration.T1a_min_cp_ul; + xranInit.T1a_max_cp_ul = startupConfiguration.T1a_max_cp_ul; + xranInit.T1a_min_up = startupConfiguration.T1a_min_up; + xranInit.T1a_max_up = startupConfiguration.T1a_max_up; + xranInit.Ta4_min = startupConfiguration.Ta4_min; + xranInit.Ta4_max = startupConfiguration.Ta4_max; + + xranInit.enableCP = startupConfiguration.enableCP; + xranInit.debugStop = startupConfiguration.debugStop; + + xranInit.cp_vlan_tag = startupConfiguration.cp_vlan_tag; + xranInit.up_vlan_tag = startupConfiguration.up_vlan_tag; + + + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + p_tx_play_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES); + tx_play_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES; + + if (p_tx_play_buffer[i] == NULL) + exit(-1); + + tx_play_buffer_size[i] = sys_load_file_to_buff(startupConfiguration.ant_file[i], + "DL IFFT IN IQ Samples in binary format", + (uint8_t*) p_tx_play_buffer[i], + tx_play_buffer_size[i], + 1); + tx_play_buffer_position[i] = 0; + } + + /* log of ul */ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + p_rx_log_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES); + rx_log_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES; + + if (p_rx_log_buffer[i] == NULL) + exit(-1); + + rx_log_buffer_position[i] = 0; + + memset(p_rx_log_buffer[i], 0, rx_log_buffer_size[i]); + } + + /* log of Prach */ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + p_prach_log_buffer[i] = (int16_t*)malloc(PRACH_PLAYBACK_BUFFER_BYTES); + prach_log_buffer_size[i] = (int32_t)PRACH_PLAYBACK_BUFFER_BYTES; + + if (p_prach_log_buffer[i] == NULL) + exit(-1); + + memset(p_prach_log_buffer[i], 0, prach_log_buffer_size[i]); + prach_log_buffer_position[i] = 0; + } + + for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + sprintf(filename, "%s-play_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file_txt(filename, + "DL IFFT IN IQ Samples in human readable format", + (uint8_t*) p_tx_play_buffer[i], + tx_play_buffer_size[i], + 1); + + sprintf(filename, "%s-play_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file(filename, + "DL IFFT IN IQ Samples in binary format", + (uint8_t*) p_tx_play_buffer[i], + tx_play_buffer_size[i]/sizeof(short), + sizeof(short)); + } + if (startupConfiguration.iqswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("TX: Swap I and Q to match RU format: [%d]\n",i); + { + /* swap I and Q */ + int32_t j; + signed short *ptr = (signed short *) p_tx_play_buffer[i]; + signed short temp; + + for (j = 0; j < (int32_t)(tx_play_buffer_size[i]/sizeof(short)) ; j = j + 2){ + temp = ptr[j]; + ptr[j] = ptr[j + 1]; + ptr[j + 1] = temp; + } + } + } + } + +#if 0 + for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + sprintf(filename, "swap_IQ_play_ant%d.txt", i); + sys_save_buf_to_file_txt(filename, + "DL IFFT IN IQ Samples in human readable format", + (uint8_t*) p_tx_play_buffer[i], + tx_play_buffer_size[i], + 1); + } +#endif + if (startupConfiguration.nebyteorderswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("TX: Convert S16 I and S16 Q to network byte order for XRAN Ant: [%d]\n",i); + for (j = 0; j < tx_play_buffer_size[i]/sizeof(short); j++){ + p_tx_play_buffer[i][j] = rte_cpu_to_be_16(p_tx_play_buffer[i][j]); + } + } + } + +#if 0 + for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + sprintf(filename, "swap_be_play_ant%d.txt", i); + sys_save_buf_to_file_txt(filename, + "DL IFFT IN IQ Samples in human readable format", + (uint8_t*) p_tx_play_buffer[i], + tx_play_buffer_size[i], + 1); + } +#endif + + timer_set_tsc_freq_from_clock(); + xran_init(argc, argv, &xranInit, argv[0], &xranHandle); + if(xranHandle == NULL) + exit(1); + + memset(&xranConf, 0, sizeof(XRANFHCONFIG)); + pXranConf = &xranConf; + + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + pXranConf->playback_conf.TxPlayBufAddr[i] = (unsigned long)p_tx_play_buffer[i]; + pXranConf->playback_conf.TxPlayBufSize = tx_play_buffer_size[i]; + } + + pXranConf->sector_id = 0; + pXranConf->nCC = numCCPorts; + pXranConf->neAxc = num_eAxc; + + pXranConf->frame_conf.nFrameDuplexType = 1; // TDD + pXranConf->frame_conf.nNumerology = startupConfiguration.mu_number; // 120KHz; same as XRAN_SCS_120KHz? +// pXranConf->frame_conf.nTddPeriod = ; + + pXranConf->prach_conf.nPrachSubcSpacing = XRAN_SCS_120KHZ; + pXranConf->prach_conf.nPrachFreqStart = 0; + pXranConf->prach_conf.nPrachFilterIdx = XRAN_FILTERINDEX_PRACH_ABC; + pXranConf->prach_conf.nPrachConfIdx = 81; + pXranConf->prach_conf.nPrachFreqOffset = -792; + + pXranConf->ru_conf.iqWidth = 16; + pXranConf->ru_conf.compMeth = XRAN_COMPMETHOD_NONE; + pXranConf->ru_conf.fftSize = XRAN_FFTSIZE_2048; + + + if(init_xran() != 0) + exit(-1); + + xran_reg_physide_cb(xranHandle, physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI); + xran_reg_physide_cb(xranHandle, physide_ul_half_slot_call_back, NULL, 10, XRAN_CB_HALF_SLOT_RX); + xran_reg_physide_cb(xranHandle, physide_ul_full_slot_call_back, NULL, 10, XRAN_CB_FULL_SLOT_RX); + + init_xran_iq_content(); + + xran_open(xranHandle, pXranConf); + + sprintf(filename, "mlog-%s", startupConfiguration.appMode == 0 ? "lls-cu" : "ru"); + + MLogOpen(0, 32, 0, 0xFFFFFFFF, filename); + puts("----------------------------------------"); + printf("MLog Info: virt=0x%016lx size=%d\n", MLogGetFileLocation(), MLogGetFileSize()); + puts("----------------------------------------"); + + state = APP_RUNNING; + sleep(6); + for (;;) { + print_menu(); + char input[10]; + int sel_opt; +//#ifdef Nightly_build +// sel_opt = 3; +// sleep(10); +//#else + if (NULL == fgets(input, 10, stdin)) { + state = APP_STOPPED; + break; + } + sel_opt = atoi(input); +//#endif + switch (sel_opt) { + case 1: + xran_start(xranHandle); + printf("Start XRAN traffic\n"); + break; + case 2: + break; + case 3: + xran_stop(xranHandle); + printf("Stop XRAN traffic\n"); + state = APP_STOPPED; + break; + case 4: +// send_cpmsg_dlul(XRAN_DIR_DL, flowId, +// frame_id, subframe_id, slot_id, +// 0, XRAN_SYMBOLPERSLOT_MAX, NUM_OF_PRB_IN_FULL_BAND, +// beam_id, cc_id, ant_id, +// cp_seq_id_num[XRAN_DIR_DL][ant_id]++); + break; + default: + puts("Wrong option passed!"); + break; + } + + if (APP_STOPPED == state) + break; + } + + get_xran_iq_content(); + + puts("Closing l1 app... Ending all threads..."); + xran_close(xranHandle); + MLogPrint(NULL); + + stop_xran(); + puts("Dump IQs..."); + + if (startupConfiguration.iqswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("RX: Swap I and Q to match CPU format: [%d]\n",i); + { + /* swap I and Q */ + int32_t j; + signed short *ptr = (signed short *) p_rx_log_buffer[i]; + signed short temp; + + for (j = 0; j < (int32_t)(rx_log_buffer_size[i]/sizeof(short)) ; j = j + 2){ + temp = ptr[j]; + ptr[j] = ptr[j + 1]; + ptr[j + 1] = temp; + } + } + } + } + + if (startupConfiguration.nebyteorderswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("RX: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i); + for (j = 0; j < rx_log_buffer_size[i]/sizeof(short); j++){ + p_rx_log_buffer[i][j] = rte_be_to_cpu_16(p_rx_log_buffer[i][j]); + } + } + } + + for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + sprintf(filename, "%s-rx_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file_txt(filename, + "UL FFT OUT IQ Samples in human readable format", + (uint8_t*) p_rx_log_buffer[i], + rx_log_buffer_size[i], + 1); + + sprintf(filename, "%s-rx_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file(filename, + "UL FFT OUT IQ Samples in binary format", + (uint8_t*) p_rx_log_buffer[i], + rx_log_buffer_size[i]/sizeof(short), + sizeof(short)); + } + + if (startupConfiguration.iqswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("PRACH: Swap I and Q to match CPU format: [%d]\n",i); + { + /* swap I and Q */ + int32_t j; + signed short *ptr = (signed short *) p_prach_log_buffer[i]; + signed short temp; + + for (j = 0; j < (int32_t)(prach_log_buffer_size[i]/sizeof(short)) ; j = j + 2){ + temp = ptr[j]; + ptr[j] = ptr[j + 1]; + ptr[j + 1] = temp; + } + } + } + } + + if (startupConfiguration.nebyteorderswap == 1){ + for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + printf("PRACH: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i); + for (j = 0; j < prach_log_buffer_size[i]/sizeof(short); j++){ + p_prach_log_buffer[i][j] = rte_be_to_cpu_16(p_prach_log_buffer[i][j]); + } + } + } + + for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) { + + sprintf(filename, "%s-prach_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file_txt(filename, + "PRACH FFT OUT IQ Samples in human readable format", + (uint8_t*) p_prach_log_buffer[i], + prach_log_buffer_size[i], + 1); + + sprintf(filename, "%s-prach_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i); + sys_save_buf_to_file(filename, + "PRACH FFT OUT IQ Samples in binary format", + (uint8_t*) p_prach_log_buffer[i], + prach_log_buffer_size[i]/sizeof(short), + sizeof(short)); + } + + return 0; +} diff --git a/fhi_lib/app/ru/Makefile b/fhi_lib/app/ru/Makefile new file mode 100644 index 0000000..29ac054 --- /dev/null +++ b/fhi_lib/app/ru/Makefile @@ -0,0 +1,85 @@ +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ +CC := icc + +ifeq ($(RTE_SDK),) + $(error "Please define RTE_SDK environment variable") +endif + +RTE_TARGET := x86_64-native-linuxapp-icc +RTE_INC := $(RTE_SDK)/$(RTE_TARGET)/include +#include $(RTE_SDK)/mk/rte.vars.mk + +ifeq ($(XRAN_DIR),) + XRAN_DIR=$(PWD)/../.. +endif + +COMMON_SRC=$(XRAN_DIR)/app/common +SRC_SRC=$(XRAN_DIR)/app/src + +ifeq ($(MLOG_DIR),) + MLOG_DIR=$(XRAN_DIR)/../mlog +endif +APP = sample-ru +SRC = $(COMMON_SRC)/common.c \ + ../lls-cu/sample-lls-cu.c \ + $(SRC_SRC)/config.c + +CFLAGS += -std=gnu11 -Wall -wd9 -Wextra -Werror -I$(XRAN_DIR)/lib/api -I$(COMMON_SRC) -I$(SRC_SRC) -I$(MLOG_DIR)/source -I$(RTE_INC) +ifeq ($(ME),1) + CFLAGS += -DMLOG_ENABLED +endif + +ifeq ($(DEBUG),1) + CFLAGS += -DDEBUG -O0 -g +else + CFLAGS += -O3 +endif + +ifeq ($(MULTI_SECTION),1) + CFLAGS += -DMULTI_SECTION +endif + +LDFLAGS += -pthread -lrt + +RTE_LIBS = -L$(RTE_SDK)/$(RTE_TARGET)/lib -Wl,-lrte_flow_classify -Wl,--whole-archive -Wl,-lrte_pipeline -Wl,--no-whole-archive -Wl,--whole-archive -Wl,-lrte_table -Wl,--no-whole-archive -Wl,--whole-archive -Wl,-lrte_port -Wl,--no-whole-archive -Wl,-lrte_pdump -Wl,-lrte_distributor -Wl,-lrte_ip_frag -Wl,-lrte_meter -Wl,-lrte_lpm -Wl,--whole-archive -Wl,-lrte_acl -Wl,--no-whole-archive -Wl,-lrte_jobstats -Wl,-lrte_metrics -Wl,-lrte_bitratestats -Wl,-lrte_latencystats -Wl,-lrte_power -Wl,-lrte_efd -Wl,-lrte_bpf -Wl,--whole-archive -Wl,-lrte_cfgfile -Wl,-lrte_gro -Wl,-lrte_gso -Wl,-lrte_hash -Wl,-lrte_member -Wl,-lrte_vhost -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_net -Wl,-lrte_ethdev -Wl,-lrte_bbdev -Wl,-lrte_cryptodev -Wl,-lrte_security -Wl,-lrte_compressdev -Wl,-lrte_eventdev -Wl,-lrte_rawdev -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci -Wl,-lrte_eal -Wl,-lrte_cmdline -Wl,-lrte_reorder -Wl,-lrte_sched -Wl,-lrte_kni -Wl,-lrte_common_octeontx -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_bus_dpaa -Wl,-lrte_bus_fslmc -Wl,-lrte_mempool_bucket -Wl,-lrte_mempool_stack -Wl,-lrte_mempool_dpaa -Wl,-lrte_mempool_dpaa2 -Wl,-lrte_pmd_af_packet -Wl,-lrte_pmd_ark -Wl,-lrte_pmd_avf -Wl,-lrte_pmd_avp -Wl,-lrte_pmd_axgbe -Wl,-lrte_pmd_bnxt -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_cxgbe -Wl,-lrte_pmd_dpaa -Wl,-lrte_pmd_dpaa2 -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ena -Wl,-lrte_pmd_enic -Wl,-lrte_pmd_fm10k -Wl,-lrte_pmd_failsafe -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_kni -Wl,-lrte_pmd_lio -Wl,-lrte_pmd_nfp -Wl,-lrte_pmd_null -Wl,-lrte_pmd_qede -Wl,-lrte_pmd_ring -Wl,-lrte_pmd_softnic -Wl,-lrte_pmd_tap -Wl,-lrte_pmd_thunderx_nicvf -Wl,-lrte_pmd_vdev_netvsc -Wl,-lrte_pmd_virtio -Wl,-lrte_pmd_vhost -Wl,-lrte_pmd_ifc -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_bus_vmbus -Wl,-lrte_pmd_netvsc -Wl,-lrte_pmd_bbdev_null -Wl,-lrte_pmd_null_crypto -Wl,-lrte_pmd_crypto_scheduler -Wl,-lrte_pmd_dpaa2_sec -Wl,-lrte_pmd_dpaa_sec -Wl,-lrte_pmd_virtio_crypto -Wl,-lrte_pmd_octeontx_zip -Wl,-lrte_pmd_qat -Wl,-lrte_pmd_skeleton_event -Wl,-lrte_pmd_sw_event -Wl,-lrte_pmd_octeontx_ssovf -Wl,-lrte_pmd_dpaa_event -Wl,-lrte_pmd_dpaa2_event -Wl,-lrte_mempool_octeontx -Wl,-lrte_pmd_octeontx -Wl,-lrte_pmd_opdl_event -Wl,-lrte_pmd_skeleton_rawdev -Wl,-lrte_pmd_dpaa2_cmdif -Wl,-lrte_pmd_dpaa2_qdma -Wl,-lrte_bus_ifpga -Wl,-lrte_pmd_ifpga_rawdev -Wl,--no-whole-archive -Wl,-lrt -Wl,-lm -Wl,-lnuma -Wl,-ldl -Wl, + +XRAN_LIB_DIR=$(XRAN_DIR)/lib/bin +LDFLAGS += -L$(XRAN_LIB_DIR) -Wl, -lxran -Wl, -L$(MLOG_DIR)/bin -Wl, $(RTE_LIBS) +ifeq ($(ME),1) + LDFLAGS += -Wl,-lmlog +endif +OBJ = $(foreach file,$(SRC),$(file:.c=.o)) + + +all: $(APP) install + +$(OBJ): %.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(APP): $(OBJ) + $(CC) -o $(APP) $(CFLAGS) $(OBJ) $(LDFLAGS) + +install: $(APP) + @mkdir -p bin + @cp $(APP) ./bin + +clean: + @rm -rf $(APP) $(OBJ) ./bin/$(APP) + +#include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/fhi_lib/app/run_lls-cu.sh b/fhi_lib/app/run_lls-cu.sh new file mode 100644 index 0000000..cec7e5b --- /dev/null +++ b/fhi_lib/app/run_lls-cu.sh @@ -0,0 +1,36 @@ +#! /bin/bash + +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ + + +ulimit -c unlimited +echo 1 > /proc/sys/kernel/core_uses_pid + +grep Huge /proc/meminfo +huge_folder="/mnt/huge_bbu" +[ -d "$huge_folder" ] || mkdir -p $huge_folder +if ! mount | grep $huge_folder; then + mount none $huge_folder -t hugetlbfs -o rw,mode=0777 +fi + +./lls-cu/bin/sample-lls-cu config_file_lls_cu.dat 0000:18:02.0 0000:18:02.1 + +umount $huge_folder +rmdir $huge_folder + diff --git a/fhi_lib/app/run_ru.sh b/fhi_lib/app/run_ru.sh new file mode 100644 index 0000000..e84bc0a --- /dev/null +++ b/fhi_lib/app/run_ru.sh @@ -0,0 +1,35 @@ +#! /bin/bash + +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ + +ulimit -c unlimited +echo 1 > /proc/sys/kernel/core_uses_pid + +grep Huge /proc/meminfo +huge_folder="/mnt/huge_ru" +[ -d "$huge_folder" ] || mkdir -p $huge_folder +if ! mount | grep $huge_folder; then + mount none $huge_folder -t hugetlbfs -o rw,mode=0777 +fi + +./ru/bin/sample-ru config_file_ru.dat 0000:18:02.0 0000:18:02.1 + +umount $huge_folder +rmdir $huge_folder + diff --git a/fhi_lib/app/src/config.c b/fhi_lib/app/src/config.c new file mode 100644 index 0000000..1564c8d --- /dev/null +++ b/fhi_lib/app/src/config.c @@ -0,0 +1,373 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief + * @file + * @ingroup + * @author Intel Corporation + **/ + +#include "rte_common.h" +#include "config.h" + +#include + +#define MAX_LINE_SIZE 512 +/* Configuration file maximum supported line length */ + + +#define KEY_APP_MODE "appMode" +#define KEY_XRAN_MODE "xranMode" +#define KEY_MU_NUMBER "mu" +#define KEY_CC_PER_PORT_NUM "ccNum" +#define KEY_ANT_NUM "antNum" +#define KEY_TTI_PERIOD "ttiPeriod" +#define KEY_LLS_CU_MAC "llsCUMac" +#define KEY_RU_MAC "ruMac" + +#define KEY_FILE_AxC0 "antC0" +#define KEY_FILE_AxC1 "antC1" +#define KEY_FILE_AxC2 "antC2" +#define KEY_FILE_AxC3 "antC3" +#define KEY_FILE_AxC4 "antC4" +#define KEY_FILE_AxC5 "antC5" +#define KEY_FILE_AxC6 "antC6" +#define KEY_FILE_AxC7 "antC7" +#define KEY_FILE_AxC8 "antC8" +#define KEY_FILE_AxC9 "antC9" +#define KEY_FILE_AxC10 "antC10" +#define KEY_FILE_AxC11 "antC11" +#define KEY_FILE_AxC12 "antC12" +#define KEY_FILE_AxC13 "antC13" +#define KEY_FILE_AxC14 "antC14" +#define KEY_FILE_AxC15 "antC15" + +#define KEY_PRACH_ENABLE "rachEanble" +#define KEY_PRACH_OFFSET "rachOffset" +#define KEY_PRACH_CFG_IDX "rachCfgIdx" + +#define KEY_IQ_SWAP "iqswap" +#define KEY_HTONS_SWAP "nebyteorderswap" + +#define KEY_TADV_CP_DL "Tadv_cp_dl" +#define KEY_T2A_MIN_CP_DL "T2a_min_cp_dl" +#define KEY_T2A_MAX_CP_DL "T2a_max_cp_dl" +#define KEY_T2A_MIN_CP_UL "T2a_min_cp_ul" +#define KEY_T2A_MAX_CP_UL "T2a_max_cp_ul" +#define KEY_T2A_MIN_UP "T2a_min_up" +#define KEY_T2A_MAX_UP "T2a_max_up" +#define KEY_TA3_MIN "Ta3_min" +#define KEY_TA3_MAX "Ta3_max" +#define KEY_T1A_MIN_CP_DL "T1a_min_cp_dl" +#define KEY_T1A_MAX_CP_DL "T1a_max_cp_dl" +#define KEY_T1A_MIN_CP_UL "T1a_min_cp_ul" +#define KEY_T1A_MAX_CP_UL "T1a_max_cp_ul" +#define KEY_T1A_MIN_UP "T1a_min_up" +#define KEY_T1A_MAX_UP "T1a_max_up" +#define KEY_TA4_MIN "Ta4_min" +#define KEY_TA4_MAX "Ta4_max" + + +#define KEY_CP_ENABLE "CPenable" +#define KEY_CP_VTAG "c_plane_vlan_tag" +#define KEY_UP_VTAG "u_plane_vlan_tag" +#define KEY_DEBUG_STOP "debugStop" + + +/** + * Set runtime configuration parameters to their defaults. + * + * @todo Initialize missing parameters. + */ +static void init_config(RuntimeConfig* config) +{ + memset(config , 0, sizeof(RuntimeConfig)); +} + +/** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - **/ + +static void trim(char* input) +{ + uint32_t i; + for (i = 0; iappMode = atoi(value); + } else if (strcmp(key, KEY_XRAN_MODE) == 0) { + config->xranMode = atoi(value); + } else if (strcmp(key, KEY_CC_PER_PORT_NUM) == 0) { + config->numCC= atoi(value); + } else if (strcmp(key, KEY_MU_NUMBER) == 0) { + config->mu_number= atoi(value); + } else if (strcmp(key, KEY_ANT_NUM) == 0) { + config->numAxc = atoi(value); + } else if (strcmp(key, KEY_TTI_PERIOD) == 0) { + config->ttiPeriod = atoi(value); + } else if (strcmp(key, KEY_IQ_SWAP) == 0) { + config->iqswap = atoi(value); + } else if (strcmp(key, KEY_HTONS_SWAP) == 0) { + config->nebyteorderswap = atoi(value); + } else if (strcmp(key, KEY_LLS_CU_MAC) == 0) { + sscanf(value, "%02x:%02x:%02x:%02x:%02x:%02x", (uint32_t*)&config->lls_cu_addr.addr_bytes[0], + (uint32_t*)&config->lls_cu_addr.addr_bytes[1], + (uint32_t*)&config->lls_cu_addr.addr_bytes[2], + (uint32_t*)&config->lls_cu_addr.addr_bytes[3], + (uint32_t*)&config->lls_cu_addr.addr_bytes[4], + (uint32_t*)&config->lls_cu_addr.addr_bytes[5]); + + printf("lls-CU MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", + config->lls_cu_addr.addr_bytes[0], + config->lls_cu_addr.addr_bytes[1], + config->lls_cu_addr.addr_bytes[2], + config->lls_cu_addr.addr_bytes[3], + config->lls_cu_addr.addr_bytes[4], + config->lls_cu_addr.addr_bytes[5]); + + } else if (strcmp(key, KEY_RU_MAC) == 0) { + sscanf(value, "%02x:%02x:%02x:%02x:%02x:%02x", (uint32_t*)&config->ru_addr.addr_bytes[0], + (uint32_t*)&config->ru_addr.addr_bytes[1], + (uint32_t*)&config->ru_addr.addr_bytes[2], + (uint32_t*)&config->ru_addr.addr_bytes[3], + (uint32_t*)&config->ru_addr.addr_bytes[4], + (uint32_t*)&config->ru_addr.addr_bytes[5]); + + printf("RU MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", + config->ru_addr.addr_bytes[0], + config->ru_addr.addr_bytes[1], + config->ru_addr.addr_bytes[2], + config->ru_addr.addr_bytes[3], + config->ru_addr.addr_bytes[4], + config->ru_addr.addr_bytes[5]); + } else if (strcmp(key, KEY_FILE_AxC0) == 0) { + strncpy(&config->ant_file[0][0], value, strlen(value)); + printf("ant0: %s\n",config->ant_file[0]); + } else if (strcmp(key, KEY_FILE_AxC1) == 0) { + strncpy(&config->ant_file[1][0], value, strlen(value)); + printf("ant1: %s\n",config->ant_file[1]); + } else if (strcmp(key, KEY_FILE_AxC2) == 0) { + strncpy(&config->ant_file[2][0], value, strlen(value)); + printf("ant2: %s\n",config->ant_file[2]); + } else if (strcmp(key, KEY_FILE_AxC3) == 0) { + strncpy(&config->ant_file[3][0], value, strlen(value)); + printf("ant3: %s\n",config->ant_file[3]); + } else if (strcmp(key, KEY_FILE_AxC4) == 0) { + strncpy(&config->ant_file[4][0], value, strlen(value)); + printf("ant4: %s\n",config->ant_file[4]); + } else if (strcmp(key, KEY_FILE_AxC5) == 0) { + strncpy(&config->ant_file[5][0], value, strlen(value)); + printf("ant5: %s\n",config->ant_file[5]); + } else if (strcmp(key, KEY_FILE_AxC6) == 0) { + strncpy(&config->ant_file[6][0], value, strlen(value)); + printf("ant6: %s\n",config->ant_file[6]); + } else if (strcmp(key, KEY_FILE_AxC7) == 0) { + strncpy(&config->ant_file[7][0], value, strlen(value)); + printf("ant7: %s\n",config->ant_file[7]); + } else if (strcmp(key, KEY_FILE_AxC8) == 0) { + strncpy(&config->ant_file[8][0], value, strlen(value)); + printf("ant8: %s\n",config->ant_file[8]); + } else if (strcmp(key, KEY_FILE_AxC9) == 0) { + strncpy(&config->ant_file[9][0], value, strlen(value)); + printf("ant9: %s\n",config->ant_file[9]); + } else if (strcmp(key, KEY_FILE_AxC10) == 0) { + strncpy(&config->ant_file[10][0], value, strlen(value)); + printf("ant10: %s\n",config->ant_file[10]); + } else if (strcmp(key, KEY_FILE_AxC11) == 0) { + strncpy(&config->ant_file[11][0], value, strlen(value)); + printf("ant11: %s\n",config->ant_file[11]); + } else if (strcmp(key, KEY_FILE_AxC12) == 0) { + strncpy(&config->ant_file[12][0], value, strlen(value)); + printf("ant12: %s\n",config->ant_file[12]); + } else if (strcmp(key, KEY_FILE_AxC13) == 0) { + strncpy(&config->ant_file[13][0], value, strlen(value)); + printf("ant13: %s\n",config->ant_file[13]); + } else if (strcmp(key, KEY_FILE_AxC14) == 0) { + strncpy(&config->ant_file[14][0], value, strlen(value)); + printf("ant14: %s\n",config->ant_file[14]); + } else if (strcmp(key, KEY_FILE_AxC15) == 0) { + strncpy(&config->ant_file[15][0], value, strlen(value)); + printf("ant15: %s\n",config->ant_file[15]); + } else if (strcmp(key, KEY_PRACH_ENABLE) == 0) { + config->enablePrach = atoi(value); + printf("Prach enable: %d\n",config->enablePrach); + } else if (strcmp(key, KEY_PRACH_OFFSET ) == 0) { + config->prachOffset = atoi(value); + printf("Prach Offset: %d\n",config->prachOffset); + } else if (strcmp(key, KEY_PRACH_CFG_IDX ) == 0) { + config->prachConfigIndex = atoi(value); + printf("Prach Conf Index: %d\n",config->prachConfigIndex); + + /* timing */ + } else if (strcmp(key, KEY_TADV_CP_DL ) == 0) { + config->Tadv_cp_dl = atoi(value); + printf("Tadv_cp_dl: %d\n",config->Tadv_cp_dl); + } else if (strcmp(key, KEY_T2A_MIN_CP_DL ) == 0) { + config->T2a_min_cp_dl = atoi(value); + printf("T2a_min_cp_dl: %d\n",config->T2a_min_cp_dl); + } else if (strcmp(key, KEY_T2A_MAX_CP_DL ) == 0) { + config->T2a_max_cp_dl = atoi(value); + printf("T2a_max_cp_dl: %d\n",config->T2a_max_cp_dl); + } else if (strcmp(key, KEY_T2A_MIN_CP_UL ) == 0) { + config->T2a_min_cp_ul = atoi(value); + printf("T2a_min_cp_ul: %d\n",config->T2a_min_cp_ul); + } else if (strcmp(key, KEY_T2A_MAX_CP_UL ) == 0) { + config->T2a_max_cp_ul = atoi(value); + printf("T2a_max_cp_ul: %d\n",config->T2a_max_cp_ul); + } else if (strcmp(key, KEY_T2A_MIN_UP ) == 0) { + config->T2a_min_up = atoi(value); + printf("T2a_min_up: %d\n",config->T2a_min_up); + } else if (strcmp(key, KEY_T2A_MAX_UP ) == 0) { + config->T2a_max_up = atoi(value); + printf("T2a_max_up: %d\n",config->T2a_max_up); + } else if (strcmp(key, KEY_TA3_MIN ) == 0) { + config->Ta3_min = atoi(value); + printf("Ta3_min: %d\n",config->Ta3_min); + } else if (strcmp(key, KEY_TA3_MAX ) == 0) { + config->Ta3_max = atoi(value); + printf("Ta3_max: %d\n",config->Ta3_max); + } else if (strcmp(key, KEY_T1A_MIN_CP_DL ) == 0) { + config->T1a_min_cp_dl = atoi(value); + printf("T1a_min_cp_dl: %d\n",config->T1a_min_cp_dl); + } else if (strcmp(key, KEY_T1A_MAX_CP_DL ) == 0) { + config->T1a_max_cp_dl = atoi(value); + printf("T1a_max_cp_dl: %d\n",config->T1a_max_cp_dl); + } else if (strcmp(key, KEY_T1A_MIN_CP_UL ) == 0) { + config->T1a_min_cp_ul = atoi(value); + printf("T1a_min_cp_ul: %d\n",config->T1a_min_cp_ul); + } else if (strcmp(key, KEY_T1A_MAX_CP_UL ) == 0) { + config->T1a_max_cp_ul = atoi(value); + printf("T1a_max_cp_ul: %d\n",config->T1a_max_cp_ul); + } else if (strcmp(key, KEY_T1A_MIN_UP ) == 0) { + config->T1a_min_up = atoi(value); + printf("T1a_min_up: %d\n",config->T1a_min_up); + } else if (strcmp(key, KEY_T1A_MAX_UP ) == 0) { + config->T1a_max_up = atoi(value); + printf("T1a_max_up: %d\n",config->T1a_max_up); + } else if (strcmp(key, KEY_TA4_MIN ) == 0) { + config->Ta4_min = atoi(value); + printf("Ta4_min: %d\n",config->Ta4_min); + } else if (strcmp(key, KEY_TA4_MAX ) == 0) { + config->Ta4_max = atoi(value); + printf("Ta4_max: %d\n",config->Ta4_max); + /* end of timing */ + } else if (strcmp(key, KEY_CP_ENABLE ) == 0) { + config->enableCP = atoi(value); + printf("CPenable: %d\n",config->enableCP); + } else if (strcmp(key, KEY_DEBUG_STOP ) == 0) { + config->debugStop = atoi(value); + printf("debugStop: %d\n",config->debugStop); + } else if (strcmp(key, KEY_CP_VTAG ) == 0) { + config->cp_vlan_tag = atoi(value); + printf("cp_vlan_tag: %d\n",config->cp_vlan_tag); + } else if (strcmp(key, KEY_UP_VTAG ) == 0) { + config->up_vlan_tag = atoi(value); + printf("up_vlan_tag: %d\n",config->up_vlan_tag); + } else { + printf("Unsupported configuration key [%s]\n", key); + return -1; + } + + return 0; +} + +int parseConfigFile(char *filename, RuntimeConfig *config) +{ + char inputLine[MAX_LINE_SIZE] = {0}; + int inputLen = 0; + int i; + int lineNum = 0; + char key[MAX_LINE_SIZE] = {0}; + char value[MAX_LINE_SIZE] = {0}; + FILE *file = fopen(filename, "r"); + + if (NULL == file) { + //log_err("Error while opening config file from: %s", filename); + return -1; + } + + init_config(config); + + for (;;) { + if (fgets(inputLine, MAX_LINE_SIZE, file) == NULL) { + if (lineNum > 0) { + printf("%d lines of config file has been read.\n", lineNum); + break; + } else { + printf("Configuration file reading error has occurred.\n"); + fclose(file); + return -1; + } + } + + if (inputLine[strlen(inputLine)-1] == '\n') + inputLine[strlen(inputLine)-1] == '\0'; + + lineNum++; + inputLen = strlen(inputLine); + + for (i=0; i inputLen - 1) || (i - 2 > inputLen)) { + //log_err("Parsing config file error at line %d", lineNum); + fclose(file); + return -1; + } + strncpy(value, &inputLine[i+1], (sizeof(value) - 1)); + value[inputLen-i-2] = '\0'; + trim(value); + + if (strlen(key) == 0 || strlen(value) == 0) { + printf("Parsing config file error at line %d", lineNum); + fclose(file); + return -1; + } + + if (fillConfigStruct(config, key, value) != 0) { + fclose(file); + return -1; + } + + break; + } + + memset(&inputLine[0], 0, sizeof(MAX_LINE_SIZE)); + memset(&key[0], 0, sizeof(MAX_LINE_SIZE)); + memset(&value[0], 0, sizeof(MAX_LINE_SIZE)); + } + fclose(file); + + return 0; +} diff --git a/fhi_lib/app/src/config.h b/fhi_lib/app/src/config.h new file mode 100644 index 0000000..b2953ee --- /dev/null +++ b/fhi_lib/app/src/config.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief + * @file + * @ingroup + * @author Intel Corporation + **/ + +#ifndef _SAMPLEAPP__CONFIG_H_ +#define _SAMPLEAPP__CONFIG_H_ + +#include +#include + +/** Run time configuration of application */ +typedef struct _RuntimeConfig +{ + uint8_t appMode; /**< Application mode: lls-CU or RU */ + uint8_t xranMode; /**< xran mode: Categoty A | Category B */ + uint8_t numCC; /**< Number of CC per ports supported by RU */ + uint8_t mu_number; /**< Mu numner as per 3GPP */ + uint8_t numAxc; /**< Number of Antenna Carriers per CC */ + uint32_t ttiPeriod; /**< TTI period */ + uint32_t testVect; /**< Test Signal to send */ + struct ether_addr lls_cu_addr; /**< lls-CU Ethernet Mac Address */ + struct ether_addr ru_addr; /**< RU Ethernet Mac Address */ + char ant_file[16][512] /**< file to use for test vector */ ; + + /* prach config */ + uint8_t enablePrach; /**< enable PRACH */ + uint8_t prachOffset; /**< Sets the PRACH position in frequency / subcarrier position, n_PRBoffset^RA and is expressed as a physical resource block number. + Set by SIB2, prach-FreqOffset in E-UTRA. */ + + uint8_t prachConfigIndex; /**< TS36.211 - Table 5.7.1-2 : PRACH Configuration Index */ + uint8_t iqswap; /**< do swap of IQ before send to ETH */ + uint8_t nebyteorderswap; /**< do swap of byte order from host byte order to network byte order. ETH */ + + uint16_t Tadv_cp_dl; + uint16_t T2a_min_cp_dl; + uint16_t T2a_max_cp_dl; + uint16_t T2a_min_cp_ul; + uint16_t T2a_max_cp_ul; + uint16_t T2a_min_up; + uint16_t T2a_max_up; + uint16_t Ta3_min; + uint16_t Ta3_max; + uint16_t T1a_min_cp_dl; + uint16_t T1a_max_cp_dl; + uint16_t T1a_min_cp_ul; + uint16_t T1a_max_cp_ul; + uint16_t T1a_min_up; + uint16_t T1a_max_up; + uint16_t Ta4_min; + uint16_t Ta4_max; + + uint8_t enableCP; /**< enable C-plane */ + uint8_t cp_vlan_tag; /**< C-plane vlan tag */ + uint8_t up_vlan_tag; /**< U-plane vlan tag */ + + int32_t debugStop; + + +} RuntimeConfig; + +/** + * Parse application configuration file. + * + * @param filename The name of the configuration file to be parsed. + * @param config The configuration structure to be filled with parsed data. */ +int parseConfigFile(char *filename, RuntimeConfig *config); + +#endif /* _SAMPLEAPP__CONFIG_H_ */ diff --git a/fhi_lib/app/src/xran_mlog_task_id.h b/fhi_lib/app/src/xran_mlog_task_id.h new file mode 100644 index 0000000..23a673c --- /dev/null +++ b/fhi_lib/app/src/xran_mlog_task_id.h @@ -0,0 +1,61 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file has the System Debug Trace Logger (Mlog) Task IDs used by PHY + * @file mlog_task_id.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#ifndef _XRAN_TASK_ID_H_ +#define _XRAN_TASK_ID_H_ + +#define RESOURCE_CORE_0 0 +#define RESOURCE_CORE_1 1 +#define RESOURCE_CORE_2 2 +#define RESOURCE_CORE_3 3 +#define RESOURCE_CORE_4 4 +#define RESOURCE_CORE_5 5 +#define RESOURCE_CORE_6 6 +#define RESOURCE_CORE_7 7 +#define RESOURCE_CORE_8 8 +#define RESOURCE_CORE_9 9 +#define RESOURCE_CORE_10 10 +#define RESOURCE_CORE_11 11 +#define RESOURCE_CORE_12 12 +#define RESOURCE_CORE_13 13 +#define RESOURCE_CORE_14 14 +#define RESOURCE_CORE_15 15 +#define RESOURCE_CORE_16 16 + +#define RESOURCE_IA_CORE 100 + +//-------------------------------------------------------------------- +// XRAN APP +//-------------------------------------------------------------------- + +#define PID_GNB_PROC_TIMING 902 +#define PID_GNB_PROC_TIMING_TIMEOUT 903 +#define PID_GNB_SYM_CB 904 +#define PID_GNB_PRACH_CB 905 + + +#endif /* _XRAN_TASK_ID_H_ */ + diff --git a/fhi_lib/build.sh b/fhi_lib/build.sh new file mode 100644 index 0000000..149ad8a --- /dev/null +++ b/fhi_lib/build.sh @@ -0,0 +1,30 @@ +#!/bin/bash +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ + +XRAN_FH_LIB_DIR=$XRAN_DIR/lib +XRAN_FH_APP_DIR=$XRAN_DIR/app + +echo 'Building XRAN Library' +cd $XRAN_FH_LIB_DIR +make clean; make #DEBUG=1 VERBOSE=1 + +echo 'Building XRAN Test Application' +cd $XRAN_FH_APP_DIR +make clean; make #DEBUG=1 VERBOSE=1 + diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile new file mode 100644 index 0000000..d65eef1 --- /dev/null +++ b/fhi_lib/lib/Makefile @@ -0,0 +1,87 @@ +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ +CC := icc +AR := xiar + +ifeq ($(RTE_SDK),) + $(error "Please define RTE_SDK environment variable") +endif + +RTE_TARGET := x86_64-native-linuxapp-icc +RTE_INC := $(RTE_SDK)/$(RTE_TARGET)/include +#include $(RTE_SDK)/mk/rte.vars.mk +API_DIR := $(PWD)/api +SRC_DIR := $(PWD)/src +ETH_DIR := $(PWD)/ethernet + + +ifeq ($(MLOG_DIR),) + MLOG_DIR=$(XRAN_DIR)/../mlog +endif + +CFLAGS += -std=gnu11 -Wall -wd9 -Wno-deprecated-declarations -Wextra -Werror -qopt-report-phase:all -qopt-zmm-usage=high \ + -fdata-sections \ + -ffunction-sections \ + -restrict \ + -g \ + -Wall \ + -Wimplicit-function-declaration \ + -Werror \ + -Wextra \ + -no-inline-max-total-size \ + -no-inline-max-size \ + -I$(API_DIR) -I$(ETH_DIR) -I$(MLOG_DIR)/source -I$(RTE_INC) -g -O3 + +ifeq ($(ME),1) + CFLAGS += -DMLOG_ENABLED +endif +SRC = $(ETH_DIR)/ethdi.c \ + $(ETH_DIR)/ethernet.c \ + $(SRC_DIR)/xran_up_api.c \ + $(SRC_DIR)/xran_sync_api.c \ + $(SRC_DIR)/xran_timer.c \ + $(SRC_DIR)/xran_cp_api.c \ + $(SRC_DIR)/xran_transport.c \ + $(SRC_DIR)/xran_common.c \ + $(SRC_DIR)/xran_ul_tables.c \ + $(SRC_DIR)/xran_main.c + +FLEX_C_CRAN_LIB = libxran.a + +OBJ = $(foreach file,$(SRC),$(file:.c=.o)) + + +all: flex_lib install + +$(OBJ): %.o: %.c + $(CC) $(CFLAGS) -I$(API_DIR) -c $< -o $@ + + +flex_lib:$(FLEX_C_CRAN_LIB) + +$(FLEX_C_CRAN_LIB): $(OBJ) + $(AR) rsu $@ $^ + +install: $(FLEX_C_CRAN_LIB) + mkdir -p bin + @mv $(FLEX_C_CRAN_LIB) ./bin + +clean: + @rm -rf $(FLEX_C_CRAN_LIB) $(OBJ) ./bin/$(FLEX_C_CRAN_LIB) + +#include $(RTE_SDK)/mk/rte.extlib.mk diff --git a/fhi_lib/lib/api/xran_cp_api.h b/fhi_lib/lib/api/xran_cp_api.h new file mode 100644 index 0000000..9d08e42 --- /dev/null +++ b/fhi_lib/lib/api/xran_cp_api.h @@ -0,0 +1,220 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the definitions for Control Plane Messages APIs. + * + * @file xran_cp_api.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_CP_API_H_ +#define _XRAN_CP_API_H_ + +#include "xran_fh_lls_cu.h" +#include "xran_pkt_cp.h" + +/* Error Codes + * For errors and exceptions, all values will be negative */ +enum xran_errcodes { + XRAN_ERRCODE_OK = 0, + XRAN_ERRCODE_INVALIDPARAM, + XRAN_ERRCODE_OUTOFMEMORY, + XRAN_ERRCODE_FAILTOSEND, + XRAN_ERRCODE_INVALIDPACKET, + XRAN_ERRCODE_MAX + }; + +/** Control Plane section types, defined in 5.4 Table 5.1 */ +enum xran_cp_sectiontype { + XRAN_CP_SECTIONTYPE_0 = 0, /**< Unused RB or Symbols in DL or UL, not supported */ + XRAN_CP_SECTIONTYPE_1 = 1, /**< Most DL/UL Radio Channels */ + XRAN_CP_SECTIONTYPE_3 = 3, /**< PRACH and Mixed-numerology Channels */ + XRAN_CP_SECTIONTYPE_5 = 5, /**< UE scheduling information, not supported */ + XRAN_CP_SECTIONTYPE_6 = 6, /**< Channel Information, not supported */ + XRAN_CP_SECTIONTYPE_7 = 7, /**< LAA, not supported */ + XRAN_CP_SECTIONTYPE_MAX + }; + +/** Filter index, defined in 5.4.4.3 */ +enum xran_cp_filterindex { + XRAN_FILTERINDEX_STANDARD = 0, /**< UL filter for standard channel */ + XRAN_FILTERINDEX_PRACH_012 = 1, /**< UL filter for PRACH preamble format 0, 1, 2 */ + XRAN_FILTERINDEX_PRACH_3 = 2, /**< UL filter for PRACH preamble format 3 */ + XRAN_FILTERINDEX_PRACH_ABC = 3, /**< UL filter for PRACH preamble format A1~3, B1~4, C0, C2 */ + XRAN_FILTERINDEX_NPRACH = 4, /**< UL filter for NPRACH */ + XRAN_FILTERINDEX_MAX + }; + +/** Maximum Slot Index, defined in 5.4.4.6 */ +#define XRAN_SLOTID_MAX 16 + +/** FFT size in frame structure, defined in 5.4.4.13 Table 5.9 */ +enum xran_cp_fftsize { + XRAN_FFTSIZE_128 = 7, /* 128 */ + XRAN_FFTSIZE_256 = 8, /* 256 */ + XRAN_FFTSIZE_512 = 9, /* 512 */ + XRAN_FFTSIZE_1024 = 10, /* 1024 */ + XRAN_FFTSIZE_2048 = 11, /* 2048 */ + XRAN_FFTSIZE_4096 = 12, /* 4096 */ + XRAN_FFTSIZE_1536 = 13, /* 1536 */ + XRAN_FFTSIZE_MAX + }; + +/** Sub-carrier spacing, defined in 5.4.4.13 Table 5.10 */ +enum xran_cp_subcarrierspacing { /*3GPP u, SCS, Nslot, Slot len */ + XRAN_SCS_15KHZ = 0, /* 0, 15kHz, 1, 1ms */ + XRAN_SCS_30KHZ = 1, /* 1, 30kHz, 2, 500us */ + XRAN_SCS_60KHZ = 2, /* 2, 60kHz, 4, 250us */ + XRAN_SCS_120KHZ = 3, /* 3, 120kHz, 8, 125us */ + XRAN_SCS_240KHZ = 4, /* 4, 240kHz, 16, 62.5us */ + XRAN_SCS_1P25KHZ = 12, /* NA, 1.25kHz, 1, 1ms */ + XRAN_SCS_3P75KHZ = 13, /* NA, 3.75kHz, 1, 1ms */ + XRAN_SCS_5KHZ = 14, /* NA, 5kHz, 1, 1ms */ + XRAN_SCS_7P5KHZ = 15, /* NA, 7.5kHz, 1, 1ms */ + XRAN_SCS_MAX + }; + +/** Resource block indicator, defined in 5.4.5.2 */ +enum xran_cp_rbindicator { + XRAN_RBIND_EVERY = 0, /**< every RB used */ + XRAN_RBIND_EVERYOTHER = 1, /**< every other RB used */ + XRAN_RBIND_MAX + }; + +/** Symbol number increment command, defined in 5.4.5.3 */ +enum xran_cp_symbolnuminc { + XRAN_SYMBOLNUMBER_NOTINC = 0, /**< do not increment the current symbol number */ + XRAN_SYMBOLNUMBER_INC = 1, /**< increment the current symbol number and use that */ + XRAN_SYMBOLNUMBER_INC_MAX + }; + +/** Minimum number of symbols, defined in 5.4.5.7 */ +#define XRAN_SYMBOLNUMBER_MIN 1 +/** Maximum number of symbols, defined in 5.4.5.7 */ +#define XRAN_SYMBOLNUMBER_MAX 14 + +/* LAA message type 5.4.5.14 Table 5.11, not supported */ +#define XRAN_LAAMSGTYPE_LBT_PDSCH_REQ 0 +#define XRAN_LAAMSGTYPE_LBT_DRS_REQ 1 +#define XRAN_LAAMSGTYPE_LBT_PDSCH_RSP 2 +#define XRAN_LAAMSGTYPE_LBT_DRS_RSP 3 +#define XRAN_LAAMSGTYPE_LBT_BUFFER_ERROR 4 +#define XRAN_LAAMSGTYPE_LBT_CWCONFIG_REQ 5 +#define XRAN_LAAMSGTYPE_LBT_CWCONFIG_RSP 6 + +#define XRAN_LBTMODE_FULL 0 +#define XRAN_LBTMODE_PARTIAL25 1 +#define XRAN_LBTMODE_PARTIAL34 2 +#define XRAN_LBTMODE_FULLSTOP 3 + +/** + * This structure contains the information to generate the section body of C-Plane message */ +struct xran_section_info { + /* section type bit- */ + /* 0 1 3 5 6 7 length */ + uint16_t id; /* X X X X X 12bits */ + uint8_t rb; /* X X X X X 1bit */ + uint8_t symInc; /* X X X X X 1bit */ + uint16_t startPrbc; /* X X X X X 10bits */ + uint8_t numPrbc; /* X X X X X 8bits */ + uint8_t numSymbol; /* X X X X 4bits */ + uint16_t reMask; /* X X X X 12bits */ + uint16_t beamId; /* X X 15bits */ + uint16_t ueId; /* X X 15bits */ + uint16_t regFactor; /* X 16bits */ + int32_t freqOffset; /* X 24bits */ + uint8_t ef; /* X X X X 1bit */ + + uint8_t type; /* type of this section */ + uint16_t pad0; + }; + +/** + * This structure contains the information to generate the section header of C-Plane message */ +struct xran_cp_header_params { + // common parameters + uint8_t filterIdx; + uint8_t frameId; + uint8_t subframeId; + uint8_t slotId; + uint8_t startSymId; + /* section type bit- */ + /* 0 1 3 5 6 7 length */ + uint8_t fftSize; /* X X 4bits */ + uint8_t scs; /* X X 4bits */ + uint8_t iqWidth; /* X X X 4bits */ + uint8_t compMeth; /* X X X 4bits */ + uint8_t numUEs; /* X 8bits */ + uint16_t timeOffset; /* X X 16bits */ + uint16_t cpLength; /* X X 16bits */ + }; + +/** + * This structure to hold the information to generate the sections of C-Plane message */ +struct xran_section_gen_info { + struct xran_section_info info; /**< The information for section */ + + uint32_t exDataSize; + /**< Extension or type 6/7 data size, not supported */ + void *exData; + /*(< The pointer to the extension or type 6/7 data, not supported */ + }; + +/** + * This structure to hold the information to generate a C-Plane message */ +struct xran_cp_gen_params { + uint8_t dir; /**< UL or DL */ + uint8_t sectionType; /**< each section must have same type with this */ + uint16_t numSections; /**< the number of sections to generate */ + + struct xran_cp_header_params hdr; + /**< The information for C-Plane message header */ + struct xran_section_gen_info *sections; + /**< Array of the section information */ + }; + + +uint16_t xran_get_cplength(int cpLength, int uval); +int32_t xran_get_freqoffset(int freqOffset, int scs); + +int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf, + struct xran_cp_gen_params *params, + uint8_t CC_ID, uint8_t Ant_ID, + uint8_t seq_id); + +int xran_cp_init_sectiondb(void *pHandle); +int xran_cp_free_sectiondb(void *pHandle); +int xran_cp_add_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + struct xran_section_info *info); +struct xran_section_info *xran_cp_find_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + uint16_t section_id); +struct xran_section_info *xran_cp_iterate_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, uint32_t *next); +int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id); +int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id); + +#endif /* _XRAN_CP_API_H_ */ diff --git a/fhi_lib/lib/api/xran_fh_lls_cu.h b/fhi_lib/lib/api/xran_fh_lls_cu.h new file mode 100644 index 0000000..24bacba --- /dev/null +++ b/fhi_lib/lib/api/xran_fh_lls_cu.h @@ -0,0 +1,822 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides public interface to XRAN Front Haul layer implementation as defined in the + * XRAN-FH.CUS.0-v02.00 spec. Implementation is specific to lls-CU node + * for 5G NR Radio Access technology + * + * @file xran_fh_lls_cu.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_FH_LLS_CU_H_ +#define _XRAN_FH_LLS_CU_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XRAN_STATUS_SUCCESS (0) +/**< + * @ingroup xran + * Success status value. */ +#define XRAN_STATUS_FAIL (-1) +/**< + * @ingroup xran + * Fail status value. */ + +#define XRAN_STATUS_RETRY (-2) +/**< + * @ingroup xran + * Retry status value. */ + +#define XRAN_STATUS_RESOURCE (-3) +/**< + * @ingroup xran + * The resource that has been requested is unavailable. Refer + * to relevant sections of the API for specifics on what the suggested + * course of action is. */ + +#define XRAN_STATUS_INVALID_PARAM (-4) +/**< + * @ingroup xran + * Invalid parameter has been passed in. */ +#define XRAN_STATUS_FATAL (-5) +/**< + * @ingroup xran + * A serious error has occurred. Recommended course of action + * is to shutdown and restart the component. */ + +#define XRAN_STATUS_UNSUPPORTED (-6) +/**< + * @ingroup xran + * The function is not supported, at least not with the specific + * parameters supplied. This may be because a particular + * capability is not supported by the current implementation. */ + +/** Macro to calculate TTI number [0:7999] from symbol index [0: 112000-1] used by timing thread */ +#define XranGetTtiNum(symIdx, numSymPerTti) (((uint32_t)symIdx / (uint32_t)numSymPerTti)) +/** Macro to calculate Symbol number [0:7] for given slot from symbol index [0: 112000-1] */ +#define XranGetSymNum(symIdx, numSymPerTti) (((uint32_t)symIdx % (uint32_t)numSymPerTti)) +/** Macro to calculate Frame number [0:99] for given tti [0: 7999] */ +#define XranGetFrameNum(tti,numSubFramePerSystemFrame, numSlotPerSubFrame) ((uint32_t)tti / ((uint32_t)numSubFramePerSystemFrame * (uint32_t)numSlotPerSubFrame)) +/** Macro to calculate Subframe number [0:9] for given tti [0: 7999] */ +#define XranGetSubFrameNum(tti, numSlotPerSubFrame, numSubFramePerSystemFrame) (((uint32_t)tti/(uint32_t)numSlotPerSubFrame) % (uint32_t)numSubFramePerSystemFrame) +/** Macro to calculate Slot number [0:7] for given tti [0: 7999] */ +#define XranGetSlotNum(tti, numSlotPerSfn) ((uint32_t)tti % ((uint32_t)numSlotPerSfn)) + +#define XRAN_PORTS_NUM (1) /**< number of XRAN ports supported */ +#define XRAN_N_FE_BUF_LEN (80)/** Number of TTIs (slots) */ +#define XRAN_MAX_SECTOR_NR (4) /**< Max sectors per XRAN port */ +#define XRAN_MAX_ANTENNA_NR (4) /**< Max antenna per port */ +#define XRAN_NUM_OF_SYMBOL_PER_SLOT ( 14 ) /**< Number of symbols per slot */ + +#define XRAN_MAX_CELLS_PER_PORT (4) /**< Max cells mapped to XRAN port */ +#define XRAN_COMPONENT_CARRIERS_MAX XRAN_MAX_SECTOR_NR /**< number of CCs */ +#define XRAN_NUM_OF_ANT_RADIO 16 /**< Max Number of Antennas supported for all CC on single XRAN port */ + +#define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ +#define XRAN_N_MAX_BUFFER_SEGMENT XRAN_MAX_PKT_BURST /**< Max number of segments per ms */ + +#define XRAN_STRICT_PARM_CHECK (1) /**< enable parameter check for C-plane */ + +//#define _XRAN_DEBUG /**< Enable debug log */ +//#define _XRAN_VERBOSE /**< Enable verbose log */ + +#ifdef _XRAN_DEBUG + #define xran_log_dbg(fmt, ...) \ + fprintf(stderr, \ + "DEBUG: %s(%d): " fmt "\n", \ + __FILE__, \ + __LINE__, ##__VA_ARGS__) +#else + #define xran_log_dbg(fmt, ...) +#endif + +#if defined(_XRAN_DEBUG) || defined(_XRAN_VERBOSE) + #define xran_log_wrn(fmt, ...) \ + fprintf( \ + stderr, \ + "WARNING: %s(%d): " fmt "\n", \ + __FILE__, \ + __LINE__, ##__VA_ARGS__) +#else + #define xran_log_dbg(fmt, ...) + #define xran_log_wrn(fmt, ...) +#endif + +#define xran_log_err(fmt, ...) \ + fprintf(stderr, \ + "ERROR: %s(%d): " fmt "\n", \ + __FILE__, \ + __LINE__, ##__VA_ARGS__) + +/** + ****************************************************************************** + * @ingroup xran + * + * @description + * Compression Method 6.3.3.13, Table 6-43 + *****************************************************************************/ +enum xran_compression_method { + XRAN_COMPMETHOD_NONE = 0, + XRAN_COMPMETHOD_BLKFLOAT = 1, + XRAN_COMPMETHOD_BLKSCALE = 2, + XRAN_COMPMETHOD_ULAW = 3, + XRAN_COMPMETHOD_MODULATION = 4, + XRAN_COMPMETHOD_MAX + }; + +/** + ****************************************************************************** + * @ingroup xran + * + * @description + * Callback function type for symbol packet enum + *****************************************************************************/ +enum callback_to_phy_id +{ + XRAN_CB_TTI = 0, /**< callback on TTI boundary */ + XRAN_CB_HALF_SLOT_RX =1, /**< callback on half slot (sym 7) packet arrival*/ + XRAN_CB_FULL_SLOT_RX =2, /**< callback on full slot (sym 14) packet arrival */ + XRAN_CB_MAX /**< max number of callbacks */ +}; + +typedef int32_t XranStatusInt32; /**< Xran status return value */ + +/** callback function type for Symbol packet */ +typedef void (*XRANFHSYMPROCCB)(void*); + +/** Callback function type for TTI event */ +typedef int (*XRANFHTTIPROCCB)(void* ); + +/** Callback function type packet arrival from transport layer (ETH or IP) */ +typedef void (*XranTransportBlockCallbackFn)(void*, int32_t); + +/** +* Component Carrier Initialization +*/ +typedef struct tagXRANCCINIT +{ + uint32_t RadioMode; /**< XRAN mode Cat A or Cat B on given CC */ + uint32_t nTxAnt; /**< Number of TX antennas */ + uint32_t nRxAnt; /**< Number of RX antennas */ + uint32_t radiobw; /**< bandwidth id */ + uint32_t dpdk_port; /**< networking layer port id */ + char *dpdk_pcie_eth_dev; /**< pcie device for this cc */ + char *ru_mac_str; /**< mac address of RU */ + uint32_t ulAgc; /**< state of UL AGC (ON/OFF) */ + uint32_t numCell; /**< Number of Cells per port per CC */ + uint32_t phyInsId[XRAN_MAX_CELLS_PER_PORT]; /**< Mapping of Cell ID to CC */ + uint32_t dpdkRxCore; /**< DPDK RX Core */ + uint32_t dpdkTxCore; /**< DPDK TX Core */ +}XRANCCINIT, *PXRANCCINIT; + +/** XRAN port enum */ +enum xran_vf_ports +{ + XRAN_UP_VF = 0, /**< port type for U-plane */ + XRAN_CP_VF, /**< port type for C-plane */ + XRAN_VF_MAX +}; + +/** DPDK IO configuration for XRAN layer */ +typedef struct tagXRAN_IO_LOOP_CFG +{ + uint8_t id; + char *dpdk_dev[XRAN_VF_MAX]; + int core; + int system_core; /* Needed as DPDK will change your starting core. */ + int pkt_proc_core; /* Needed for packet processing thread. */ + int pkt_aux_core; /* Needed for debug purposes. */ + int timing_core; /* Needed for getting precise time */ + int port[XRAN_VF_MAX]; /* This is auto-detected, no need to set. */ +}XRAN_IO_LOOP_CFG, *PXRAN_IO_LOOP_CFG; + +/** XRAN spec section 3.1.3.1.6 ecpriRtcid / ecpriPcid define */ +typedef struct tagXRANEAXCIDCONFIG +{ + uint16_t mask_cuPortId; /**< Mask CU PortId */ + uint16_t mask_bandSectorId; /**< Mask Band */ + uint16_t mask_ccId; /**< Mask CC */ + uint16_t mask_ruPortId; /**< Mask RU Port ID */ + + uint8_t bit_cuPortId; /**< bandsectorId + ccId + ruportId */ + uint8_t bit_bandSectorId; /**< ccId + ruPortId */ + uint8_t bit_ccId; /**< ruportId */ + uint8_t bit_ruPortId; /**< 0 */ +}XRANEAXCIDCONFIG, *PXRANEAXCIDCONFIG; + +/** +* XRAN Front haul interface initialization settings +*/ +typedef struct tagXRANFHINIT +{ + uint32_t llscuId; /**< lls-cu ID */ + uint32_t nSec; /**< number of sectors, shall be 1 */ + XRANCCINIT ccCfg[XRAN_COMPONENT_CARRIERS_MAX]; /**< configuration of each CCs */ + XRANEAXCIDCONFIG eAxCId_conf; /**< config of ecpriRtcid/ecpriPcid */ + uint32_t radio_iface; /**< enable/disable radio */ + uint32_t dpdkMasterCore; /**< master core of DPDK */ + uint32_t dpdkMemorySize; /**< huge pages allocation for DPDK */ + uint32_t dpdkIrqMode; /**< DPDK IRQ or PMD mode */ + uint32_t dpdkBasebandFecMode; /**< DPDK Baseband FEC device mode (0-SW, 1-HW) */ + char *dpdkBasebandDevice; /**< DPDK Baseband device address */ + uint32_t singleThreadTxRx; + uint32_t bbuPoolCores; /**< DPDK cores for BBU pool */ + uint32_t radioEnabled; /**< reserved */ + uint32_t powerSaveEn; /**< reserved */ + char *filePrefix; /**< DPDK prefix */ + XRAN_IO_LOOP_CFG io_cfg;/**< DPDK IO for XRAN */ + uint8_t xranMode; /**< mode: lls-CU or RU */ + int8_t *p_lls_cu_addr; /**< lls-CU Ethernet Mac Address */ + int8_t *p_ru_addr; /**< RU Ethernet Mac Address */ + uint32_t ttiPeriod; /**< TTI period */ + + uint16_t Tadv_cp_dl; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_min_cp_dl; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_max_cp_dl; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_min_cp_ul; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_max_cp_ul; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_min_up; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T2a_max_up; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t Ta3_min; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t Ta3_max; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_min_cp_dl; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_max_cp_dl; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_min_cp_ul; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_max_cp_ul; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_min_up; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t T1a_max_up; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t Ta4_min; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + uint16_t Ta4_max; /**< Table 2 7 : xRAN Delay Management Model Parameters */ + + uint8_t enableCP; /**< enable C-plane */ + uint8_t cp_vlan_tag; /**< C-plane vlan tag */ + uint8_t up_vlan_tag; /**< U-plane vlan tag */ + int32_t debugStop; /**< enable auto stop */ +} XRANFHINIT, *PXRANFHINIT; + +/** XRAN Playback format */ +typedef enum { + XRAN_RADIO_PLAYBACK_TIME_DOMAIN = 0, + XRAN_RADIO_PLAYBACK_FREQ_DOMAIN = 1 +} XranPlaybackFormatEnum; + +/* PRACH config required for XRAN based FH */ +typedef struct tagXRANPRACHCONFIG +{ + /**** word 5 *****/ + /* PRACH config*/ + /** PRACH Configuration Index*/ + uint8_t nPrachConfIdx; + /** PRACH Sub-carrier spacing + Value:0->1 + For below 6GHz the values indicate 15kHz or 30kHz + For above 6GHz the values indicate 60kHz or 120kHz*/ + /*PRACH zeroCorrelationZoneConfig */ + uint8_t nPrachSubcSpacing; + /** PRACH zeroCorrelationZoneConfig */ + uint8_t nPrachZeroCorrConf; + /** PRACH restrictedSetConfig */ + uint8_t nPrachRestrictSet; + + /**** word 6 *****/ + /** PRACH Root Sequence Index */ + uint16_t nPrachRootSeqIdx; + /** PRACH prach-frequency-start */ + uint16_t nPrachFreqStart; + + /** PRACH prach-frequency-offset */ + int32_t nPrachFreqOffset; + /** PRACH Filter index */ + uint8_t nPrachFilterIdx; +}XRANPRACHCONFIG, *PXRANPRACHCONFIG; + +/** XRAN front haul playback configuration (not supported in 19.03) */ +typedef struct tagXRANFHPLAYBACK +{ + XranPlaybackFormatEnum TxPlayFormatType; /**< type of play back files [Time|Freq] */ + + unsigned long TxPlayBufAddr[XRAN_NUM_OF_ANT_RADIO]; /**< pointer to buffers to play */ + uint32_t TxPlayBufSize; /**< Buffer size */ + + char* TxPlayFileName[XRAN_NUM_OF_ANT_RADIO]; /**< files to play */ + uint32_t TxPlayFileSize; /**< expected the same size for all Ant */ + +}XRANPLAYBACKCONFIG,*PXRANPLAYBACKCONFIG; + +/** XRAN front haul logging configuration (not supported in 19.03) */ +typedef struct tagXRANFHLOGCONF +{ + /* logging */ + unsigned long TxLogBufAddr; + uint32_t TxLogBufSize; + + unsigned long TxLogIfftInAddr; + uint32_t TxLogIfftInSize; + + unsigned long TxLogIfft1200InAddr; + uint32_t TxLogIfft1200InSize; + + unsigned long RxLogFftOutAddr; + uint32_t RxLogFftOutSize; + + unsigned long RxLogFftOutExpAddr; + uint32_t RxLogFftOutExpSize; + + unsigned long RxLogFftOutGainAddr; + uint32_t RxLogFftOutGainSize; + + unsigned long RxLogBufAddr; + uint32_t RxLogBufSize; + + unsigned long RxLogAlawBufAddr; + uint32_t RxLogAlawBufSize; + + unsigned long RxLogPrachBufAddr; + uint32_t RxLogPrachBufSize; + + uint32_t cfg_dl_iq_buf_enabled; + uint32_t cfg_ul_iq_buf_enabled; + +}XRANFHLOGCONF, *PXRANFHLOGCONF; + +/** XRAN front haul frame config */ +typedef struct tagXRANFRAMECONFIG +{ + /** Frame Duplex type: 0 -> FDD, 1 -> TDD */ + uint8_t nFrameDuplexType; + /** Numerology, determine sub carrier spacing, Value: 0->4 + 0: 15khz, 1: 30khz, 2: 60khz + 3: 120khz, 4: 240khz */ + uint8_t nNumerology; + /** TDD period */ + uint8_t nTddPeriod; +}XRANFRAMECONFIG, *PXRANFRAMECONFIG; + +/** XRAN front haul BBU pooling config */ +typedef struct tagXRANBBUPOOLCONFIG +{ + uint32_t isBbuPool; /**< FH running with BBU pool */ +}XRANBBUPOOLCONFIG, *PXRANBBUPOOLCONFIG; + +/** XRAN front haul IQ compression settings */ +typedef struct tagXRANRUCONFIG +{ + uint8_t iqWidth; /**< IQ bit width */ + uint8_t compMeth; /**< Compression method */ + uint8_t fftSize; /**< FFT Size */ +}XRANRUCONFIG, *PXRANRUCONFIG; + +/** XRAN front haul Phase compensation settings */ +typedef struct +{ + uint32_t nSecNum; + uint32_t nPhaseCompFlag; + uint32_t nDlArfcn[XRAN_MAX_SECTOR_NR]; + uint32_t nUlArfcn[XRAN_MAX_SECTOR_NR]; +}XRANPHASECompConfig; + +/** + * @ingroup xran + *XRAN front haul general configuration */ +typedef struct tagXRANFHCONFIG +{ + uint32_t dpdk_port; /**< DPDK port number used for FH */ + uint32_t sector_id; /**< Band sector ID for FH */ + uint32_t nCC; /**< number of Component carriers supported on FH */ + uint32_t neAxc; /**< number of eAxc supported on FH */ + XRANPLAYBACKCONFIG playback_conf;/**< configuration of playback of IQs supported with FH */ + XRANFHLOGCONF log_conf; /**< config of logging functionality supported by FH */ + XRANFHTTIPROCCB ttiCb; /**< call back for TTI event */ + void *ttiCbParam; /**< parameters of call back function */ + XRANPRACHCONFIG prach_conf; /**< PRACH specific configurations for FH */ + XRANFRAMECONFIG frame_conf; /**< frame config */ + XRANBBUPOOLCONFIG bbu_conf; /**< BBU pool config */ + XRANRUCONFIG ru_conf; /**< config of RU as per XRAN spec */ + XRANPHASECompConfig phase_compensation; /**< phase compensation settings */ +}XRANFHCONFIG, *PXRANFHCONFIG; + + +/** + * @ingroup xran + * CC instance handle pointer type */ +typedef void * XranCcInstanceHandleVoidP; + +/** + ***************************************************************************** + * @ingroup xran + * + * @description + * A flat buffer structure. The data pointer, pData, is a virtual address. + * The API requires the memory to by physically contiguous. Each flat + * buffer segment may contain several equally sized elements. + * + *****************************************************************************/ +typedef struct XRANFlatBuffer +{ + uint32_t nElementLenInBytes; + /**< The Element length specified in bytes. + * This parameter specifies the size of a single element in the buffer. + * The total size of the buffer is described as + * bufferSize = nElementLenInBytes * nNumberOfElements */ + uint32_t nNumberOfElements; + /**< The number of elements in the physical contiguous memory segment */ + uint32_t nOffsetInBytes; + /**< Offset in bytes to the start of the data in the physical contiguous + * memory segment */ + uint32_t nIsPhyAddr; + uint8_t *pData; + /**< The data pointer is a virtual address, however the actual data pointed + * to is required to be in contiguous physical memory unless the field + requiresPhysicallyContiguousMemory in CpaInstanceInfo is false. */ +} XRANFlatBufferStruct; + +/** + ***************************************************************************** + * @ingroup xran + * Scatter/Gather buffer list containing an array of Simple buffers. + * + * @description + * A Scatter/Gather buffer list structure. It is expected that this buffer + * structure will be used where more than one flat buffer can be provided + * on a particular API. + * + * IMPORTANT - The memory for the pPrivateMetaData member must be allocated + * by the client as contiguous memory. When allocating memory for + * pPrivateMetaData a call to cpaCyBufferListGetMetaSize MUST be made to + * determine the size of the Meta Data Buffer. The returned size + * (in bytes) may then be passed in a memory allocation routine to allocate + * the pPrivateMetaData memory. + * + *****************************************************************************/ +typedef struct XRANBufferList +{ + uint32_t nNumBuffers; + /**< Number of pointers */ + XRANFlatBufferStruct *pBuffers; + /**< Pointer to an unbounded array containing the number of CpaFlatBuffers + * defined by nNumBuffers */ + void *pUserData; + /**< This is an opaque field that is not read or modified internally. */ + void *pPrivateMetaData; + /**< Private Meta representation of this buffer List - the memory for this + * buffer needs to be allocated by the client as contiguous data. + * The amount of memory required is returned with a call to + * cpaCyBufferListGetMetaSize. If cpaCyBufferListGetMetaSize returns a size + * of zero no memory needs to be allocated, and this parameter can be NULL. + */ +} XRANBufferListStruct; + +/** + * @ingroup xran + * Initialize the XRAN Layer via DPDK. + * + * @param argc + * A non-negative value. If it is greater than 0, the array members + * for argv[0] through argv[argc] (non-inclusive) shall contain pointers + * to strings. + * @param argv + * An array of strings. The contents of the array, as well as the strings + * which are pointed to by the array, may be modified by this function. + * + * @return + * 0 - on success + * Error codes returned via rte_errno + */ +int32_t xran_init(int argc, char *argv[], PXRANFHINIT p_xran_fh_init, char *appName, void ** pHandle); + +/** + * @ingroup xran + * + * Function returns handles for number of sectors supported by XRAN layer. Currently function + * supports one handle XRAN layer where it supports only one CC + * + * @param pHandle + * Pointer to XRAN layer handle + * @param nNumInstances + * total number of instances of CC + * @param pSectorInstanceHandles + * Pointer to XranCcInstanceHandleVoidP where to store Handle pointer + * + * @return + * 0 - on success + */ +int32_t xran_sector_get_instances (void * pHandle, uint16_t nNumInstances, + XranCcInstanceHandleVoidP * pSectorInstanceHandles); + +/** + * @ingroup xran + * + * Function initialize Memory Management subsystem (mm) in order to handle memory buffers between XRAN layer + * and PHY. + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param nMemorySize + * memory size of all segments + * @param nMemorySegmentSize + * size of memory per segment + * + * @return + * 0 - on success + */ +int32_t xran_mm_init (void * pHandle, uint64_t nMemorySize, uint32_t nMemorySegmentSize); + +/** + * @ingroup xran + * + * Function allocates buffer memory (bm) used between XRAN layer and PHY. In general case it's DPDK mbuf. + * it uses Memory Management system to get memory chunk and define memory pool on top of it. + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param nPoolIndex + * pointer to buffer pool identification to be returned + * @param nNumberOfBuffers + * number of buffer to allocate in the pool + * @param nBufferSize + * buffer size to allocate + * + * @return + * 0 - on success + */ +int32_t xran_bm_init (void * pHandle, uint32_t * pPoolIndex, uint32_t nNumberOfBuffers, uint32_t nBufferSize); + +/** + * @ingroup xran + * + * Function allocates buffer used between XRAN layer and PHY. In general case it's DPDK mbuf. + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param nPoolIndex + * buffer pool identification + * @param ppVirtAddr + * Pointer to pointer where to store address of new buffer + * + * @return + * 0 - on success + */ +int32_t xran_bm_allocate_buffer(void * pHandle, uint32_t nPoolIndex, void **ppVirtAddr); + +/** + * @ingroup xran + * + * Function frees buffer used between XRAN layer and PHY. In general case it's DPDK mbuf + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param pVirtAddr + * Pointer to buffer + * + * @return + * 0 - on success + */ +int32_t xran_bm_free_buffer(void * pHandle, void *pVirtAddr); + +/** + * @ingroup xran + * + * Function destroys Memory Management (MM) layer of XRAN library + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * + * @return + * 0 - on success + */ +int32_t xran_mm_destroy (void * pHandle); + +/** + * @ingroup xran + * + * Function configures TX(DL) and RX(UL) output buffers and callback (UL only) for XRAN layer with + * given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param pSrcBuffer + * list of memory buffers to use to fetch IQs from PHY to XRAN layer (DL) + * @param pDstBuffer + * list of memory buffers to use to deliver IQs from XRAN layer to PHY (UL) + * @param XranTransportBlockCallbackFn pCallback + * Callback function to call with arrival of all packets for given CC for given symbol + * @param pCallbackTag + * Parameters of Callback function + * + * @return + * 0 - on success + * -1 - on error + */ +int32_t xran_5g_fronthault_config (void * pHandle, + XRANBufferListStruct *pSrcBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XranTransportBlockCallbackFn pCallback, + void *pCallbackTag); + +/** + * @ingroup xran + * + * Function configures PRACH output buffers and callback for XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param pDstBuffer + * list of memory buffers to use to deliver PRACH IQs from xran layer to PHY + * @param XranTransportBlockCallbackFn pCallback + * Callback function to call with arrival of PRACH packets for given CC + * @param pCallbackTag + * Parameters of Callback function + * + * @return + * 0 - on success + * -1 - on error + */ +int32_t xran_5g_prach_req (void * pHandle, + XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XranTransportBlockCallbackFn pCallback, + void *pCallbackTag); +/** + * @ingroup xran + * + * Function configures phase compensation for RU via XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param nTxPhaseCps + * TX(DL) phase compensation settings + * @param nTxPhaseCps + * RX(UL) phase compensation settings + * @param nSectorId + * Sector id to use with given settings + * + * @return + * 0 - on success + */ +int32_t xran_5g_pre_compenstor_cfg(void* pHandle, + uint32_t nTxPhaseCps, + uint32_t nRxPhaseCps, + uint8_t nSectorId); + +/** + * @ingroup xran + * + * Function opens XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param PXRANFHCONFIG pConf + * Pointer to XRAN configuration structure with specific settings to use + * + * @return + * 0 - on success + */ +int32_t xran_open(void *pHandle, PXRANFHCONFIG pConf); + +/** + * @ingroup xran + * + * Function starts XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * + * @return + * 0 - on success + */ +int32_t xran_start(void *pHandle); + +/** + * @ingroup xran + * + * Function stops XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * + * @return + * 0 - on success + */ +int32_t xran_stop(void *pHandle); + +/** + * @ingroup xran + * + * Function closes XRAN layer with given handle + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * + * @return + * 0 - on success + */ +int32_t xran_close(void *pHandle); + +/** + * @ingroup xran + * + * Function registers callback to XRAN layer. Function support callbacks aligned on packet arrival. + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param symCb + * pointer to callback function + * @param symCb + * pointer to Callback Function parameters + * @param symb + * symbol to be register for + * @param ant + * Antenna number to trigger callback for packet arrival + * + * @return + * 0 - in case of success + * -1 - in case of failure + */ +int32_t xran_reg_sym_cb(void *pHandle, XRANFHSYMPROCCB symCb, void * symCbParam, uint8_t symb, uint8_t ant); + +/** + * @ingroup xran + * + * Function registers callback to XRAN layer. Function support callbacks align to OTA time. TTI even, half of slot, + * full slot with respect to PTP time. + * + * @param pHandle + * Pointer to XRAN layer handle for given CC + * @param Cb + * pointer to callback function + * @param cbParam + * pointer to Callback Function parameters + * @param skipTtiNum + * number of calls to be skipped before first call + * @param callback_to_phy_id + * call back time identification (see enum callback_to_phy_id) + * + * @return + * 0 - in case of success + * -1 - in case of failure + */ +int32_t xran_reg_physide_cb(void *pHandle, XRANFHTTIPROCCB Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id); + +/** + * @ingroup xran + * + * Function returns current TTI, Frame, Subframe, Slot Number as seen "Over air" base on PTP time + * + * @param nFrameIdx + * Pointer to Frame number [0-99] + * + * @param nSubframeIdx + * Pointer to Subframe number [0-10] + * + * @param nSlotIdx + * Pointer to Slot number [0-7] + * + * @param nSecond + * Pointer to current UTC second + * + * @return + * current TTI number [0-7999] + */ +int32_t xran_get_slot_idx (uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); + +#ifdef __cplusplus +} +#endif + +#endif /* _XRAN_FH_LLS_CU_H_*/ diff --git a/fhi_lib/lib/api/xran_pkt.h b/fhi_lib/lib/api/xran_pkt.h new file mode 100644 index 0000000..112ea41 --- /dev/null +++ b/fhi_lib/lib/api/xran_pkt.h @@ -0,0 +1,261 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief Definitions and support functions to process XRAN packet + * @file xran_pkt.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +/* XRAN-FH.CUS.0-v02.01.03 xRAN Front haul Working Group Control, User and Synchronization Plane Specification */ + +/* + * Layer common to data and control packets + */ + +#ifndef _XRAN_PKT_H_ +#define _XRAN_PKT_H_ + +#include +#include +#include + + +/** + ***************************************************************************** + * @file xran_pkt.h + * + * @defgroup xran_common_pkt XRAN Packet definitions and functions + * @ingroup xran + * + * @description + * Definitions and support functions to process XRAN packet + *****************************************************************************/ + +#define ECPRI_MAX_PAYLOAD_SIZE 65535 /**< Max packet size taken in this implementation */ + +/* XRAN spec: For this encapsulation, either the eCPRI Ethertype or the IEEE 1914.3 Ethertype shall be use */ +#define XRAN_ETHER_TYPE 0xAEFE /**< defined by eCPRI Specification V1.1 */ + +#define XRAN_ECPRI_VER 0x0001 /**< eCPRI protocol revision 3.1.3.1.1 */ +#define XRAN_PAYLOAD_VER 0x0001 /**< Payload version 5.4.4.2 */ + +#define VLAN_ID 0 /**< Default Tag protocol identifier (TPID)*/ +#define VLAN_PCP 7 /**< U-Plane and C-Plane only see Table 3 5 : Quality of service classes */ + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * eCPRI message types + * as per eCPRI spec 3.2.4. Message Types + *****************************************************************************/ +enum ecpri_msg_type +{ + ECPRI_IQ_DATA = 0x00, /**< U-plane: IQ data */ + ECPRI_BIT_SEQUENCE = 0x01, /* msg type is not supported */ + ECPRI_RT_CONTROL_DATA = 0x02, /**< C-plane: Control */ + + /* Below msg types are not supported */ + ECPRI_GEN_DATA_TRANSFER = 0x03, + ECPRI_REMOTE_MEM_ACCESS = 0x04, + ECPRI_DELAY_MEASUREMENT = 0x05, + ECPRI_REMOTE_RESET = 0x06, + ECPRI_EVENT_INDICATION = 0x07, + ECPRI_MSG_TYPE_MAX +}; + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * see 3.1.3.1.7 ecpriSeqid (message identifier) + *****************************************************************************/ +struct ecpri_seq_id +{ + uint8_t seq_id:8; /**< Sequence ID */ + uint8_t sub_seq_id:7; /**< Subsequence ID */ + uint8_t e_bit:1; /**< E bit */ +} __rte_packed; + + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * Structure holds common eCPRI header as per + * Table 3 1 : eCPRI Transport Header Field Definitions + *****************************************************************************/ +struct xran_ecpri_hdr +{ + uint8_t ecpri_concat:1; /**< This parameter indicates when eCPRI concatenation is in use + (allowing multiple eCPRI messages in a single Ethernet payload). + NOTE: This parameter is part of the eCPRI common header. */ + uint8_t ecpri_resv:3; /**< This parameter is reserved for eCPRI future use. + NOTE: This parameter is part of the eCPRI common header. */ + uint8_t ecpri_ver:4; /**< This parameter indicates the eCPRI protocol version. + NOTE: This parameter is part of the eCPRI common header. */ + uint8_t ecpri_mesg_type:8; /**< This parameter indicates the type of service conveyed by + the message type. NOTE: This parameter is part of the eCPRI + common header. NOTE: In this version of the specification, + only values "0000 0000b" and "0000 0010b" and "0000 0101b" are used. */ + rte_be16_t ecpri_payl_size:16; /**< This parameter is the size in bytes of the payload part + of the corresponding eCPRI message. It does not include any padding bytes + following the eCPRI message. The maximum supported payload size is 216-1, + but the actual size may be further limited by the maximum payload size of + the underlying transport network. NOTE: This parameter is part of the + eCPRI common header. */ + + rte_be16_t ecpri_xtc_id; /**< 3.1.3.1.6 This parameter is a component_eAxC identifier (c_eAxC ID) and + identifies the specific data flow associated with each C-Plane (ecpriRtcid) or + U-Plane (ecpriPcid) message. It is the analog of CPRI's "AxC" (antenna-carrier) + value so is designated here as "eAxC" ("e" for "extended" to accommodate multiple + bands and multiple component carriers). In addition, the "eAxC" is divided into + "component eAxC" parts (c_eAxC) because multiple lls-CU processors may contribute + to a single eAxC and must be identified for correct data routing. */ + + struct ecpri_seq_id ecpri_seq_id; /**< This parameter provides unique message identification and ordering on + two different levels. The first octet of this parameter is the Sequence ID, which is used to identify ordering of + messages within an eAxC message stream. The Sequence ID field increments and wraps independently for each U-Plane + eAxC DL, U-Plane eAxC UL, C-Plane eAxC DL, and C-Plane eAxC UL, even if they share the same eAxC ID. + The Sequence ID is used to verify that all messages are received and also to reorder messages that are received out of order. + The second octet of this parameter is the Subsequence ID. The Subsequence ID is used to verify ordering and implement + reordering when radio-transport-level (eCPRI or IEEE-1914.3) fragmentation occurs. + Radio-transport (eCPRI or IEEE-1914.3) fragmentation is a method of splitting U-plane messages containing one or + more sections whose length exceeds the maximum packet or message length of the underlying protocol. + The Subsequence ID field consists of a 7 bit Subsequence counter and a single bit field, called E-bit. + The Subsequence number increments starting from zero for each fragment of a U-plane message. The E bit + is used to indicate the last message of the radio-transport level fragments. It is always set to zero + except for the last message of the U-plane fragment. In the case of C-plane messages radio-transport + fragmentation is not allowed, therefore the Subsequence ID shall be set to zero, and the E bit set to one. + See Section 3.1.4 for a description of the fragmentation process. + NOTE: As an alternative to radio-transport-level fragmentation, application fragmentation can be implemented. + In this case the application can take the responsibility to ensure all transport messages are not too long + (fit within the necessary transport payload size). When this "application layer fragmentation" is used, + the subsequence identifier shall always be set to "0", and the E-bit set to "1" (See Section 3.1.4). */ + +} __rte_packed; + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * Structure holds complete xran packet header + * 3.1.1 Ethernet Encapsulation + *****************************************************************************/ +struct xran_pkt_hdr +{ + struct ether_hdr eth_hdr; /**< Ethernet Header */ + struct vlan_hdr vlan_hdr; /**< VLAN Header */ + struct xran_ecpri_hdr ecpri_hdr; /**< eCPRI Transport Header */ +}; + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * Enum used to set xRAN packet data direction (gNB Tx/Rx 5.4.4.1) + * uplink or downlink + *****************************************************************************/ +enum xran_pkt_dir +{ + XRAN_DIR_UL = 0, /**< UL direction */ + XRAN_DIR_DL = 1, /**< DL direction */ + XRAN_DIR_MAX +}; + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * Structure holds components of radio application header + * 5.4.4 Coding of Information Elements - Application Layer, Common + * for U-plane as per 6.3.2 DL/UL Data + *****************************************************************************/ +struct radio_app_common_hdr +{ + /* Octet 9 */ + uint8_t filter_id:4; /**< This parameter defines an index to the channel filter to be + used between IQ data and air interface, both in DL and UL. + For most physical channels filterIndex =0000b is used which + indexes the standard channel filter, e.g. 100MHz channel filter + for 100MHz nominal carrier bandwidth. (see 5.4.4.3 for more) */ + uint8_t payl_ver:3; /**< This parameter defines the payload protocol version valid + for the following IEs in the application layer. In this version of + the specification payloadVersion=001b shall be used. */ + uint8_t data_direction:1; /**< This parameter indicates the gNB data direction. */ + + /* Octet 10 */ + uint8_t frame_id:8; /**< This parameter is a counter for 10 ms frames (wrapping period 2.56 seconds) */ + + /* Octet 11 */ + /* Octet 12 */ + union { + uint16_t value; + struct { + uint16_t symb_id:6; /**< This parameter identifies the first symbol number within slot, + to which the information of this message is applies. */ + uint16_t slot_id:6; /**< This parameter is the slot number within a 1ms sub-frame. All slots in + one sub-frame are counted by this parameter, slotId running from 0 to Nslot-1. + In this version of the specification the maximum Nslot=16, All + other values of the 6 bits are reserved for future use. */ + uint16_t subframe_id:4; /**< This parameter is a counter for 1 ms sub-frames within 10ms frame. */ + }; + }sf_slot_sym; + +} __rte_packed; + +/** + ****************************************************************************** + * @ingroup xran_common_pkt + * + * @description + * This parameter defines the compression method and IQ bit width for the + * user data in the data section. This field is absent from U-Plane messages + * when the static IQ format and compression method is configured via the M-Plane. + * In this way a single compression method and IQ bit width is provided + * (per UL and DL, per LTE and NR) without adding more overhead to U-Plane messages. + *****************************************************************************/ +struct compression_hdr +{ + uint8_t ud_iq_width:4; /**< Bit width of each I and each Q + 16 for udIqWidth=0, otherwise equals udIqWidth e.g. udIqWidth = 0000b means I and Q are each 16 bits wide; + e.g. udIQWidth = 0001b means I and Q are each 1 bit wide; + e.g. udIqWidth = 1111b means I and Q are each 15 bits wide + */ + uint8_t ud_comp_meth:4; + /**< udCompMeth| compression method |udIqWidth meaning + ---------------+-----------------------------+-------------------------------------------- + 0000b | no compression |bitwidth of each uncompressed I and Q value + 0001b | block floating point |bitwidth of each I and Q mantissa value + 0010b | block scaling |bitwidth of each I and Q scaled value + 0011b | mu-law |bitwidth of each compressed I and Q value + 0100b | modulation compression |bitwidth of each compressed I and Q value + 0100b - 1111b | reserved for future methods |depends on the specific compression method + */ +} __rte_packed; + +#endif diff --git a/fhi_lib/lib/api/xran_pkt_cp.h b/fhi_lib/lib/api/xran_pkt_cp.h new file mode 100644 index 0000000..0f0e1ba --- /dev/null +++ b/fhi_lib/lib/api/xran_pkt_cp.h @@ -0,0 +1,287 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the definition of Control Plane Messages + * for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01. + * + * @file xran_pkt_cp.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_PKT_CP_H_ +#define _XRAN_PKT_CP_H_ + + +/********************************************************************** + * Common structures for C/U-plane + **********************************************************************/ +/** + * @ingroup xran_cp_pkt + * + * @description + * user data compression header defined in 5.4.4.10 / 6.3.3.13 + */ +struct xran_radioapp_udComp_header { + uint8_t udCompMeth:4; /**< Compression method, XRAN_COMPMETHOD_xxxx */ + uint8_t udIqWidth:4; /**< IQ bit width, 1 ~ 16 */ + } __attribute__((__packed__)); + + +/********************************************************************** + * Definition of C-Plane Protocol 5.4 + **********************************************************************/ +/** + * @ingroup xran_cp_pkt + * + * @description + * Common Radio Application Header for C-Plane + */ +struct xran_cp_radioapp_common_header { /* 6bytes, first 4bytes need the conversion for byte order */ + uint32_t startSymbolId:6; /**< 5.4.4.7 start symbol identifier */ + uint32_t slotId:6; /**< 5.4.4.6 slot identifier */ + uint32_t subframeId:4; /**< 5.4.4.5 subframe identifier */ + uint32_t frameId:8; /**< 5.4.4.4 frame identifier */ + uint32_t filterIndex:4; /**< 5.4.4.3 filter index, XRAN_FILTERINDEX_xxxx */ + uint32_t payloadVer:3; /**< 5.4.4.2 payload version, should be 1 */ + uint32_t dataDirection:1; /**< 5.4.4.1 data direction (gNB Tx/Rx) */ + uint8_t numOfSections; /**< 5.4.4.8 number of sections */ + uint8_t sectionType; /**< 5.4.4.9 section type */ + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * frame structure defined in 5.4.4.13 + */ +struct xran_cp_radioapp_frameStructure { + uint8_t uScs:4; /**< sub-carrier spacing, XRAN_SCS_xxx */ + uint8_t fftSize:4; /**< FFT size, XRAN_FFTSIZE_xxx */ + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section headers definition for C-Plane. + * Section type 6 and 7 are not present since those have different fields. + */ +struct xran_cp_radioapp_section_header { // 8bytes, need the conversion for byte order + union { + struct { + uint32_t reserved:16; + uint32_t numSymbol:4; /**< 5.4.5.7 number of symbols */ + uint32_t reMask:12; /**< 5.4.5.5 resource element mask */ + } s0; + struct { + uint32_t beamId:15; /**< 5.4.5.9 beam identifier */ + uint32_t ef:1; /**< 5.4.5.8 extension flag */ + uint32_t numSymbol:4; /**< 5.4.5.7 number of symbols */ + uint32_t reMask:12; /**< 5.4.5.5 resource element mask */ + } s1; + struct { + uint32_t beamId:15; /**< 5.4.5.9 beam identifier */ + uint32_t ef:1; /**< 5.4.5.8 extension flag */ + uint32_t numSymbol:4; /**< 5.4.5.7 number of symbols */ + uint32_t reMask:12; /**< 5.4.5.5 resource element mask */ + } s3; + struct { + uint32_t ueId:15; /**< 5.4.5.10 UE identifier */ + uint32_t ef:1; /**< 5.4.5.8 extension flag */ + uint32_t numSymbol:4; /**< 5.4.5.7 number of symbols */ + uint32_t reMask:12; /**< 5.4.5.5 resource element mask */ + } s5; + } u; + + uint32_t numPrbc:8; /**< 5.4.5.6 number of contiguous PRBs per control section */ + uint32_t startPrbc:10; /**< 5.4.5.4 starting PRB of control section */ + uint32_t symInc:1; /**< 5.4.5.3 symbol number increment command XRAN_SYMBOLNUMBER_xxxx */ + uint32_t rb:1; /**< 5.4.5.2 resource block indicator, XRAN_RBIND_xxx */ + uint32_t sectionId:12; /**< 5.4.5.1 section identifier */ + } __attribute__((__packed__)); + + +/********************************************************** + * Scheduling and Beam-forming Commands 5.4.2 + **********************************************************/ +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 0 + */ +struct xran_cp_radioapp_section0_header { // 12bytes (6+2+1+2+1) + struct xran_cp_radioapp_common_header cmnhdr; + uint16_t timeOffset; /**< 5.4.4.12 time offset */ + + struct xran_cp_radioapp_frameStructure frameStructure; + uint16_t cpLength; /**< 5.4.4.14 cyclic prefix length */ + uint8_t reserved; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section definition for type 0: Unused RB or Symbols in DL or UL (Table 5-2) + * Not supported in this release + */ +struct xran_cp_radioapp_section0 { // 8bytes (4+4) + struct xran_cp_radioapp_section_header hdr; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 1 + */ +struct xran_cp_radioapp_section1_header { // 8bytes (6+1+1) + struct xran_cp_radioapp_common_header cmnhdr; + struct xran_radioapp_udComp_header udComp; + uint8_t reserved; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section definition for type 1: Most DL/UL Radio Channels (Table 5-3) + */ +struct xran_cp_radioapp_section1 { // 8bytes (4+4) + struct xran_cp_radioapp_section_header hdr; + + // section extensions // 5.4.6 & 5.4.7 + // ......... + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 3 + */ +struct xran_cp_radioapp_section3_header { // 12bytes (6+2+1+2+1) + struct xran_cp_radioapp_common_header cmnhdr; + uint16_t timeOffset; /**< 5.4.4.12 time offset */ + + struct xran_cp_radioapp_frameStructure frameStructure; + uint16_t cpLength; /**< 5.4.4.14 cyclic prefix length */ + struct xran_radioapp_udComp_header udComp; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section definition for type 3: PRACH and Mixed-numerology Channels (Table 5-4) + */ +struct xran_cp_radioapp_section3 { // 12bytes (4+4+4) + struct xran_cp_radioapp_section_header hdr; + uint32_t freqOffset:24; /**< 5.4.5.11 frequency offset */ + uint32_t reserved:8; + + // section extensions // 5.4.6 & 5.4.7 + // ......... + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 5 + */ +struct xran_cp_radioapp_section5_header { // 8bytes (6+1+1) + struct xran_cp_radioapp_common_header cmnhdr; + struct xran_radioapp_udComp_header udComp; + uint8_t reserved; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section definition for type 5: UE scheduling information (Table 5-5) + * Not supported in this release + */ +struct xran_cp_radioapp_section5 { + struct xran_cp_radioapp_section_header hdr; + + // section extensions // 5.4.6 & 5.4.7 + // ......... + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 6 + */ +struct xran_cp_radioapp_section6_header { // 8bytes (6+1+1) + struct xran_cp_radioapp_common_header cmnhdr; + uint8_t numberOfUEs; /**< 5.4.4.11 number of UEs */ + uint8_t reserved; + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section definition for type 5: Channel Information (Table 5-6) + * Not supported in this release + */ +struct xran_cp_radioapp_section6 { + uint32_t regularizationFactor:16;/**< 5.4.5.12 regularization Factor */ + uint32_t ueId:15; /**< 5.4.5.10 UE identifier */ + uint32_t ef:1; /**< 5.4.5.8 extension flag */ + uint8_t startPrbch:2; /**< 5.4.5.4 starting PRB of control section */ + uint8_t symInc:1; /**< 5.4.5.3 symbol number increment command XRAN_SYMBOLNUMBER_xxxx */ + uint8_t rb:1; /**< 5.4.5.2 resource block indicator, XRAN_RBIND_xxx */ + uint8_t reserved:4; + uint8_t startPrbcl:8; /**< 5.4.5.4 starting PRB of control section */ + uint8_t numPrbc:8; /**< 5.4.5.6 number of contiguous PRBs per control section */ + + // ciIQsamples start from here // 5.4.5.13 channel information I and Q values + // ......... + // + // section extensions // 5.4.6 & 5.4.7 + // ......... + } __attribute__((__packed__)); + +/** + * @ingroup xran_cp_pkt + * + * @description + * Section header definition for type 7: LAA + * Not supported in this release + */ +struct xran_cp_radioapp_section7_header { + struct xran_cp_radioapp_common_header cmnhdr; + uint16_t reserved; + uint8_t laaMsgLen:4; /**< 5.4.5.15 LAA message length */ + uint8_t laaMsgType:4; /**< 5.4.5.14 LAA message type */ + + // Payload start from here // 5.4.5.16 ~ 5.4.5.32 + } __attribute__((__packed__)); + + +#endif /* _XRAN_PKT_CP_H_ */ diff --git a/fhi_lib/lib/api/xran_pkt_up.h b/fhi_lib/lib/api/xran_pkt_up.h new file mode 100644 index 0000000..a2399f0 --- /dev/null +++ b/fhi_lib/lib/api/xran_pkt_up.h @@ -0,0 +1,138 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief Definitions and support functions to process XRAN packet + * @file xran_pkt_up.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +/** + ***************************************************************************** + * @file xran_pkt_up.h + * + * @defgroup xran_up_pkt U-Plane XRAN Packet definitions and functions + * @ingroup xran + * + * @description + * Structures relevant to U-plane packets only (data now only) + *****************************************************************************/ +#ifndef _XRAN_PKT_UP_H_ +#define _XRAN_PKT_UP_H_ + +#include "xran_pkt.h" + +#define IQ_PAIR_NUM_IN_RB 12 +#define MAX_DATA_SECTIONS_NUM 273 +#define MAX_IQ_BIT_WIDTH 16 + +/* currently library supports I and Q sizes of 8 and 16 bits each */ +#define IQ_BITS MAX_IQ_BIT_WIDTH + +/* + * Structure holding data section header fields + * It is repeated for every section ID in xRAN packet + */ + +/** + ****************************************************************************** + * @ingroup xran_up_pkt + * + * @description + * Structure holding data section header fields + * It is repeated for every section ID in xRAN packet + * 5.4.5 Coding of Information Elements - Application Layer, Sections + * for U-plane as per 6.3.2 DL/UL Data + *****************************************************************************/ +struct data_section_hdr { + union { + uint32_t all_bits; + struct { + uint32_t num_prbu:8; /**< 5.4.5.6 number of contiguous PRBs per control section */ + uint32_t start_prbu:10; /**< 5.4.5.4 starting PRB of control section */ + uint32_t sym_inc:1; /**< 5.4.5.3 symbol number increment command XRAN_SYMBOLNUMBER_xxxx */ + uint32_t rb:1; /**< 5.4.5.2 resource block indicator, XRAN_RBIND_xxx */ + uint32_t sect_id:12; /**< 5.4.5.1 section identifier */ + }; + }fields; + } __attribute__((__packed__)); + + +/* + ****************************************************************************** + * @ingroup xran_up_pkt + * + * @description + * Structure holds compression header structure and field reserved for future use. + * reserved goes always with udCompHdr in u-plane pkt + * U-plane as per 6.3.2 DL/UL Data + *****************************************************************************/ +struct data_section_compression_hdr +{ + struct compression_hdr ud_comp_hdr; + uint8_t rsrvd; /**< This parameter provides 1 byte for future definition, + should be set to all zeros by the sender and ignored by the receiver. + This field is only present when udCompHdr is present, and is absent when + the static IQ format and compression method is configured via the M-Plane */ + + /* TODO: support for Block Floating Point compression */ + /* udCompMeth 0000b = no compression absent*/ +}; + +/* + ****************************************************************************** + * @ingroup xran_up_pkt + * + * @description + * Structure holds the compression parameters by the compression header. + * may not be present by udCompMeth in 6.3.3.13 + *****************************************************************************/ +union compression_params { + struct block_fl_point { + uint8_t exponent:4; + uint8_t reserved:4; + } blockFlPoint; + struct block_scaling { + uint8_t sblockScaler; + } blockScaling; + struct u_law { + uint8_t compShift:4; + uint8_t compBitWidth:4; + } uLaw; + } __attribute__((__packed__)); + + +/* + ****************************************************************************** + * @ingroup xran_up_pkt + * + * @description + * Structure holds an IQ sample pair + * U-plane as per 6.3.2 DL/UL Data + * Each bit field size is defined with IQ_BITS macro + * Currently supported I and Q sizes are 8 and 16 bits + *****************************************************************************/ +struct rb_map +{ + int16_t i_sample:IQ_BITS; /**< This parameter is the In-phase sample value */ + int16_t q_sample:IQ_BITS; /**< This parameter is the Quadrature sample value */ +} __rte_packed;; + +#endif diff --git a/fhi_lib/lib/api/xran_sync_api.h b/fhi_lib/lib/api/xran_sync_api.h new file mode 100644 index 0000000..2e98311 --- /dev/null +++ b/fhi_lib/lib/api/xran_sync_api.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides interface to synchronization related APIs (PTP/1588) + * for XRAN. + * + * @file xran_sync_api.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_SYNC_API_H_ +#define _XRAN_SYNC_API_H_ + +/** + * @brief Function checks if machine is synchronized using PTP for Linux + * software. + * + * @return int Returns 0 if synchronized, otherwise positive. + */ +int xran_is_synchronized(void); + +#endif /* _XRAN_SYNC_API_H_ */ diff --git a/fhi_lib/lib/api/xran_timer.h b/fhi_lib/lib/api/xran_timer.h new file mode 100644 index 0000000..d44b5e0 --- /dev/null +++ b/fhi_lib/lib/api/xran_timer.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides interface to Timing for XRAN. + * + * @file xran_timer.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_TIMER_H +#define _XRAN_TIMER_H +#include +#include +#include +#include + +#define MSEC_PER_SEC 1000L + +#define XranIncrementSymIdx(sym_idx, numSymPerMs) (((uint32_t)sym_idx >= (((uint32_t)numSymPerMs * MSEC_PER_SEC) - 1)) ? 0 : (uint32_t)sym_idx+1) +#define XranDecrementSymIdx(sym_idx, numSymPerMs) (((uint32_t)sym_idx == 0) ? (((uint32_t)numSymPerMs * MSEC_PER_SEC)) - 1) : (uint32_t)sym_idx-1) + +long poll_next_tick(long interval_ns); +long sleep_next_tick(long interval); +int timing_set_debug_stop(int value); +int timing_get_debug_stop(void); +inline uint64_t timing_get_current_second(void); + +#endif diff --git a/fhi_lib/lib/api/xran_transport.h b/fhi_lib/lib/api/xran_transport.h new file mode 100644 index 0000000..6d69c3e --- /dev/null +++ b/fhi_lib/lib/api/xran_transport.h @@ -0,0 +1,74 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the definitions for Transport layer (eCPRI) API. + * + * @file xran_transport.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_TRANSPORT_H_ +#define _XRAN_TRANSPORT_H_ + +#include +#include + +#include "xran_pkt.h" + +struct xran_eaxc_info { + uint8_t cuPortId; + uint8_t bandSectorId; + uint8_t ccId; + uint8_t ruPortId; + }; + +/** + * @brief Compose ecpriRtcid/ecpriPcid + * + * @param CU_Port_ID CU Port ID + * @param BanbSector_ID Band Sector ID + * @param CC_ID Component Carrier ID + * @param Ant_ID RU Port ID (antenna ID) + * @return uint16_t composed ecpriRtcid/ecpriPcid + */ +uint16_t xran_compose_cid(uint8_t CU_Port_ID, uint8_t BandSector_ID, uint8_t CC_ID, uint8_t Ant_ID); + +/** + * @brief Decompose ecpriRtcid/ecpriPcid + * + * @param cid composed ecpriRtcid/ecpriPcid (network byte order) + * @param result the pointer of the structure to store decomposed values + * @return none + */ +void xran_decompose_cid(uint16_t cid, struct xran_eaxc_info *result); + +/** + * @brief modify the payload size of eCPRI header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet which has eCPRI header already + * @param size payload size to be updated + * @return none + */ +void xran_update_ecpri_payload_size(struct rte_mbuf *mbuf, int size); + +#endif + diff --git a/fhi_lib/lib/api/xran_up_api.h b/fhi_lib/lib/api/xran_up_api.h new file mode 100644 index 0000000..4665762 --- /dev/null +++ b/fhi_lib/lib/api/xran_up_api.h @@ -0,0 +1,116 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the definitions for User Plane Messages APIs. + * + * @file xran_up_api.h + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#ifndef _XRAN_UP_API_H_ +#define _XRAN_UP_API_H_ + +#include +#include + +#include "xran_pkt.h" +#include "xran_pkt_up.h" + +#define XRAN_BYTE_ORDER_SWAP + +/* + * structure used for storing packet parameters needed for generating + * a data packet + */ +struct xran_up_pkt_gen_params +{ + struct radio_app_common_hdr app_params; + struct data_section_hdr sec_hdr; + struct data_section_compression_hdr compr_hdr_param; + union compression_params compr_param; +}; + +/* + * structure used for storing packet parameters needed for generating + * a data packet without compression + * Next fields are omitted: + * udCompHdr (not always present) + * reserved (not always present) + * udCompParam (not always present) + */ +struct xran_up_pkt_gen_no_compression_params +{ + struct radio_app_common_hdr app_params; + struct data_section_hdr sec_hdr; +}; + + +/** + * @brief Function that is preparing an mbuf with portion of IQ samples related + * to the single symbol. + * + * @param mbuf Initialized rte_mbuf packet + * @param iq_data_start Address of the first element in IQ data array. + * @param iq_data_num_elements Size of the IQ data array. + * @param iq_data_offset IQ data array's elements already sent. + * @param alignment Align data to this many bytes. + * @param params Structure containing Radio App Header and Data Section Header + * structures. + * @return int Bytes of IQ samples that have been appended to the packet. + */ +int xran_prepare_iq_symbol_portion( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes, + uint32_t *iq_data_offset, + const uint8_t alignment, + struct xran_up_pkt_gen_params *params, + int sub_seq_id); + +/** + * @brief Function extracts IQ samples from received mbuf packet. + * + * @param mbuf Packet with received data. + * @param iq_data_start Address of the first IQ sample in mbuf will be returned + * here + * @return int Bytes of IQ samples that have been extracted from mbuf. + */ +int xran_extract_iq_samples(struct rte_mbuf *mbuf, + void **iq_data_start, + uint8_t *CC_ID, + uint8_t *Ant_ID, + uint8_t *frame_id, + uint8_t *subframe_id, + uint8_t *slot_id, + uint8_t *symb_id, + struct ecpri_seq_id *seq_id); + +int xran_prepare_iq_symbol_portion_no_comp( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes, + struct xran_up_pkt_gen_no_compression_params *params, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t seq_id); + +#endif /* _XRAN_UP_API_H_ */ diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c new file mode 100644 index 0000000..3664ecc --- /dev/null +++ b/fhi_lib/lib/ethernet/ethdi.c @@ -0,0 +1,376 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file has all definitions for the Ethernet Data Interface Layer + * @file ethdi.c + * @ingroup group_lte_source_auxlib + * @author Intel Corporation + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ethernet.h" +#include "ethdi.h" +#ifndef MLOG_ENABLED +#include "../src/mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif + +#include "../src/xran_lib_mlog_tasks_id.h" + +struct xran_ethdi_ctx g_ethdi_ctx = { 0 }; +enum xran_if_state xran_if_current_state = XRAN_STOPPED; + +struct rte_mbuf *xran_ethdi_mbuf_alloc(void) +{ + return rte_pktmbuf_alloc(_eth_mbuf_pool); +} + +int xran_ethdi_mbuf_send(struct rte_mbuf *mb, uint16_t ethertype) +{ + struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx(); + int res = 0; + + mb->port = ctx->io_cfg.port[ETHDI_UP_VF]; + xran_add_eth_hdr_vlan(&ctx->entities[ID_RU], ethertype, mb, ctx->up_vtag); + + res = xran_enqueue_mbuf(mb, ctx->tx_ring[ETHDI_UP_VF]); + return res; +} + +int xran_ethdi_mbuf_send_cp(struct rte_mbuf *mb, uint16_t ethertype) +{ + struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx(); + int res = 0; + + mb->port = ctx->io_cfg.port[ETHDI_CP_VF]; + xran_add_eth_hdr_vlan(&ctx->entities[ID_RU], ethertype, mb, ctx->cp_vtag); + + res = xran_enqueue_mbuf(mb, ctx->tx_ring[ETHDI_CP_VF]); + return res; +} + +void xran_ethdi_stop_tx() +{ + struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx(); + rte_timer_stop_sync(&ctx->timer_tx); +} + + +struct { + uint16_t ethertype; + ethertype_handler fn; +} xran_ethertype_handlers[] = { + { ETHER_TYPE_ETHDI, NULL }, + { ETHER_TYPE_ECPRI, NULL }, + { ETHER_TYPE_START_TX, NULL } +}; + + + +int xran_register_ethertype_handler(uint16_t ethertype, ethertype_handler callback) +{ + int i; + + for (i = 0; i < RTE_DIM(xran_ethertype_handlers); ++i) + if (xran_ethertype_handlers[i].ethertype == ethertype) { + xran_ethertype_handlers[i].fn = callback; + + return 1; + } + + elog("support for ethertype %u not found", ethertype); + + return 0; +} + +int xran_handle_ether(uint16_t ethertype, struct rte_mbuf *pkt, uint64_t rx_time) +{ + int i; + + for (i = 0; i < RTE_DIM(xran_ethertype_handlers); ++i) + if (xran_ethertype_handlers[i].ethertype == ethertype) + if (xran_ethertype_handlers[i].fn) + return xran_ethertype_handlers[i].fn(pkt, rx_time); + + wlog("Packet with unrecognized ethertype '%.4X' dropped", ethertype); + + return 0; +}; + + +/* Process vlan tag. Cut the ethernet header. Call the etherype handlers. */ +int xran_ethdi_filter_packet(struct rte_mbuf *pkt, uint64_t rx_time) +{ + struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx(); + +#ifdef VLAN_SUPPORT + if (rte_vlan_strip(pkt) == 0) { + if (pkt->vlan_tci == ctx->cp_vtag) { + dlog("VLAN tci matches %d", pkt->vlan_tci); + } else { + wlog("packet with wrong VLAN tag %d, dropping", + pkt->vlan_tci); + return 0; + } + } else + dlog("Packet not vlan tagged"); +#endif + + const struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(pkt, void *); + +#if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1 + nlog("*** processing RX'ed packet of size %d ***", + rte_pktmbuf_data_len(pkt)); + /* TODO: just dump ethernet header in readable format? */ +#endif + +#if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1 + { + char dst[ETHER_ADDR_FMT_SIZE] = "(empty)"; + char src[ETHER_ADDR_FMT_SIZE] = "(empty)"; + + ether_format_addr(dst, sizeof(dst), ð_hdr->d_addr); + ether_format_addr(src, sizeof(src), ð_hdr->s_addr); + nlog("src: %s dst: %s ethertype: %.4X", dst, src, + rte_be_to_cpu_16(eth_hdr->ether_type)); + } +#endif + + /* Cut out the ethernet header. It's not needed anymore. */ + if (rte_pktmbuf_adj(pkt, sizeof(*eth_hdr)) == NULL) { + wlog("Packet too short, dropping"); + return 0; + } + + + return xran_handle_ether(rte_be_to_cpu_16(eth_hdr->ether_type), pkt, rx_time); +} + + + + +int xran_ethdi_init_dpdk_io(char *name, const struct xran_io_loop_cfg *io_cfg, + int *lcore_id, struct ether_addr *p_lls_cu_addr, struct ether_addr *p_ru_addr, + uint16_t cp_vlan, uint16_t up_vlan) +{ + uint16_t port[2] = {0, 0}; + struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx(); + int i; + char core_mask[20]; + char *argv[] = { name, core_mask, "-m3072", "--proc-type=auto", + "--file-prefix", name, "-w", "0000:00:00.0" }; + + if (io_cfg == NULL) + return 0; + + snprintf(core_mask, sizeof(core_mask), "-c%x", + (1 << io_cfg->core) | + (1 << io_cfg->system_core) | + (1 << io_cfg->pkt_proc_core) | + (1 << io_cfg->pkt_aux_core) | + (1 << io_cfg->timing_core)); + + ctx->io_cfg = *io_cfg; + ctx->ping_state = PING_IDLE; + ctx->known_peers = 1; + ctx->busy_poll_till = rte_rdtsc(); + ctx->cp_vtag = cp_vlan; + ctx->up_vtag = up_vlan; + + for (i = 0; i <= ID_BROADCAST; i++) /* Initialize all as broadcast */ + memset(&ctx->entities[i], 0xFF, sizeof(ctx->entities[0])); + + /* This will return on system_core, which is not necessarily the + * one we're on right now. */ + if (rte_eal_init(RTE_DIM(argv), argv) < 0) + rte_panic("Cannot init EAL: %s\n", rte_strerror(rte_errno)); + + xran_init_mbuf_pool(); + + /* Timers. */ + rte_timer_subsystem_init(); + rte_timer_init(&ctx->timer_ping); + rte_timer_init(&ctx->timer_sync); + rte_timer_init(&ctx->timer_tx); + + *lcore_id = rte_get_next_lcore(rte_lcore_id(), 0, 0); + + PANIC_ON(*lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()"); + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + for (i = 0; i < ETHDI_VF_MAX; i ++){ + if (rte_eth_dev_attach(io_cfg->dpdk_dev[i], &port[i]) != 0 || + rte_eth_dev_count_avail() == 0) + errx(1, "Network port doesn't exist."); + xran_init_port(port[i], p_lls_cu_addr); /* we only have 1 port at this stage */ + if(i==0){ + ctx->tx_ring[i] = rte_ring_create("tx_ring_up", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + ctx->rx_ring[i] = rte_ring_create("rx_ring_up", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + ctx->pkt_dump_ring[i] = rte_ring_create("pkt_dump_ring_up", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + }else { + ctx->tx_ring[i] = rte_ring_create("tx_ring_cp", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + ctx->rx_ring[i] = rte_ring_create("rx_ring_cp", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + ctx->pkt_dump_ring[i] = rte_ring_create("pkt_dump_ring_cp", NUM_MBUFS, + rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ); + } + } + } else { + rte_panic("ethdi_dpdk_io_loop() failed to start with RTE_PROC_SECONDARY\n"); + } + PANIC_ON(ctx->tx_ring == NULL, "failed to allocate tx ring"); + PANIC_ON(ctx->rx_ring == NULL, "failed to allocate rx ring"); + PANIC_ON(ctx->pkt_dump_ring == NULL, "failed to allocate pkt dumping ring"); + for (i = 0; i < ETHDI_VF_MAX; i++) + ctx->io_cfg.port[i] = port[i]; + + rte_eth_macaddr_get(port[ETHDI_UP_VF], &ctx->entities[io_cfg->id]); + ether_addr_copy(p_ru_addr, &ctx->entities[ID_RU]); + + /* Start the actual IO thread */ + if (rte_eal_remote_launch(xran_ethdi_dpdk_io_loop, &ctx->io_cfg, *lcore_id)) + rte_panic("ethdi_dpdk_io_loop() failed to start\n"); + + return 1; +} + +static inline uint16_t xran_tx_from_ring(int port, struct rte_ring *r) +{ + struct rte_mbuf *mbufs[BURST_SIZE]; + uint16_t dequeued, sent = 0; + uint32_t remaining; + int i; + long t1 = MLogTick(); + + dequeued = rte_ring_dequeue_burst(r, (void **)mbufs, BURST_SIZE, + &remaining); + if (!dequeued) + return 0; /* Nothing to send. */ + + while (1) { /* When tx queue is full it is trying again till succeed */ + t1 = MLogTick(); + sent += rte_eth_tx_burst(port, 0, &mbufs[sent], dequeued - sent); + MLogTask(PID_RADIO_ETH_TX_BURST, t1, MLogTick()); + + if (sent == dequeued) + return remaining; + } +} + + + +/* + * This is the main DPDK-IO loop. + * This will sleep if there's no packets incoming and there's + * no work enqueued, sleep lenth is defined in IDLE_SLEEP_MICROSECS + */ +int xran_ethdi_dpdk_io_loop(void *io_loop_cfg) +{ + struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx(); + const struct xran_io_loop_cfg *const cfg = io_loop_cfg; + const int port[ETHDI_VF_MAX] = {cfg->port[ETHDI_UP_VF], cfg->port[ETHDI_CP_VF]}; + int port_id = 0; + struct sched_param sched_param; + int res = 0; + + printf("%s [PORT: %d %d] [CPU %2d] [PID: %6d]\n", __FUNCTION__, port[ETHDI_UP_VF], port[ETHDI_CP_VF] , rte_lcore_id(), getpid()); + + printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid()); + sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO; + if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param))) + { + printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res); + } + + for (;;) { + for (port_id = 0; port_id < ETHDI_VF_MAX; port_id++){ + struct rte_mbuf *mbufs[BURST_SIZE]; + /* RX */ + const uint16_t rxed = rte_eth_rx_burst(port[port_id], 0, mbufs, BURST_SIZE); + if (rxed != 0){ + long t1 = MLogTick(); + rte_ring_enqueue_burst(ctx->rx_ring[port_id], (void*)mbufs, rxed, NULL); + MLogTask(PID_RADIO_RX_VALIDATE, t1, MLogTick()); + } + + /* TX */ + const uint16_t sent = xran_tx_from_ring(port[port_id], ctx->tx_ring[port_id]); + if (rxed | sent) + continue; /* more packets might be waiting in queues */ + + rte_pause(); /* short pause, optimize memory access */ + if (XRAN_STOPPED == xran_if_current_state) + break; + } + + if (XRAN_STOPPED == xran_if_current_state) + break; + } + + fflush(stderr); + fflush(stdout); + puts("IO loop finished"); + + //for (port_id = 0; port_id < ETHDI_VF_MAX; port_id++) + // xran_ethdi_port_stats(port[port_id]); + + return 0; +} diff --git a/fhi_lib/lib/ethernet/ethdi.h b/fhi_lib/lib/ethernet/ethdi.h new file mode 100644 index 0000000..3b00e15 --- /dev/null +++ b/fhi_lib/lib/ethernet/ethdi.h @@ -0,0 +1,169 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file has all definitions for the Ethernet Data Interface Layer + * @file ethdi.h + * @ingroup group_lte_source_auxlib + * @author Intel Corporation + **/ + + +#ifndef _ETHDI_H_ +#define _ETHDI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "ethernet.h" + +#define XRAN_THREAD_DEFAULT_PRIO (98) + +/* How often to ping? */ +#define PING_INTERVAL 300 /* (us) */ +#define PING_BUSY_POLL 50 /* (us) how long to actively wait for response */ + +/* If we're not receiving packets for more then this threshold... */ +//#define SLEEP_THRESHOLD (rte_get_tsc_hz() / 30) /* = 33.3(3)ms */ +/* we go to sleep for this long (usleep). Undef SLEEP_TRESHOLD to disable. */ +#define SLEEP_TIME 200 /* (us) */ +#define BCAST {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + +#define TX_TIMER_INTERVAL ((rte_get_timer_hz() / 1000000000L)*interval_us*1000) /* nanosec */ +#define TX_RX_LOOP_TIME rte_get_timer_hz() / 1 + +extern enum xran_if_state xran_if_current_state; + +enum xran_if_state +{ + XRAN_RUNNING, + XRAN_STOPPED +}; + +enum xran_ping_states +{ + PING_IDLE, + PING_NEEDED, + AWAITING_PONG +}; + +enum xran_ethdi_vf_ports +{ + ETHDI_UP_VF = 0, + ETHDI_CP_VF, + ETHDI_VF_MAX +}; + +struct xran_io_loop_cfg +{ + uint8_t id; + char *dpdk_dev[ETHDI_VF_MAX]; + int core; + int system_core; /* Needed as DPDK will change your starting core. */ + int pkt_proc_core; /* Needed for packet processing thread. */ + int pkt_aux_core; /* Needed for packet dumping for debug purposes. */ + int timing_core; /* Needed for getting precise time */ + int port[ETHDI_VF_MAX]; /* This is auto-detected, no need to set. */ +}; + +/* CAUTION: Keep in sync with the string table below. */ +enum xran_entities_id +{ + ID_LLS_CU, + ID_RU, + ID_BROADCAST, + ID_MAX +}; + +static char *const entity_names[] = { + "xRAN lls-CU sim app", + "xRAN RU sim app", +}; + +typedef int (*PROCESS_CB)(void * arg); + +struct xran_ethdi_ctx +{ + struct xran_io_loop_cfg io_cfg; + struct ether_addr entities[ID_BROADCAST + 1]; + uint8_t ping_state; + int ping_times; + int known_peers; + + struct rte_ring *tx_ring[ETHDI_VF_MAX]; + struct rte_ring *rx_ring[ETHDI_VF_MAX]; + struct rte_ring *pkt_dump_ring[ETHDI_VF_MAX]; + struct rte_timer timer_autodetect; + struct rte_timer timer_ping; + struct rte_timer timer_sync; + struct rte_timer timer_tx; + + uint64_t busy_poll_till; + + unsigned pkt_stats[PKT_LAST + 1]; + + uint16_t cp_vtag; + uint16_t up_vtag; +}; + +enum { + MBUF_KEEP, + MBUF_FREE +}; + +extern uint8_t ping_dst_id; +extern struct ether_addr entities_addrs[]; + +static inline struct xran_ethdi_ctx *xran_ethdi_get_ctx(void) +{ + extern struct xran_ethdi_ctx g_ethdi_ctx; + + return &g_ethdi_ctx; +} +typedef int (*xran_ethdi_handler)(struct rte_mbuf *, int sender, uint64_t rx_time); + +typedef int (*ethertype_handler)(struct rte_mbuf *, uint64_t rx_time); +typedef int (*xran_ethdi_handler)(struct rte_mbuf *, int sender, uint64_t rx_time); +typedef void (xran_ethdi_tx_callback)(struct rte_timer *tim, void *arg); + + +int xran_register_ethertype_handler(uint16_t ethertype, ethertype_handler callback); + + +int xran_ethdi_init_dpdk_io(char *name, const struct xran_io_loop_cfg *io_cfg, + int *lcore_id, struct ether_addr *p_lls_cu_addr, struct ether_addr *p_ru_addr, + uint16_t cp_vlan, uint16_t up_vlan); +int xran_ethdi_dpdk_io_loop(void *); +struct rte_mbuf *xran_ethdi_mbuf_alloc(void); +int xran_ethdi_mbuf_send(struct rte_mbuf *mb, uint16_t ethertype); +int xran_ethdi_mbuf_send_cp(struct rte_mbuf *mb, uint16_t ethertype); +void xran_ethdi_stop_tx(void); +int xran_ethdi_filter_packet(struct rte_mbuf *pkt, uint64_t rx_time); + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _ETHDI_H_ */ diff --git a/fhi_lib/lib/ethernet/ethernet.c b/fhi_lib/lib/ethernet/ethernet.c new file mode 100644 index 0000000..ebf997c --- /dev/null +++ b/fhi_lib/lib/ethernet/ethernet.c @@ -0,0 +1,357 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file has all definitions for the Ethernet Data Interface Layer + * @file ethernet.c + * @ingroup group_lte_source_auxlib + * @author Intel Corporation + **/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ethernet.h" +#include "ethdi.h" + +/* Our mbuf pools. */ +struct rte_mempool *_eth_mbuf_pool; +struct rte_mempool *_eth_mbuf_pool_rx; +struct rte_mempool *_eth_mbuf_pool_small; +struct rte_mempool *_eth_mbuf_pool_big; + +/* + * Make sure the ring indexes are big enough to cover buf space x2 + * This ring-buffer maintains the property head - tail <= RINGSIZE. + * head == tail: ring buffer empty + * head - tail == RINGSIZE: ring buffer full + */ +typedef uint16_t ring_idx; +static struct { + ring_idx head; + ring_idx read_head; + ring_idx tail; + char buf[1024]; /* needs power of 2! */ +} io_ring = { {0}, 0, 0}; + +#define RINGSIZE sizeof(io_ring.buf) +#define RINGMASK (RINGSIZE - 1) + + +/* + * Display part of the message stored in the ring buffer. + * Might require multiple calls to print the full message. + * Will return 0 when nothing left to print. + */ +int xran_show_delayed_message(void) +{ + ring_idx tail = io_ring.tail; + ring_idx wlen = io_ring.read_head - tail; /* always within [0, RINGSIZE] */ + + if (wlen <= 0) + return 0; + + tail &= RINGMASK; /* modulo the range down now that we have wlen */ + + /* Make sure we're not going over buffer end. Next call will wrap. */ + if (tail + wlen > RINGSIZE) + wlen = RINGSIZE - tail; + + RTE_ASSERT(tail + wlen <= RINGSIZE); + + /* We use write() here to avoid recaculating string length in fwrite(). */ + const ssize_t written = write(STDOUT_FILENO, io_ring.buf + tail, wlen); + if (written <= 0) + return 0; /* To avoid moving tail the wrong way on error. */ + + /* Move tail up. Only we touch it. And we only print from one core. */ + io_ring.tail += written; + + return written; /* next invocation will print the rest if any */ +} + + +void xran_init_mbuf_pool(void) +{ + /* Init the buffer pool */ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + _eth_mbuf_pool = rte_pktmbuf_pool_create("mempool", NUM_MBUFS, + MBUF_CACHE, 0, MBUF_POOL_ELEMENT, rte_socket_id()); + _eth_mbuf_pool_rx = rte_pktmbuf_pool_create("mempool_rx", NUM_MBUFS, + MBUF_CACHE, 0, MBUF_POOL_ELEMENT, rte_socket_id()); + _eth_mbuf_pool_small = rte_pktmbuf_pool_create("mempool_small", + NUM_MBUFS, MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL, rte_socket_id()); + _eth_mbuf_pool_big = rte_pktmbuf_pool_create("mempool_big", + NUM_MBUFS_BIG, 0, 0, MBUF_POOL_ELM_BIG, rte_socket_id()); + } else { + _eth_mbuf_pool = rte_mempool_lookup("mempool"); + _eth_mbuf_pool_rx = rte_mempool_lookup("mempool_rx"); + _eth_mbuf_pool_small = rte_mempool_lookup("mempool_small"); + _eth_mbuf_pool_big = rte_mempool_lookup("mempool_big"); + } + if (_eth_mbuf_pool == NULL) + rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno)); + if (_eth_mbuf_pool_rx == NULL) + rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno)); + if (_eth_mbuf_pool_small == NULL) + rte_panic("Cannot create small mbuf pool: %s\n", rte_strerror(rte_errno)); + if (_eth_mbuf_pool_big == NULL) + rte_panic("Cannot create big mbuf pool: %s\n", rte_strerror(rte_errno)); +} + +/* Init NIC port, then start the port */ +void xran_init_port(int p_id, struct ether_addr *p_lls_cu_addr) +{ + char buf[ETHER_ADDR_FMT_SIZE]; + struct ether_addr eth_addr; + struct rte_eth_rxmode rxmode = + { .split_hdr_size = 0, + .max_rx_pkt_len = MAX_RX_LEN, + .offloads=(DEV_RX_OFFLOAD_JUMBO_FRAME|DEV_RX_OFFLOAD_CRC_STRIP) + }; + struct rte_eth_txmode txmode = { + .mq_mode = ETH_MQ_TX_NONE + }; + struct rte_eth_conf port_conf = { + .rxmode = rxmode, + .txmode = txmode + }; + struct ether_addr pDstEthAddr; + + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + + int ret; + struct rte_eth_dev_info dev_info; + const char *drv_name = ""; + int sock_id = rte_eth_dev_socket_id(p_id); + + // ether_format_addr(buf, sizeof(buf), p_lls_cu_addr); + // printf("port %d set mac address %s\n", p_id, buf); + // rte_eth_dev_default_mac_addr_set(p_id, p_lls_cu_addr); + + rte_eth_dev_info_get(p_id, &dev_info); + if (dev_info.driver_name) + drv_name = dev_info.driver_name; + printf("initializing port %d for TX, drv=%s\n", p_id, drv_name); + + /* In order to receive packets from any server need to add broad case address + * for the port*/ + pDstEthAddr.addr_bytes[0] = 0xFF; + pDstEthAddr.addr_bytes[1] = 0xFF; + pDstEthAddr.addr_bytes[2] = 0xFF; + + pDstEthAddr.addr_bytes[3] = 0xFF; + pDstEthAddr.addr_bytes[4] = 0xFF; + pDstEthAddr.addr_bytes[5] = 0xFF; + + rte_eth_macaddr_get(p_id, ð_addr); + ether_format_addr(buf, sizeof(buf), ð_addr); + printf("port %d mac address %s\n", p_id, buf); + + struct ether_addr addr; + rte_eth_macaddr_get(p_id, &addr); + +// rte_eth_dev_mac_addr_add(p_id, &pDstEthAddr,1); + // rte_eth_dev_mac_addr_add(p_id, &addr, 1); + + printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 + " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", + (unsigned)p_id, + addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], + addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); + + /* Init port */ + ret = rte_eth_dev_configure(p_id, 1, 1, &port_conf); + if (ret < 0) + rte_panic("Cannot configure port %u (%d)\n", p_id, ret); + + /* Init RX queues */ + rxq_conf = dev_info.default_rxconf; + ret = rte_eth_rx_queue_setup(p_id, 0, BURST_SIZE, + sock_id, &rxq_conf, _eth_mbuf_pool_rx); + if (ret < 0) + rte_panic("Cannot init RX for port %u (%d)\n", + p_id, ret); + + /* Init TX queues */ + txq_conf = dev_info.default_txconf; + ret = rte_eth_tx_queue_setup(p_id, 0, BURST_SIZE, sock_id, &txq_conf); + if (ret < 0) + rte_panic("Cannot init TX for port %u (%d)\n", + p_id, ret); + + /* Start port */ + ret = rte_eth_dev_start(p_id); + if (ret < 0) + rte_panic("Cannot start port %u (%d)\n", p_id, ret); + + rte_eth_promiscuous_enable(p_id); +} + +void xran_memdump(void *addr, int len) +{ + int i; + char tmp_buf[len * 2 + len / 16 + 1]; + char *p = tmp_buf; + + return; +#if 0 + for (i = 0; i < len; ++i) { + sprintf(p, "%.2X ", ((uint8_t *)addr)[i]); + if (i % 16 == 15) + *p++ = '\n'; + } + *p = 0; + nlog("%s", tmp_buf); +#endif +} + + +/* Prepend ethernet header, possibly vlan tag. */ +void xran_add_eth_hdr_vlan(struct ether_addr *dst, uint16_t ethertype, struct rte_mbuf *mb, uint16_t vlan_tci) +{ + /* add in the ethernet header */ + struct ether_hdr *const h = (void *)rte_pktmbuf_prepend(mb, sizeof(*h)); + + PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed"); + + /* Fill in the ethernet header. */ + rte_eth_macaddr_get(mb->port, &h->s_addr); /* set source addr */ + h->d_addr = *dst; /* set dst addr */ + h->ether_type = rte_cpu_to_be_16(ethertype); /* ethertype too */ + +#if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1 + { + char dst[ETHER_ADDR_FMT_SIZE] = "(empty)"; + char src[ETHER_ADDR_FMT_SIZE] = "(empty)"; + + nlog("*** packet for TX below (len %d) ***", rte_pktmbuf_pkt_len(mb)); + ether_format_addr(src, sizeof(src), &h->s_addr); + ether_format_addr(dst, sizeof(dst), &h->d_addr); + nlog("src: %s dst: %s ethertype: %.4X", src, dst, ethertype); + } +#endif +#ifdef VLAN_SUPPORT + mb->vlan_tci = vlan_tci; + dlog("Inserting vlan tag of %d", vlan_tci); + rte_vlan_insert(&mb); +#endif +} + +int xran_send_message_burst(int dst_id, int pkt_type, void *body, int len) +{ + struct rte_mbuf *mbufs[BURST_SIZE]; + int i; + uint8_t *src = body; + const struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx(); + + /* We're limited by maximum mbuf size on the receive size. + * We can change this but this would be a bigger rework. */ + RTE_ASSERT(len < MBUF_POOL_ELM_BIG); + + /* Allocate the required number of mbufs. */ + const uint8_t count = ceilf((float)len / MAX_DATA_SIZE); + if (rte_pktmbuf_alloc_bulk(_eth_mbuf_pool, mbufs, count) != 0) + rte_panic("Failed to allocate %d mbufs\n", count); + + nlog("burst transfer with data size %lu", MAX_DATA_SIZE); + for (i = 0; len > 0; ++i) { + char *p; + struct burst_hdr *bhdr; + struct ethdi_hdr *edi_hdr; + + /* Setup the ethdi_hdr. */ + edi_hdr = (void *)rte_pktmbuf_append(mbufs[i], sizeof(*edi_hdr)); + if (edi_hdr == NULL) + rte_panic("append of ethdi_hdr failed\n"); + edi_hdr->pkt_type = PKT_BURST; + /* edi_hdr->source_id setup in tx_from_ring */ + edi_hdr->dest_id = dst_id; + + /* Setup the burst header */ + bhdr = (void *)rte_pktmbuf_append(mbufs[i], sizeof(*bhdr)); + if (bhdr == NULL) /* append failed. */ + rte_panic("mbuf prepend of burst_hdr failed\n"); + bhdr->original_type = pkt_type; + bhdr->pkt_idx = i; /* save the index of the burst chunk. */ + bhdr->total_pkts = count; + + /* now copy in the actual data */ + const int curr_data_len = RTE_MIN(len, MAX_TX_LEN - + rte_pktmbuf_pkt_len(mbufs[i]) - sizeof(struct ether_hdr)); + p = (void *)rte_pktmbuf_append(mbufs[i], curr_data_len); + if (p == NULL) + rte_panic("mbuf append of %d data bytes failed\n", curr_data_len); + /* This copy is unavoidable, as we're splitting one big buffer + * into multiple mbufs. */ + rte_memcpy(p, src, curr_data_len); + + dlog("curr_data_len[%d] = %d", i, curr_data_len); + dlog("packet %d size %d", i, rte_pktmbuf_pkt_len(mbufs[i])); + + /* Update our source data pointer and remaining length. */ + len -= curr_data_len; + src += curr_data_len; + } + + /* Now enqueue the full prepared burst. */ + i = rte_ring_enqueue_bulk(ctx->tx_ring[0], (void **)mbufs, count, NULL); + PANIC_ON(i != count, "failed to enqueue all mbufs: %d/%d", i, count); + dlog("%d packets enqueued on port %d.", count, ctx->io_cfg.port); + + return 1; +} diff --git a/fhi_lib/lib/ethernet/ethernet.h b/fhi_lib/lib/ethernet/ethernet.h new file mode 100644 index 0000000..b22aed8 --- /dev/null +++ b/fhi_lib/lib/ethernet/ethernet.h @@ -0,0 +1,165 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file has all definitions for the Ethernet Data Interface Layer + * @file ethernet.h + * @ingroup group_lte_source_auxlib + * @author Intel Corporation + **/ + +#ifndef AUXLIB_ETHERNET_H +#define AUXLIB_ETHERNET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define BURST_SIZE 64 + +//#define VLAN_SUPPORT +#define FLEXRAN_UP_VLAN_TAG 2 +#define ETHER_TYPE_ETHDI ETHER_TYPE_IPv4 /* hack needed for jumbo frames */ +#define ETHER_TYPE_ECPRI 0xAEFE +#define ETHER_TYPE_SYNC 0xBEFE +#define ETHER_TYPE_START_TX 0xCEFE + +#define NUM_MBUFS 262144 +#define MBUF_CACHE 256 + +#define MBUF_POOL_ELM_SMALL 1500 /* regular ethernet MTU, most compatible */ +#define MBUF_POOL_ELEMENT MAX_RX_LEN + +#define MAX_RX_LEN 9600 +#define MAX_TX_LEN (MAX_RX_LEN - 14) /* headroom for rx driver */ +#define MAX_DATA_SIZE (MAX_TX_LEN - sizeof(struct ether_hdr) - \ + sizeof(struct ethdi_hdr) - sizeof(struct burst_hdr)) + +/* Looks like mbuf size is limited to 16 bits - see the buf_len field. */ +#define MBUF_POOL_ELM_BIG USHRT_MAX +#define NUM_MBUFS_BIG 64 + +#define DEFAULT_DUMP_LENGTH 96 + +extern struct rte_mempool *_eth_mbuf_pool; +extern struct rte_mempool *_eth_mbuf_pool_small; +extern struct rte_mempool *_eth_mbuf_pool_big; + +/* Do NOT change the order of this enum and below + * - need to be in sync with the table of handlers in testue.c */ +enum pkt_type +{ + PKT_ZERO, + PKT_EMPTY, + PKT_DISCOVER_REQUEST, + PKT_PING, + PKT_PONG, + PKT_DISCOVER_REPLY, + PKT_LTE_DATA, + PKT_LTE_CONTROL, + PKT_BURST, + PKT_DATATEST, + PKT_ADD_ETHDEV, + PKT_SYNC_START, + PKT_LAST, +}; + +/* Do NOT change the order. */ +static char * const xran_pkt_descriptions[PKT_LAST + 1] = { + "ZERO", + "empty packet", + "discovery request packet", + "ping packet", + "pong packet", + "discovery reply packet", + "LTE data packet", + "LTE control packet", + "BURST packet", + "DATATEST packet", + "Add ethernet port command packet", + "SYNC-START packet", + "LAST packet", +}; + +struct burst_hdr { + int8_t pkt_idx; + int8_t total_pkts; + int8_t original_type; + int8_t data[]; +}; + +struct ethdi_hdr { + uint8_t pkt_type; + uint8_t source_id; + uint8_t dest_id; + int8_t data[]; /* original raw data starts here! */ +}; + + +void xran_init_mbuf_pool(void); + +void xran_init_port(int port, struct ether_addr *p_lls_cu_addr); + +void xran_add_eth_hdr_vlan(struct ether_addr *dst, uint16_t ethertype, struct rte_mbuf *mb, uint16_t vlan_tci); +int xran_send_mbuf(struct ether_addr *dst, struct rte_mbuf *mb); + +int xran_send_message_burst(int dst_id, int pkt_type, void *body, int len); + +void xran_memdump(void *addr, int len); + +/* + * Print a message after all critical processing done. + * Mt-safe. 4 variants - normal, warning, error and debug log. + */ + +#define nlog(m, ...) +#define delayed_message /* this is the old alias for this function */ +#define wlog(m, ...) +#define elog(m, ...) +#ifdef DEBUG +# define dlog(m, ...) +#else +# define dlog(m, ...) +#endif + +#define PANIC_ON(x, m, ...) do { if (unlikely(x)) \ + rte_panic("%s: " m "\n", #x, ##__VA_ARGS__); } while (0) + +/* Add mbuf to the TX ring. */ +static inline int xran_enqueue_mbuf(struct rte_mbuf *mb, struct rte_ring *r) +{ + if (rte_ring_enqueue(r, mb) == 0) { + return 1; /* success */ + } + + rte_pktmbuf_free(mb); + wlog("failed to enqueue packet on port %d (ring full)", mb->port); + + return 0; /* fail */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* AUXLIB_ETHERNET_H */ diff --git a/fhi_lib/lib/src/mlog_lnx_xRAN.h b/fhi_lib/lib/src/mlog_lnx_xRAN.h new file mode 100644 index 0000000..5494045 --- /dev/null +++ b/fhi_lib/lib/src/mlog_lnx_xRAN.h @@ -0,0 +1,55 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +#ifndef _MLOG_LNX_XRAN_H_ +#define _MLOG_LNX_XRAN_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MLOG_FALSE ( 0 ) + +#define MLogOpen(a, b, c, d, e) MLOG_FALSE +#define MLogRestart(a) MLOG_FALSE +#define MLogPrint(a) MLOG_FALSE +#define MLogGetFileLocation() NULL +#define MLogGetFileSize() 0 +#define MLogSetMask(a) MLOG_FALSE +#define MLogGetMask() +#define MLogRegisterTick() +#define MLogTick() 0 +#define MLogIncrementCounter() 0 +#define MLogTask(w,x,y) 0 +#define MLogTaskCore(w,x,y,z) 0 +#define MLogMark(x,y) +#define MLogDevInfo(x) +#define MLogRegisterFrameSubframe(x,y) +#define MLogAddVariables(x,y,z) +#define MLogGetStats(a, b, c, d, e) MLOG_FALSE +#define MLogGetAvgStats(a, b, c, d) MLOG_FALSE +#define MLogAddTestCase(a, b) MLOG_FALSE +#define MLogAddPowerStats(a, b, c, d, e) MLOG_FALSE + +#ifdef __cplusplus +} +#endif /* #ifdef __cplusplus */ + +#endif /* #ifndef _MLOG_LNX_H_ */ + diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c new file mode 100644 index 0000000..67079e2 --- /dev/null +++ b/fhi_lib/lib/src/xran_common.c @@ -0,0 +1,397 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +#ifndef _XRAN_COMMON_ +#define _XRAN_COMMON_ + +/** + * @brief XRAN layer common functionality for both lls-CU and RU as well as C-plane and + * U-plane + * @file xran_common.c + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#include +#include +#include +#include +#include + +#include "xran_common.h" +#include "ethdi.h" +#include "xran_pkt.h" +#include "xran_pkt_up.h" +#include "xran_cp_api.h" +#include "xran_up_api.h" +#include "../src/xran_printf.h" + +#ifndef MLOG_ENABLED +#include "mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif + +#define MBUFS_CNT 256 + +extern int xran_process_rx_sym(void *arg, + void *iq_data_start, + uint16_t size, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t frame_id, + uint8_t subframe_id, + uint8_t slot_id, + uint8_t symb_id); + + +int process_mbuf(struct rte_mbuf *pkt) +{ + void *iq_samp_buf; + struct ecpri_seq_id seq; + static int symbol_total_bytes = 0; + int num_bytes = 0; + struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx(); + uint8_t CC_ID = 0; + uint8_t Ant_ID = 0; + uint8_t frame_id = 0; + uint8_t subframe_id = 0; + uint8_t slot_id = 0; + uint8_t symb_id = 0; + + num_bytes = xran_extract_iq_samples(pkt, + &iq_samp_buf, + &CC_ID, + &Ant_ID, + &frame_id, + &subframe_id, + &slot_id, + &symb_id, + &seq); + if (num_bytes <= 0) + return -1; + + symbol_total_bytes += num_bytes; + + if (seq.e_bit == 1) { + print_dbg("Completed receiving symbol %d, size=%d bytes\n", + symb_id, symbol_total_bytes); + + if (symbol_total_bytes) + xran_process_rx_sym(NULL, + iq_samp_buf, + symbol_total_bytes, + CC_ID, + Ant_ID, + frame_id, + subframe_id, + slot_id, + symb_id); + symbol_total_bytes = 0; + } + + return 0; +} + +static int set_iq_bit_width(uint8_t iq_bit_width, struct data_section_compression_hdr *compr_hdr) +{ + if (iq_bit_width == MAX_IQ_BIT_WIDTH) + compr_hdr->ud_comp_hdr.ud_iq_width = (uint8_t) 0; + else + compr_hdr->ud_comp_hdr.ud_iq_width = iq_bit_width; + + return 0; + +} + +/* Send a single 5G symbol over multiple packets */ +int send_symbol_ex(enum xran_pkt_dir direction, + uint16_t section_id, + struct rb_map *data, + uint8_t frame_id, + uint8_t subframe_id, + uint8_t slot_id, + uint8_t symbol_no, + int prb_start, + int prb_num, + uint8_t CC_ID, + uint8_t RU_Port_ID, + uint8_t seq_id) +{ + const int n_bytes = prb_num * N_SC_PER_PRB * sizeof(struct rb_map); + int sent; + uint32_t off; + struct xran_up_pkt_gen_no_compression_params xp = { 0 }; + + /* radio app header */ + xp.app_params.data_direction = direction; + xp.app_params.payl_ver = 1; + xp.app_params.filter_id = 0; + xp.app_params.frame_id = frame_id; + xp.app_params.sf_slot_sym.subframe_id = subframe_id; + xp.app_params.sf_slot_sym.slot_id = slot_id; + xp.app_params.sf_slot_sym.symb_id = symbol_no; + + /* convert to network byte order */ + xp.app_params.sf_slot_sym.value = rte_cpu_to_be_16(xp.app_params.sf_slot_sym.value); + + xp.sec_hdr.fields.sect_id = section_id; + xp.sec_hdr.fields.num_prbu = (uint8_t)prb_num; + xp.sec_hdr.fields.start_prbu = (uint8_t)prb_start; + xp.sec_hdr.fields.sym_inc = 0; + xp.sec_hdr.fields.rb = 0; + + /* network byte order */ + xp.sec_hdr.fields.all_bits = rte_cpu_to_be_32(xp.sec_hdr.fields.all_bits); + + struct rte_mbuf *mb = xran_ethdi_mbuf_alloc(); + + if (mb == NULL){ + MLogPrint(NULL); + errx(1, "out of mbufs after %d packets", 1); + } + + sent = xran_prepare_iq_symbol_portion_no_comp(mb, + data, + n_bytes, + &xp, + CC_ID, + RU_Port_ID, + seq_id); + if (sent <= 0) + errx(1, "failed preparing symbol"); + + xran_ethdi_mbuf_send(mb, ETHER_TYPE_ECPRI); + +#ifdef DEBUG + printf("Symbol %2d sent (%d packets, %d bytes)\n", symbol_no, i, n_bytes); +#endif + + return sent; +} + +int send_cpmsg_dlul(void *pHandle, enum xran_pkt_dir dir, + uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id, + uint8_t startsym, uint8_t numsym, int prb_num, + uint16_t beam_id, + uint8_t cc_id, uint8_t ru_port_id, + uint8_t seq_id) +{ + struct xran_cp_gen_params params; + struct xran_section_gen_info sect_geninfo[XRAN_MAX_NUM_SECTIONS]; + struct rte_mbuf *mbuf; + int ret, nsection, i; + + + params.dir = dir; + params.sectionType = XRAN_CP_SECTIONTYPE_1; // Most DL/UL Radio Channels + params.hdr.filterIdx = XRAN_FILTERINDEX_STANDARD; + params.hdr.frameId = frame_id; + params.hdr.subframeId = subframe_id; + params.hdr.slotId = slot_id; + params.hdr.startSymId = startsym; // start Symbol ID + params.hdr.iqWidth = xran_get_conf_iqwidth(pHandle); + params.hdr.compMeth = xran_get_conf_compmethod(pHandle); + + nsection = 0; + sect_geninfo[nsection].info.type = params.sectionType; + sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id); + sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY; + sect_geninfo[nsection].info.symInc = XRAN_SYMBOLNUMBER_NOTINC; + sect_geninfo[nsection].info.startPrbc = 0; + sect_geninfo[nsection].info.numPrbc = NUM_OF_PRB_IN_FULL_BAND, + sect_geninfo[nsection].info.numSymbol = numsym; + sect_geninfo[nsection].info.reMask = 0xfff; + sect_geninfo[nsection].info.beamId = beam_id; + + sect_geninfo[nsection].info.ef = 0; // no extension + sect_geninfo[nsection].exDataSize = 0; + sect_geninfo[nsection].exData = NULL; + nsection++; + + params.numSections = nsection; + params.sections = sect_geninfo; + + mbuf = xran_ethdi_mbuf_alloc(); + if(unlikely(mbuf == NULL)) { + print_err("Alloc fail!\n"); + return (-1); + } + + ret = xran_prepare_ctrl_pkt(mbuf, ¶ms, cc_id, ru_port_id, seq_id); + if(ret < 0) { + print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n", + frame_id, subframe_id, slot_id, dir); + } + else { + xran_ethdi_mbuf_send_cp(mbuf, ETHER_TYPE_ECPRI); + for(i=0; iPrachCPConfig); + +#if 0 + printf("%d:%d:%d:%d - filter=%d, startSym=%d[%d:%d], numSym=%d, occasions=%d, freqOff=%d\n", + frame_id, subframe_id, slot_id, prach_port_id, + pPrachCPConfig->filterIdx, + pPrachCPConfig->startSymId, + pPrachCPConfig->startPrbc, + pPrachCPConfig->numPrbc, + pPrachCPConfig->numSymbol, + pPrachCPConfig->occassionsInPrachSlot, + pPrachCPConfig->freqOffset); +#endif + + params.dir = XRAN_DIR_UL; + params.sectionType = XRAN_CP_SECTIONTYPE_3; + params.hdr.filterIdx = pPrachCPConfig->filterIdx; + params.hdr.frameId = frame_id; + params.hdr.subframeId = subframe_id; + params.hdr.slotId = slot_id; + params.hdr.startSymId = pPrachCPConfig->startSymId; + params.hdr.iqWidth = xran_get_conf_iqwidth(pHandle); + params.hdr.compMeth = xran_get_conf_compmethod(pHandle); + /* use timeOffset field for the CP length value for prach sequence */ + params.hdr.timeOffset = pPrachCPConfig->timeOffset; + params.hdr.fftSize = xran_get_conf_fftsize(pHandle); + params.hdr.scs = xran_get_conf_prach_scs(pHandle); + params.hdr.cpLength = 0; + + nsection = 0; + sect_geninfo[nsection].info.type = params.sectionType; + sect_geninfo[nsection].info.id = xran_alloc_sectionid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id); + sect_geninfo[nsection].info.rb = XRAN_RBIND_EVERY; + sect_geninfo[nsection].info.symInc = XRAN_SYMBOLNUMBER_NOTINC; + sect_geninfo[nsection].info.startPrbc = pPrachCPConfig->startPrbc; + sect_geninfo[nsection].info.numPrbc = pPrachCPConfig->numPrbc, + sect_geninfo[nsection].info.numSymbol = pPrachCPConfig->numSymbol*pPrachCPConfig->occassionsInPrachSlot; + sect_geninfo[nsection].info.reMask = 0xfff; + sect_geninfo[nsection].info.beamId = beam_id; + sect_geninfo[nsection].info.freqOffset= pPrachCPConfig->freqOffset; + + sect_geninfo[nsection].info.ef = 0; // no extension + sect_geninfo[nsection].exDataSize = 0; + sect_geninfo[nsection].exData = NULL; + nsection++; + + params.numSections = nsection; + params.sections = sect_geninfo; + + mbuf = xran_ethdi_mbuf_alloc(); + if(unlikely(mbuf == NULL)) { + print_err("Alloc fail!\n"); + return (-1); + } + + ret = xran_prepare_ctrl_pkt(mbuf, ¶ms, cc_id, prach_port_id, seq_id); + if(ret < 0) { + print_err("Fail to build prach control packet - [%d:%d:%d]\n", frame_id, subframe_id, slot_id); + return (ret); + } + else { + xran_ethdi_mbuf_send_cp(mbuf, ETHER_TYPE_ECPRI); + for(i=0; i < nsection; i++) + xran_cp_add_section_info(pHandle, + XRAN_DIR_UL, cc_id, prach_port_id, subframe_id, slot_id, + §_geninfo[i].info); + } + + return (ret); +} + + +int process_ring(struct rte_ring *r) +{ + assert(r); + + struct rte_mbuf *mbufs[MBUFS_CNT]; + int i; + uint32_t remaining; + const uint16_t dequeued = rte_ring_dequeue_burst(r, (void **)mbufs, + RTE_DIM(mbufs), &remaining); + + if (!dequeued) + return 0; + for (i = 0; i < dequeued; ++i) { + if (xran_ethdi_filter_packet(mbufs[i], 0) == MBUF_FREE) + rte_pktmbuf_free(mbufs[i]); + } + + return remaining; +} + +int ring_processing_thread(void *args) +{ + struct timespec tv = {0}; + int64_t prev_nsec = 0; + uint8_t is_timer_set = 0; + struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx(); + struct sched_param sched_param; + int res = 0; + + printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid()); + sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO; + if ((res = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched_param))) + { + printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res); + } + for (;;) { + if (!is_timer_set) { + if (clock_gettime(CLOCK_REALTIME, &tv) != 0) + err(1, "gettimeofday() failed"); + if (tv.tv_nsec % 125000 < prev_nsec % 125000) { /* crossed an 125ms boundary */ + rte_timer_manage(); /* timers only run on IO core */ + is_timer_set = 1; + } + prev_nsec = tv.tv_nsec; + } else { + rte_timer_manage(); + } + + /* UP first */ + if (process_ring(ctx->rx_ring[ETHDI_UP_VF])) + continue; + /* CP next */ + if (process_ring(ctx->rx_ring[ETHDI_CP_VF])) + continue; + + if (XRAN_STOPPED == xran_if_current_state) + break; + } + + puts("Pkt processing thread finished."); + return 0; +} + +#endif /* _XRAN_COMMON_ */ diff --git a/fhi_lib/lib/src/xran_common.h b/fhi_lib/lib/src/xran_common.h new file mode 100644 index 0000000..ad17c1e --- /dev/null +++ b/fhi_lib/lib/src/xran_common.h @@ -0,0 +1,300 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief XRAN layer common functionality for both lls-CU and RU as well as C-plane and + * U-plane + * @file xran_common.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#ifndef _XRAN_COMMON_H_ +#define _XRAN_COMMON_H_ + +#include +#include + +#include +#include +#include + +#include "xran_fh_lls_cu.h" +#include "xran_pkt_up.h" + +#define APP_LLS_CU 0 +#define APP_RU 1 +#define NUM_OF_PRB_IN_FULL_BAND (66) +#define N_SC_PER_PRB 12 +#define N_SYM_PER_SLOT 14 +#define N_FULLBAND_SC (NUM_OF_PRB_IN_FULL_BAND*N_SC_PER_PRB) +#define MAX_ANT_CARRIER_SUPPORTED 16 +/* 0.125, just for testing */ +#define SLOTNUM_PER_SUBFRAME 8 +#define SUBFRAMES_PER_SYSTEMFRAME 10 +#define SLOTS_PER_SYSTEMFRAME (SLOTNUM_PER_SUBFRAME*SUBFRAMES_PER_SYSTEMFRAME) +#define PDSCH_PAYLOAD_SIZE (N_FULLBAND_SC*4) +#define NUM_OF_SLOT_IN_TDD_LOOP (80) +#define IQ_PLAYBACK_BUFFER_BYTES (NUM_OF_SLOT_IN_TDD_LOOP*N_SYM_PER_SLOT*N_FULLBAND_SC*4L) + +/* PRACH data samples are 32 bits wide, 16bits for I and 16bits for Q. Each packet contains 839 samples. The payload length is 3356 octets.*/ +#define PRACH_PLAYBACK_BUFFER_BYTES (10*839*4L) + +#define XRAN_MAX_NUM_SECTIONS (NUM_OF_PRB_IN_FULL_BAND) // TODO: need to decide proper value + +#define XRAN_MAX_MBUF_LEN 9600 /**< jummbo frame */ +#define NSEC_PER_SEC 1000000000 +#define TIMER_RESOLUTION_CYCLES 1596*1 /* 1us */ +#define XRAN_RING_SIZE 512 /*4*14*8 pow of 2 */ +#define XRAN_NAME_MAX_LEN (64) +#define XRAN_RING_NUM (3) + +#define MAX_NUM_OF_XRAN_CTX (2) +#define XranIncrementCtx(ctx) ((ctx >= (MAX_NUM_OF_XRAN_CTX-1)) ? 0 : (ctx+1)) +#define XranDecrementCtx(ctx) ((ctx == 0) ? (MAX_NUM_OF_XRAN_CTX-1) : (ctx-1)) + +#define XranDiffSymIdx(prevSymIdx, currSymIdx, numTotalSymIdx) ((prevSymIdx > currSymIdx) ? ((currSymIdx + numTotalSymIdx) - prevSymIdx) : (currSymIdx - prevSymIdx)) + +#define XRAN_SYM_JOB_SIZE 512 + +struct send_symbol_cb_args +{ + struct rb_map *samp_buf; + uint8_t *symb_id; +}; + +struct pkt_dump +{ + int num_samp; + int num_bytes; + uint8_t symb; + struct ecpri_seq_id seq; +} __rte_packed; + +/* PRACH configuration table defines */ +#define XRAN_PRACH_CANDIDATE_PREAMBLE (2) +#define XRAN_PRACH_CANDIDATE_Y (2) +#define XRAN_PRACH_CANDIDATE_SLOT (40) +#define XRAN_PRACH_CONFIG_TABLE_SIZE (256) +#define XRAN_PRACH_PREAMBLE_FORMAT_OF_ABC (9) +typedef enum +{ + FORMAT_0 = 0, + FORMAT_1, + FORMAT_2, + FORMAT_3, + FORMAT_A1, + FORMAT_A2, + FORMAT_A3, + FORMAT_B1, + FORMAT_B2, + FORMAT_B3, + FORMAT_B4, + FORMAT_C0, + FORMAT_C2, + FORMAT_LAST +}PreambleFormatEnum; + +/* add PRACH used config table, same structure as used in refPHY */ +typedef struct +{ + uint8_t prachConfigIdx; + uint8_t preambleFmrt[XRAN_PRACH_CANDIDATE_PREAMBLE]; + uint8_t x; + uint8_t y[XRAN_PRACH_CANDIDATE_Y]; + uint8_t slotNr[XRAN_PRACH_CANDIDATE_SLOT]; + uint8_t slotNrNum; + uint8_t startingSym; + uint8_t nrofPrachInSlot; + uint8_t occassionsInPrachSlot; + uint8_t duration; +} xRANPrachConfigTableStruct; + +typedef struct +{ + uint8_t preambleFmrt; + uint16_t lRALen; + uint8_t fRA; + uint32_t nu; + uint16_t nRaCp; +}xRANPrachPreambleLRAStruct; + +typedef struct +{ + uint8_t filterIdx; + uint8_t startSymId; + uint16_t startPrbc; + uint8_t numPrbc; + uint8_t numSymbol; + uint16_t timeOffset; + int32_t freqOffset; + uint8_t occassionsInPrachSlot; + uint8_t x; + uint8_t y[XRAN_PRACH_CANDIDATE_Y]; + uint8_t isPRACHslot[XRAN_PRACH_CANDIDATE_SLOT]; +}xRANPrachCPConfigStruct; + + +typedef struct DeviceHandleInfo +{ + /**< Structure that contains the information to describe the + * instance i.e service type, virtual function, package Id etc..*/ + uint16_t nIndex; + /* Unique ID of an handle shared between phy layer and library */ + /**< number of antennas supported per link*/ + uint32_t nBufferPoolIndex; + /**< Buffer poolIndex*/ + struct rte_mempool * p_bufferPool[XRAN_MAX_SECTOR_NR]; + uint32_t bufferPoolElmSz[XRAN_MAX_SECTOR_NR]; + uint32_t bufferPoolNumElm[XRAN_MAX_SECTOR_NR]; + +}XranLibHandleInfoStruct; + +typedef void (*XranSymCallbackFn)(struct rte_timer *tim, void* arg); + +/* + * manage one cell's all Ethernet frames for one DL or UL LTE subframe + */ +typedef struct { + /* -1-this subframe is not used in current frame format + 0-this subframe can be transmitted, i.e., data is ready + 1-this subframe is waiting transmission, i.e., data is not ready + 10 - DL transmission missing deadline. When FE needs this subframe data but bValid is still 1, + set bValid to 10. + */ + int32_t bValid ; // when UL rx, it is subframe index. + int32_t nSegToBeGen; + int32_t nSegGenerated; // how many date segment are generated by DL LTE processing or received from FE + // -1 means that DL packet to be transmitted is not ready in BS + int32_t nSegTransferred; // number of data segments has been transmitted or received + struct rte_mbuf *pData[XRAN_N_MAX_BUFFER_SEGMENT]; // point to DPDK allocated memory pool + XRANBufferListStruct sBufferList; +} BbuIoBufCtrlStruct; + +struct xran_sym_job { + uint32_t sym_idx; + uint32_t status; +}__rte_cache_aligned; + +#define XranIncrementJob(i) ((i >= (XRAN_SYM_JOB_SIZE-1)) ? 0 : (i+1)) + +struct xran_lib_ctx +{ + uint8_t llscu_id; + uint8_t sector_id; + XRANEAXCIDCONFIG eAxc_id_cfg; + XRANFHINIT xran_init_cfg; + XRANFHCONFIG xran_fh_cfg; + XranLibHandleInfoStruct* pDevHandle; + xRANPrachCPConfigStruct PrachCPConfig; + uint32_t enableCP; + char ring_name[XRAN_RING_NUM][XRAN_MAX_SECTOR_NR][RTE_RING_NAMESIZE]; + struct rte_ring *dl_sym_idx_ring[XRAN_MAX_SECTOR_NR]; + struct rte_ring *xran2phy_ring[XRAN_MAX_SECTOR_NR]; + struct rte_ring *xran2prach_ring[XRAN_MAX_SECTOR_NR]; + + struct xran_sym_job sym_job[XRAN_SYM_JOB_SIZE]; + uint32_t sym_job_idx; + + BbuIoBufCtrlStruct sFrontHaulTxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + BbuIoBufCtrlStruct sFrontHaulRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + BbuIoBufCtrlStruct sFHPrachRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR]; + + /* buffers lists */ + XRANFlatBufferStruct sFrontHaulTxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + XRANFlatBufferStruct sFrontHaulRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + XRANFlatBufferStruct sFHPrachRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + + XranTransportBlockCallbackFn pCallback[XRAN_MAX_SECTOR_NR]; + void *pCallbackTag[XRAN_MAX_SECTOR_NR]; + + XranTransportBlockCallbackFn pPrachCallback[XRAN_MAX_SECTOR_NR]; + void *pPrachCallbackTag[XRAN_MAX_SECTOR_NR]; + + XranSymCallbackFn pSymCallback[XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + void *pSymCallbackTag[XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + + int32_t sym_up; /**< when we start sym 0 of up with respect to OTA time as measured in symbols */ + int32_t sym_up_ul; + + XRANFHTTIPROCCB ttiCb[XRAN_CB_MAX]; + void *TtiCbParam[XRAN_CB_MAX]; + uint32_t SkipTti[XRAN_CB_MAX]; + + int xran2phy_mem_ready; + + int rx_packet_symb_tracker[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT]; + int rx_packet_callback_tracker[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR]; + int phy_tti_cb_done; +}; + +extern const xRANPrachConfigTableStruct gxranPrachDataTable_sub6_fdd[XRAN_PRACH_CONFIG_TABLE_SIZE]; +extern const xRANPrachConfigTableStruct gxranPrachDataTable_sub6_tdd[XRAN_PRACH_CONFIG_TABLE_SIZE]; +extern const xRANPrachConfigTableStruct gxranPrachDataTable_mmw[XRAN_PRACH_CONFIG_TABLE_SIZE]; +extern const xRANPrachPreambleLRAStruct gxranPreambleforLRA[XRAN_PRACH_PREAMBLE_FORMAT_OF_ABC]; + +int process_mbuf(struct rte_mbuf *pkt); +int process_ring(struct rte_ring *r); +int ring_processing_thread(void *args); +int packets_dump_thread(void *args); + +int send_symbol_ex(enum xran_pkt_dir direction, + uint16_t section_id, + struct rb_map *data, + uint8_t frame_id, + uint8_t subframe_id, + uint8_t slot_id, + uint8_t symbol_no, + int prb_start, + int prb_num, + uint8_t CC_ID, + uint8_t RU_Port_ID, + uint8_t seq_id); + +int send_cpmsg_dlul(void *pHandle, enum xran_pkt_dir dir, + uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id, + uint8_t startsym, uint8_t numsym, int prb_num, + uint16_t beam_id, uint8_t cc_id, uint8_t ru_port_id, + uint8_t seq_id); + +int send_cpmsg_prach(void *pHandle, + uint8_t frame_id, uint8_t subframe_id, uint8_t slot_id, + uint16_t beam_id, uint8_t cc_id, uint8_t prach_port_id, + uint8_t seq_id); + +uint8_t xran_get_max_sections(void *pHandle); + +XRANEAXCIDCONFIG *xran_get_conf_eAxC(void *pHandle); +uint8_t xran_get_conf_prach_scs(void *pHandle); +uint8_t xran_get_conf_fftsize(void *pHandle); +uint8_t xran_get_conf_numerology(void *pHandle); +uint8_t xran_get_conf_iqwidth(void *pHandle); +uint8_t xran_get_conf_compmethod(void *pHandle); + +uint8_t xran_get_num_cc(void *pHandle); +uint8_t xran_get_num_eAxc(void *pHandle); +uint8_t xran_get_llscuid(void *pHandle); +uint8_t xran_get_sectorid(void *pHandle); +struct xran_lib_ctx *xran_lib_get_ctx(void); + +uint16_t xran_alloc_sectionid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id); +uint8_t xran_get_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id); + +#endif + diff --git a/fhi_lib/lib/src/xran_cp_api.c b/fhi_lib/lib/src/xran_cp_api.c new file mode 100644 index 0000000..d42b22b --- /dev/null +++ b/fhi_lib/lib/src/xran_cp_api.c @@ -0,0 +1,1086 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the API functions to build Control Plane Messages + * for XRAN Front Haul layer as defined in XRAN-FH.CUS.0-v02.01. + * + * @file xran_cp_api.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include + +#include "xran_common.h" +#include "xran_transport.h" +#include "xran_cp_api.h" +#include "xran_hash.h" +#include "xran_printf.h" + + +struct xran_sectioninfo_db { + uint32_t max_num; + uint32_t cur_index; +#if defined(XRAN_CP_USES_HASHTABLE) + struct rte_hash *hash; +#endif + struct xran_section_info *list; + }; + + +static struct xran_sectioninfo_db *sectiondb[XRAN_DIR_MAX]; + +int xran_cp_init_sectiondb(void *pHandle) +{ + int i, j, k; + uint32_t size; + uint16_t cid; + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + for(i=0; i < XRAN_DIR_MAX; i++) { + size = (xran_get_num_cc(pHandle) * num_eAxc * sizeof(struct xran_sectioninfo_db)); + print_log("Allocation Size for Section DB : %d (%dx%dx%ld)", size + , xran_get_num_cc(pHandle) + , num_eAxc + , sizeof(struct xran_sectioninfo_db)); + sectiondb[i] = malloc(size); + + if(sectiondb[i] == NULL) { + print_err("Allocation Failed for Section DB!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + for(j=0; j < xran_get_num_cc(pHandle); j++) { // CC + for(k=0; k < num_eAxc; k++) { // antenna + ptr = sectiondb[i] + num_eAxc*j + k; + + ptr->max_num = xran_get_max_sections(pHandle); + ptr->cur_index = 0; + + // allicate array to store section information + size = sizeof(struct xran_section_info)*xran_get_max_sections(pHandle); + print_log("Allocation Size for list : %d (%ldx%d)", size, + sizeof(struct xran_section_info), + xran_get_max_sections(pHandle)); + ptr->list = malloc(size); + if(ptr-> list == NULL) { + print_err("Allocation Failed for Section DB!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + +#if defined(XRAN_CP_USES_HASHTABLE) + // Create hash table for section information + cid = rte_be_to_cpu_16(xran_compose_cid(xran_get_llscuid(pHandle), xran_get_sectorid(pHandle), j, k)); + print_log("Creating hash for %04X", cid); + ptr->hash = xran_section_init_hash(i, cid, xran_get_max_sections(pHandle)); +#endif + } + } + } + + return (XRAN_ERRCODE_OK); +} + +int xran_cp_free_sectiondb(void *pHandle) +{ + int i, j, k; + uint32_t size; + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + for(i=0; i < XRAN_DIR_MAX; i++) { + for(j=0; j < xran_get_num_cc(pHandle); j++) { // CC + for(k=0; k < num_eAxc; k++) { // antenna + ptr = sectiondb[i] + num_eAxc*j + k; + +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_free_hash(ptr->hash); +#endif + if(ptr->list != NULL) + free(ptr->list); + else print_err("list is NULL"); + } + } + if(sectiondb[i] != NULL) + free(sectiondb[i]); + else print_err("sectiondb[%d] is NULL", i); + } + + return (XRAN_ERRCODE_OK); +} + +static struct xran_sectioninfo_db *xran_get_section_db(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + struct xran_sectioninfo_db *ptr; + uint8_t num_eAxc; + + if(unlikely(dir>=XRAN_DIR_MAX)) { + print_err("Invalid direction - %d", dir); + return (NULL); + } + + if(unlikely(cc_id >= xran_get_num_cc(pHandle))) { + print_err("Invalid CC id - %d", cc_id); + return (NULL); + } + +#if !defined(PRACH_USES_SHARED_PORT) + num_eAxc = xran_get_num_eAxc(pHandle) * 2; +#else + num_eAxc = xran_get_num_eAxc(pHandle); +#endif + + if(unlikely(ruport_id >= num_eAxc)) { + print_err("Invalid eAxC id - %d", ruport_id); + return (NULL); + } + + ptr = sectiondb[dir] + xran_get_num_eAxc(pHandle)*cc_id + ruport_id; + + return(ptr); +} + +static struct xran_section_info *xran_get_section_info(struct xran_sectioninfo_db *ptr, uint16_t index) +{ + if(unlikely(ptr == NULL)) + return (NULL); + + if(unlikely(ptr->max_num < index)) { + print_err("Index is out of range - %d", index); + return (NULL); + } + + return(&(ptr->list[index])); +} + +int xran_cp_add_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + struct xran_section_info *info) +{ + struct xran_sectioninfo_db *ptr; + struct xran_section_info *list; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(ptr->cur_index >= ptr->max_num)) { + print_err("No more space to add section information!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + list = xran_get_section_info(ptr, ptr->cur_index); + + rte_memcpy(list, info, sizeof(struct xran_section_info)); +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_add_hash(ptr->hash, info->id, ptr->cur_index); +#endif + + ptr->cur_index++; + + return (XRAN_ERRCODE_OK); +} + +int xran_cp_add_multisection_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + uint8_t num_sections, struct xran_section_gen_info *gen_info) +{ + int i; + struct xran_sectioninfo_db *ptr; + struct xran_section_info *list; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(ptr->cur_index >= (ptr->max_num+num_sections))) { + print_err("No more space to add section information!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + list = xran_get_section_info(ptr, ptr->cur_index); + + for(i=0; ihash, gen_info[i].info.id, ptr->cur_index); +#endif + ptr->cur_index++; + } + + return (XRAN_ERRCODE_OK); +} + +struct xran_section_info *xran_cp_find_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, + uint16_t section_id) +{ + int index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (NULL); + +#if defined(XRAN_CP_USES_HASHTABLE) + index = xran_section_lookup(ptr->hash, section_id); + if(unlikely(index > ptr->max_num)) { + print_err("Invalid index - %d", index); + return (NULL); + } + + if(index < 0) { + print_dbg("No section ID in the list - %d", section_id); + return (NULL); + } + + return (xran_get_section_info(ptr, index)); +#else + for(index=0; indexcur_index; index++) { + if(ptr->list[index].id == section_id) { + print_dbg("Found section info %04X", section_id); + return (xran_get_section_info(ptr, index)); + } + } + + print_dbg("No section ID in the list - %d", section_id); + return (NULL); +#endif + +} + +struct xran_section_info *xran_cp_iterate_section_info(void *pHandle, + uint8_t dir, uint8_t cc_id, uint8_t ruport_id, + uint8_t subframe_id, uint8_t slot_id, uint32_t *next) +{ + int index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (NULL); + +#if defined(XRAN_CP_USES_HASHTABLE) + index = xran_section_iterate(ptr->hash, next); + if(unlikely(index > ptr->max_num)) { + print_err("Invalid index - %d", index); + return (NULL); + } + + if(index < 0) { + print_dbg("No section ID in the list - %d", section_id); + return (NULL); + } + + return (xran_get_section_info(ptr, index)); +#else + index = *next; + if(*next < ptr->cur_index) { + (*next)++; + return (xran_get_section_info(ptr, index)); + } + else + print_dbg("No more sections in the list"); + + return (NULL); +#endif +} + +int xran_cp_getsize_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + int i, index; + struct xran_sectioninfo_db *ptr; + + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) + return (-1); + + return (ptr->cur_index); +} + +int xran_cp_reset_section_info(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ruport_id) +{ + struct xran_sectioninfo_db *ptr; + + ptr = xran_get_section_db(pHandle, dir, cc_id, ruport_id); + if(unlikely(ptr == NULL)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + ptr->cur_index = 0; +#if defined(XRAN_CP_USES_HASHTABLE) + xran_section_reset_hash(ptr->hash); +#endif + + return (XRAN_ERRCODE_OK); +} + +int xran_dump_sectiondb(void) +{ + // TODO: + return (0); +} + + +// Cyclic Prefix Length 5.4.4.14 +// CP_length = cpLength * Ts * 2^u, Ts = 1/30.72MHz, if u is N/A, it shall be zero +#define CPLEN_TS (30720000) +inline uint16_t xran_get_cplength(int cpLength, int uval) // uval = -1 for N/A +{ + return ((cpLength * ((uval<0)?0:(2<>1); +} + + +/** + * @brief Fill the section body of type 0 in C-Plane packet + * + * @param section + * A pointer to the section in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section0( + struct xran_cp_radioapp_section0 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s0.reMask = params->info.reMask; + section->hdr.u.s0.numSymbol = params->info.numSymbol; + section->hdr.u.s0.reserved = 0; + + // for network byte order + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 0 in C-Plane packet + * + * @param s0hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section0_hdr( + struct xran_cp_radioapp_section0_header *s0hdr, + struct xran_cp_gen_params *params) + +{ + s0hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset); + s0hdr->frameStructure.fftSize = params->hdr.fftSize; + s0hdr->frameStructure.uScs = params->hdr.scs; + s0hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength); + s0hdr->reserved = 0; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief Fill the section body of type 1 in C-Plane packet + * Extension is not supported. + * + * @param section + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section1( + struct xran_cp_radioapp_section1 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s1.reMask = params->info.reMask; + section->hdr.u.s1.numSymbol = params->info.numSymbol; + section->hdr.u.s1.beamId = params->info.beamId; + + if(params->info.ef) { + // TODO: need to handle extension + print_err("Extension is not supported!"); + section->hdr.u.s1.ef = 0; +// section->hdr.u.s1.ef = params->info.ef; + } + else + section->hdr.u.s1.ef = 0; + + // for network byte order + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 1 in C-Plane packet + * + * @param s1hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section1_hdr( + struct xran_cp_radioapp_section1_header *s1hdr, + struct xran_cp_gen_params *params) +{ + s1hdr->udComp.udIqWidth = params->hdr.iqWidth; + s1hdr->udComp.udCompMeth = params->hdr.compMeth; + s1hdr->reserved = 0; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief Fill the section body of type 3 in C-Plane packet + * Extension is not supported. + * + * @param section + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section3( + struct xran_cp_radioapp_section3 *section, + struct xran_section_gen_info *params) +{ +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->info.numSymbol > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid number of Symbols - %d", params->info.numSymbol); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + section->hdr.sectionId = params->info.id; + section->hdr.rb = params->info.rb; + section->hdr.symInc = params->info.symInc; + section->hdr.startPrbc = params->info.startPrbc; + section->hdr.numPrbc = params->info.numPrbc; + + section->hdr.u.s3.reMask = params->info.reMask; + section->hdr.u.s3.numSymbol = params->info.numSymbol; + section->hdr.u.s3.beamId = params->info.beamId; + + section->freqOffset = rte_cpu_to_be_32(params->info.freqOffset)>>8; + section->reserved = 0; + + if(params->info.ef) { + // TODO: need to handle extension + print_err("Extension is not supported!"); + section->hdr.u.s3.ef = 0; +// section->hdr.u.s3.ef = params->info.ef; + } + else + section->hdr.u.s3.ef = 0; + + // for network byte order (header, 8 bytes) + *((uint64_t *)section) = rte_cpu_to_be_64(*((uint64_t *)section)); + + return (XRAN_ERRCODE_OK); +} +/** + * @brief Fill the section header of type 3 in C-Plane packet + * + * @param s3hdr + * A pointer to the section header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static int xran_prepare_section3_hdr( + struct xran_cp_radioapp_section3_header *s3hdr, + struct xran_cp_gen_params *params) + +{ + s3hdr->timeOffset = rte_cpu_to_be_16(params->hdr.timeOffset); + s3hdr->frameStructure.fftSize = params->hdr.fftSize; + s3hdr->frameStructure.uScs = params->hdr.scs; + s3hdr->cpLength = rte_cpu_to_be_16(params->hdr.cpLength); + s3hdr->udComp.udIqWidth = params->hdr.iqWidth; + s3hdr->udComp.udCompMeth = params->hdr.compMeth; + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief add sections to C-Plane packet + * Section type 1 and 3 are supported. + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +int xran_append_control_section(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params) +{ + int i, ret; + uint32_t totalen; + void *section; + int section_size; + int (*xran_prepare_section_func)(void *section, void *params); + + + totalen = 0; + switch(params->sectionType) { + case XRAN_CP_SECTIONTYPE_0: /* Unused RB or Symbols in DL or UL, not supportted */ + section_size = sizeof(struct xran_cp_radioapp_section0); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section0; + break; + + case XRAN_CP_SECTIONTYPE_1: /* Most DL/UL Radio Channels */ + section_size = sizeof(struct xran_cp_radioapp_section1); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section1; + break; + + case XRAN_CP_SECTIONTYPE_3: /* PRACH and Mixed-numerology Channels */ + section_size = sizeof(struct xran_cp_radioapp_section3); + xran_prepare_section_func = (int (*)(void *, void *))xran_prepare_section3; + break; + + case XRAN_CP_SECTIONTYPE_5: /* UE scheduling information, not supported */ + case XRAN_CP_SECTIONTYPE_6: /* Channel Information, not supported */ + case XRAN_CP_SECTIONTYPE_7: /* LAA, not supported */ + default: + section_size = 0; + xran_prepare_section_func = NULL; + print_err("Section Type %d is not supported!", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + if(unlikely(xran_prepare_section_func == NULL)) { + print_err("Section Type %d is not supported!", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + for(i=0; inumSections; i++) { + section = rte_pktmbuf_append(mbuf, section_size); + if(section == NULL) { + print_err("Fail to allocate the space for section[%d]!", i); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + if(unlikely(xran_prepare_section_func((void *)section, + (void *)¶ms->sections[i]) < 0)) { + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + totalen += section_size; + } + + return (totalen); +} + +/** + * @brief fill the information of a radio application header in a C-Plane packet + * + * @param apphdr + * A pointer to the application header in the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +static inline int xran_prepare_radioapp_common_header( + struct xran_cp_radioapp_common_header *apphdr, + struct xran_cp_gen_params *params) +{ + +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->dir != XRAN_DIR_DL && params->dir != XRAN_DIR_UL)) { + print_err("Invalid direction!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + if(unlikely(params->hdr.slotId > XRAN_SLOTID_MAX)) { + print_err("Invalid Slot ID!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + if(unlikely(params->hdr.startSymId > XRAN_SYMBOLNUMBER_MAX)) { + print_err("Invalid Symbol ID!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + apphdr->dataDirection = params->dir; + apphdr->payloadVer = XRAN_PAYLOAD_VER; + apphdr->filterIndex = params->hdr.filterIdx; + apphdr->frameId = params->hdr.frameId; + apphdr->subframeId = params->hdr.subframeId; + apphdr->slotId = params->hdr.slotId; + apphdr->startSymbolId = params->hdr.startSymId; + apphdr->numOfSections = params->numSections; + apphdr->sectionType = params->sectionType; + + // radio app header has common parts of 4bytes for all section types + *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr)); + + return (XRAN_ERRCODE_OK); +} + +/** + * @brief add a radio application header in a C-Plane packet + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @return + * 0 on success; non zero on failure + */ +int xran_append_radioapp_header(struct rte_mbuf *mbuf, struct xran_cp_gen_params *params) +{ + int ret; + uint32_t totalen; + struct xran_cp_radioapp_common_header *apphdr; + int (*xran_prepare_radioapp_section_hdr_func)(void *hdr, void *params); + + +#if (XRAN_STRICT_PARM_CHECK) + if(unlikely(params->sectionType >= XRAN_CP_SECTIONTYPE_MAX)) { + print_err("Invalid Section Type - %d", params->sectionType); + return (-XRAN_ERRCODE_INVALIDPARAM); + } +#endif + + switch(params->sectionType) { + case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section0_hdr; + totalen = sizeof(struct xran_cp_radioapp_section0_header); + break; + + case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section1_hdr; + totalen = sizeof(struct xran_cp_radioapp_section1_header); + break; + + case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels + xran_prepare_radioapp_section_hdr_func = (int (*)(void *, void*))xran_prepare_section3_hdr; + totalen = sizeof(struct xran_cp_radioapp_section3_header); + break; + + case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported + case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported + case XRAN_CP_SECTIONTYPE_7: // LAA, not supported + default: + print_err("Section Type %d is not supported!", params->sectionType); + xran_prepare_radioapp_section_hdr_func = NULL; + totalen = 0; + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + apphdr = (struct xran_cp_radioapp_common_header *)rte_pktmbuf_append(mbuf, totalen); + if(unlikely(apphdr == NULL)) { + print_err("Fail to reserve the space for radio application header!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + ret = xran_prepare_radioapp_common_header(apphdr, params); + if(unlikely(ret < 0)) { + return (ret); + } + + if(likely(xran_prepare_radioapp_section_hdr_func)) { + xran_prepare_radioapp_section_hdr_func(apphdr, params); + } + else { + print_err("xran_prepare_radioapp_section_hdr_func is NULL!"); + return (-XRAN_ERRCODE_INVALIDPARAM); + } + + return (totalen); +} + +/** + * @brief Create a C-Plane packet + * Transport layer fragmentation is not supported. + * + * @ingroup xran_cp_pkt + * + * @param mbuf + * A pointer to the packet buffer + * @param params + * A porinter to the information to generate a C-Plane packet + * @param CC_ID + * Component Carrier ID for this C-Plane message + * @param Ant_ID + * Antenna ID(RU Port ID) for this C-Plane message + * @param seq_id + * Sequence ID for this C-Plane message + * @return + * 0 on success; non zero on failure + */ +int xran_prepare_ctrl_pkt(struct rte_mbuf *mbuf, + struct xran_cp_gen_params *params, + uint8_t CC_ID, uint8_t Ant_ID, + uint8_t seq_id) +{ + int ret; + uint32_t payloadlen; + struct xran_ecpri_hdr *ecpri_hdr; + + + ecpri_hdr = (struct xran_ecpri_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr)); + if(unlikely(ecpri_hdr == NULL)) { + print_err("Fail to allocate the space for eCPRI hedaer!"); + return (-XRAN_ERRCODE_OUTOFMEMORY); + } + + ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER; + ecpri_hdr->ecpri_resv = 0; // should be zero + ecpri_hdr->ecpri_concat = 0; + ecpri_hdr->ecpri_mesg_type = ECPRI_RT_CONTROL_DATA; + ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID); + ecpri_hdr->ecpri_seq_id.seq_id = seq_id; + + /* TODO: Transport layer fragmentation is not supported */ + ecpri_hdr->ecpri_seq_id.sub_seq_id = 0; + ecpri_hdr->ecpri_seq_id.e_bit = 1; + + payloadlen = 0; + + ret = xran_append_radioapp_header(mbuf, params); + if(ret < 0) { + return (ret); + } + payloadlen += ret; + + ret = xran_append_control_section(mbuf, params); + if(ret < 0) { + return (ret); + } + payloadlen += ret; + +// printf("Total Payload length = %d\n", payloadlen); + ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(payloadlen); + + return (XRAN_ERRCODE_OK); +} + +/////////////////////////////////////// +// for Debug +int xran_parse_cp_pkt(struct rte_mbuf *mbuf, struct xran_cp_gen_params *result) +{ + struct xran_ecpri_hdr *ecpri_hdr; + struct xran_cp_radioapp_common_header *apphdr; + int i, ret; + int extlen; + + + ret = 0; + ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *); + if(ecpri_hdr == NULL) { + print_err("Invalid packet - eCPRI hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + /* Process eCPRI header. */ + if(ecpri_hdr->ecpri_ver != XRAN_ECPRI_VER) { + print_err("Invalid eCPRI version - %d", ecpri_hdr->ecpri_ver); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(ecpri_hdr->ecpri_resv != 0) { + print_err("Invalid reserved field - %d", ecpri_hdr->ecpri_resv); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(ecpri_hdr->ecpri_mesg_type != ECPRI_RT_CONTROL_DATA) { + print_err("Not C-Plane Message - %d", ecpri_hdr->ecpri_mesg_type); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } +#if 0 + printf("[CPlane] [%04X:%03d-%3d-%d] len=%5d\n", + rte_be_to_cpu_16(ecpri_hdr->ecpri_xtc_id), + ecpri_hdr->ecpri_seq_id.seq_id, ecpri_hdr->ecpri_seq_id.sub_seq_id, + ecpri_hdr->ecpri_seq_id.e_bit, + rte_be_to_cpu_16(ecpri_hdr->ecpri_payl_size)); +#endif + + /* Process radio header. */ + apphdr = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_ecpri_hdr)); + if(apphdr == NULL) { + print_err("Invalid packet - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + *((uint32_t *)apphdr) = rte_cpu_to_be_32(*((uint32_t *)apphdr)); + + if(apphdr->payloadVer != XRAN_PAYLOAD_VER) { + print_err("Invalid Payload version - %d", apphdr->payloadVer); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + result->dir = apphdr->dataDirection; + result->hdr.filterIdx = apphdr->filterIndex; + result->hdr.frameId = apphdr->frameId; + result->hdr.subframeId = apphdr->subframeId; + result->hdr.slotId = apphdr->slotId; + result->hdr.startSymId = apphdr->startSymbolId; + result->sectionType = apphdr->sectionType; + result->numSections = apphdr->numOfSections; + + switch(apphdr->sectionType) { + case XRAN_CP_SECTIONTYPE_0: // Unused RB or Symbols in DL or UL, not supportted + { + struct xran_cp_radioapp_section0_header *hdr; + struct xran_cp_radioapp_section0 *section; + + hdr = (struct xran_cp_radioapp_section0_header*)apphdr; + + result->hdr.fftSize = rte_be_to_cpu_16(hdr->timeOffset); + result->hdr.scs = hdr->frameStructure.fftSize; + result->hdr.timeOffset = hdr->frameStructure.uScs; + result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength); + //hdr->reserved; /* should be zero */ + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0_header)); + if(section == NULL) { + print_err("Invalid packet 0 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s0.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s0.reMask; + //section->hdr.u.s0.reserved; /* should be zero */ + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section0)); + if(section == NULL) { + print_err("Invalid packet 0 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_1: // Most DL/UL Radio Channels + { + struct xran_cp_radioapp_section1_header *hdr; + struct xran_cp_radioapp_section1 *section; + + hdr = (struct xran_cp_radioapp_section1_header*)apphdr; + + result->hdr.iqWidth = hdr->udComp.udIqWidth; + result->hdr.compMeth = hdr->udComp.udCompMeth; + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section1_header)); + if(section == NULL) { + print_err("Invalid packet 1 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s1.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s1.reMask; + result->sections[i].info.beamId = section->hdr.u.s1.beamId; + result->sections[i].info.ef = section->hdr.u.s1.ef; + + if(section->hdr.u.s1.ef) { + // TODO: handle section extension + extlen = 0; + } + else extlen = 0; + + section = (void *)rte_pktmbuf_adj(mbuf, + sizeof(struct xran_cp_radioapp_section1)+extlen); + if(section == NULL) { + print_err("Invalid packet 1 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_3: // PRACH and Mixed-numerology Channels + { + struct xran_cp_radioapp_section3_header *hdr; + struct xran_cp_radioapp_section3 *section; + + hdr = (struct xran_cp_radioapp_section3_header*)apphdr; + + result->hdr.timeOffset = rte_be_to_cpu_16(hdr->timeOffset); + result->hdr.scs = hdr->frameStructure.uScs; + result->hdr.fftSize = hdr->frameStructure.fftSize; + result->hdr.cpLength = rte_be_to_cpu_16(hdr->cpLength); + result->hdr.iqWidth = hdr->udComp.udIqWidth; + result->hdr.compMeth = hdr->udComp.udCompMeth; + + section = (void *)rte_pktmbuf_adj(mbuf, sizeof(struct xran_cp_radioapp_section3_header)); + if(section == NULL) { + print_err("Invalid packet 3 - radio app hedaer!"); + return (-XRAN_ERRCODE_INVALIDPACKET); + } + + for(i=0; inumSections; i++) { + *((uint64_t *)section) = rte_be_to_cpu_64(*((uint64_t *)section)); + + result->sections[i].info.type = apphdr->sectionType; + result->sections[i].info.id = section->hdr.sectionId; + result->sections[i].info.rb = section->hdr.rb; + result->sections[i].info.symInc = section->hdr.symInc; + result->sections[i].info.startPrbc = section->hdr.startPrbc; + result->sections[i].info.numPrbc = section->hdr.numPrbc, + result->sections[i].info.numSymbol = section->hdr.u.s3.numSymbol; + result->sections[i].info.reMask = section->hdr.u.s3.reMask; + result->sections[i].info.beamId = section->hdr.u.s3.beamId; + result->sections[i].info.ef = section->hdr.u.s3.ef; + result->sections[i].info.freqOffset = ((int32_t)rte_be_to_cpu_32(section->freqOffset))>>8; + + if(section->reserved) { + print_err("Invalid packet 3 - section[%d:%d]", i, section->reserved); + ret = -XRAN_ERRCODE_INVALIDPACKET; + } + + if(section->hdr.u.s3.ef) { + // TODO: handle section extension + extlen = 0; + } + else extlen = 0; + + section = (void *)rte_pktmbuf_adj(mbuf, + sizeof(struct xran_cp_radioapp_section3)+extlen); + if(section == NULL) { + print_err("Invalid packet 3 - number of section [%d:%d]!", + result->numSections, i); + result->numSections = i; + ret = (-XRAN_ERRCODE_INVALIDPACKET); + break; + } + } + } + break; + + case XRAN_CP_SECTIONTYPE_5: // UE scheduling information, not supported + case XRAN_CP_SECTIONTYPE_6: // Channel Information, not supported + case XRAN_CP_SECTIONTYPE_7: // LAA, not supported + default: + ret = -XRAN_ERRCODE_INVALIDPARAM; + print_err("Non-supported Section Type - %d", apphdr->sectionType); + } + +#if 0 + printf("[CP-%s] [%3d:%2d:%2d] section%d[%d] startSym=%d filterIdx=%X IQwidth=%d CompMeth=%d\n", + result->dir?"DL":"UL", + result->hdr.frameId, result->hdr.subframeId, result->hdr.slotId, + result->sectionType, result->numSections, + result->hdr.startSymId, + result->hdr.filterIdx, + result->hdr.iqWidth, result->hdr.compMeth); + + for(i=0; inumSections; i++) { + printf(" >> %3d:%04X| rb=%d symInc=%d numSym=%d startPrbc=%02X numPrbc=%d reMask=%03X beamId=%04X freqOffset=%d ef=%d\n", + i, result->sections[i].info.id, + result->sections[i].info.rb, + result->sections[i].info.symInc, result->sections[i].info.numSymbol, + result->sections[i].info.startPrbc, result->sections[i].info.numPrbc, + result->sections[i].info.reMask, + result->sections[i].info.beamId, + result->sections[i].info.freqOffset, + result->sections[i].info.ef); +// result->sections[i].info.type + } +#endif + + return(ret); +} + diff --git a/fhi_lib/lib/src/xran_hash.h b/fhi_lib/lib/src/xran_hash.h new file mode 100644 index 0000000..b06c694 --- /dev/null +++ b/fhi_lib/lib/src/xran_hash.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief Definitions and support functions to process XRAN packet + * @file xran_hash.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#ifndef _XRAN_HASH_H +#define _XRAN_HASH_H + +#include +#include +#include + +#define DEFAULT_HASH_FUNC rte_hash_crc + + +struct rte_hash *xran_section_init_hash(uint16_t dir, uint16_t cid, int max_num_sections); +void xran_section_free_hash(struct rte_hash *hash); + +void xran_section_reset_hash(struct rte_hash *hash); +int xran_section_add_hash(const struct rte_hash *hash, uint16_t section_id, int index); +int xran_section_lookup(const struct rte_hash *hash, uint16_t section_id); +int xran_section_iterate(const struct rte_hash *hash, uint32_t *next); + +#endif diff --git a/fhi_lib/lib/src/xran_lib_mlog_tasks_id.h b/fhi_lib/lib/src/xran_lib_mlog_tasks_id.h new file mode 100644 index 0000000..2c99c19 --- /dev/null +++ b/fhi_lib/lib/src/xran_lib_mlog_tasks_id.h @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief This file has the System Debug Trace Logger (Mlog) Task IDs used by XRAN library + * @file mlog_task_id.h + * @ingroup group_lte_source_common + * @author Intel Corporation + **/ + +#ifndef _XRAN_TASK_ID_H_ +#define _XRAN_TASK_ID_H_ + +#define RESOURCE_CORE_0 0 +#define RESOURCE_CORE_1 1 +#define RESOURCE_CORE_2 2 +#define RESOURCE_CORE_3 3 +#define RESOURCE_CORE_4 4 +#define RESOURCE_CORE_5 5 +#define RESOURCE_CORE_6 6 +#define RESOURCE_CORE_7 7 +#define RESOURCE_CORE_8 8 +#define RESOURCE_CORE_9 9 +#define RESOURCE_CORE_10 10 +#define RESOURCE_CORE_11 11 +#define RESOURCE_CORE_12 12 +#define RESOURCE_CORE_13 13 +#define RESOURCE_CORE_14 14 +#define RESOURCE_CORE_15 15 +#define RESOURCE_CORE_16 16 + +#define RESOURCE_IA_CORE 100 + +//-------------------------------------------------------------------- +// XRAN +//-------------------------------------------------------------------- +#define PID_TTI_TIMER 2100 +#define PID_TTI_CB 2101 + +#define PID_SYM_TIMER 2102 +#define PID_GNB_PROC_TIMING_TIMEOUT 2103 + +#define PID_TIME_SYSTIME_POLL 2104 +#define PID_TIME_SYSTIME_STOP 2105 +#define PID_TIME_ARM_TIMER 2106 + + +#define PID_RADIO_FREQ_RX_PKT 2400 +#define PID_RADIO_RX_STOP 2401 +#define PID_RADIO_RX_UL_IQ 2402 +#define PID_RADIO_PRACH_PKT 2403 +#define PID_RADIO_FE_COMPRESS 2404 +#define PID_RADIO_FE_DECOMPRESS 2405 +#define PID_RADIO_TX_BYPASS_PROC 2406 +#define PID_RADIO_ETH_TX_BURST 2407 +#define PID_RADIO_TX_DL_IQ 2408 +#define PID_RADIO_RX_VALIDATE 2409 + +#define PID_RADIO_RX_IRQ_ON 2410 +#define PID_RADIO_RX_IRQ_OFF 2411 +#define PID_RADIO_RX_EPOLL_WAIT 2412 + +#define PID_RADIO_TX_LTEMODE_PROC 2413 +#define PID_RADIO_RX_LTEMODE_PROC 2414 + +#define PID_RADIO_TX_PLAY_BACK_IQ 2415 + +#define PID_PROCESS_TX_SYM 2416 + +#define PID_CP_DL_CB 2500 +#define PID_CP_UL_CB 2501 +#define PID_UP_DL_CB 2502 +#define PID_SYM_OTA_CB 2503 +#define PID_TTI_CB_TO_PHY 2504 +#define PID_HALF_SLOT_CB_TO_PHY 2505 +#define PID_FULL_SLOT_CB_TO_PHY 2506 +#define PID_UP_UL_HALF_DEAD_LINE_CB 2507 +#define PID_UP_UL_FULL_DEAD_LINE_CB 2508 + +#define PID_PROCESS_UP_PKT 2600 +#define PID_PROCESS_CP_PKT 2700 + + + +#endif /* _XRAN_TASK_ID_H_ */ + diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c new file mode 100644 index 0000000..94751f6 --- /dev/null +++ b/fhi_lib/lib/src/xran_main.c @@ -0,0 +1,1445 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief XRAN main functionality module + * @file xran_main.c + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "xran_fh_lls_cu.h" + +#include "ethdi.h" +#include "xran_pkt.h" +#include "xran_up_api.h" +#include "xran_cp_api.h" +#include "xran_sync_api.h" +#include "xran_lib_mlog_tasks_id.h" +#include "xran_timer.h" +#include "xran_common.h" +#include "xran_printf.h" + +#ifndef MLOG_ENABLED +#include "mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif + +#define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) ) + +#define XranOffsetSym(offSym, otaSym, numSymTotal) (((int32_t)offSym > (int32_t)otaSym) ? \ + ((int32_t)otaSym + ((int32_t)numSymTotal) - (uint32_t)offSym) : \ + (((int32_t)otaSym - (int32_t)offSym) >= numSymTotal) ? \ + (((int32_t)otaSym - (int32_t)offSym) - numSymTotal) : \ + ((int32_t)otaSym - (int32_t)offSym)) + +#define MAX_NUM_OF_XRAN_CTX (2) +#define XranIncrementCtx(ctx) ((ctx >= (MAX_NUM_OF_XRAN_CTX-1)) ? 0 : (ctx+1)) +#define XranDecrementCtx(ctx) ((ctx == 0) ? (MAX_NUM_OF_XRAN_CTX-1) : (ctx-1)) + +struct xran_timer_ctx { + uint32_t tti_to_process; +}; + +static XranLibHandleInfoStruct DevHandle; +static struct xran_lib_ctx g_xran_lib_ctx = { 0 }; + +struct xran_timer_ctx timer_ctx[MAX_NUM_OF_XRAN_CTX]; + +static struct rte_timer tti_to_phy_timer[10]; +static struct rte_timer tti_timer; +static struct rte_timer sym_timer; +static struct rte_timer tx_cp_dl_timer; +static struct rte_timer tx_cp_ul_timer; +static struct rte_timer tx_up_timer; + +static long interval_us = 125; + +uint32_t xran_lib_ota_tti = 0; /* [0:7999] */ +uint32_t xran_lib_ota_sym = 0; /* [0:7] */ +uint32_t xran_lib_ota_sym_idx = 0; /* [0 : 14*8*1000-1] */ + +uint64_t xran_lib_gps_second = 0; + +static uint8_t xran_cp_seq_id_num[XRAN_MAX_CELLS_PER_PORT][XRAN_DIR_MAX][XRAN_MAX_ANTENNA_NR]; +static uint8_t xran_section_id_curslot[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR]; +static uint16_t xran_section_id[XRAN_MAX_CELLS_PER_PORT][XRAN_MAX_ANTENNA_NR]; + +void xran_timer_arm(struct rte_timer *tim, void* arg); +int xran_process_tx_sym(void *arg); + +int xran_process_rx_sym(void *arg, + void *iq_data_start, + uint16_t size, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t frame_id, + uint8_t subframe_id, + uint8_t slot_id, + uint8_t symb_id); + +void tti_ota_cb(struct rte_timer *tim, void *arg); +void tti_to_phy_cb(struct rte_timer *tim, void *arg); +void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore); + +struct xran_lib_ctx *xran_lib_get_ctx(void) +{ + return &g_xran_lib_ctx; +} + +static inline XRANFHCONFIG *xran_lib_get_ctx_fhcfg(void) +{ + return (&(xran_lib_get_ctx()->xran_fh_cfg)); +} + +inline uint16_t xran_get_beamid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id) +{ + return (0); // NO BEAMFORMING +} + +int xran_init_sectionid(void *pHandle) +{ + int cell, dir, ant; + + for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) { + for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) { + xran_section_id[cell][ant] = 0; + xran_section_id_curslot[cell][ant] = 255; + } + } + + return (0); +} + +int xran_init_seqid(void *pHandle) +{ + int cell, dir, ant; + + for(cell=0; cell < XRAN_MAX_CELLS_PER_PORT; cell++) { + for(dir=0; dir < XRAN_DIR_MAX; dir++) { + for(ant=0; ant < XRAN_MAX_ANTENNA_NR; ant++) { + xran_cp_seq_id_num[cell][dir][ant] = 0; + } + } + } + + return (0); +} + +inline uint16_t xran_alloc_sectionid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id) +{ + if(cc_id >= XRAN_MAX_CELLS_PER_PORT) { + print_err("Invalid CC ID - %d", cc_id); + return (0); + } + if(ant_id >= XRAN_MAX_ANTENNA_NR) { + print_err("Invalid antenna ID - %d", ant_id); + return (0); + } + + /* if new slot has been started, + * then initializes section id again for new start */ + if(xran_section_id_curslot[cc_id][ant_id] != slot_id) { + xran_section_id[cc_id][ant_id] = 0; + xran_section_id_curslot[cc_id][ant_id] = slot_id; + } + + return(xran_section_id[cc_id][ant_id]++); +} + +inline uint8_t xran_get_seqid(void *pHandle, uint8_t dir, uint8_t cc_id, uint8_t ant_id, uint8_t slot_id) +{ + if(dir >= XRAN_DIR_MAX) { + print_err("Invalid direction - %d", dir); + return (0); + } + if(cc_id >= XRAN_MAX_CELLS_PER_PORT) { + print_err("Invalid CC ID - %d", cc_id); + return (0); + } + if(ant_id >= XRAN_MAX_ANTENNA_NR) { + print_err("Invalid antenna ID - %d", ant_id); + return (0); + } + + return(xran_cp_seq_id_num[cc_id][dir][ant_id]++); +} + +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) +{ + return (0); +} + +////////////////////////////////////////// +// For RU emulation +static struct xran_section_gen_info cpSections[255]; +static struct xran_cp_gen_params cpInfo; +int process_cplane(struct rte_mbuf *pkt) +{ + int xran_parse_cp_pkt(struct rte_mbuf *mbuf, struct xran_cp_gen_params *result); + + cpInfo.sections = cpSections; + xran_parse_cp_pkt(pkt, &cpInfo); + + return (0); +} +////////////////////////////////////////// + +void sym_ota_cb(struct rte_timer *tim, void *arg) +{ + uint8_t offset = 0; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg; + long t1 = MLogTick(); + + if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 0){ + tti_ota_cb(NULL, arg); + } + + if(XranGetSymNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT) == 1){ + if(p_xran_lib_ctx->phy_tti_cb_done == 0){ + uint64_t t3 = MLogTick(); + /* rearm timer to deliver TTI event to PHY */ + p_xran_lib_ctx->phy_tti_cb_done = 0; + 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); + MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick()); + } + } + + xran_process_tx_sym(timer_ctx); + /* check if there is call back to do something else on this symbol */ + if(p_xran_lib_ctx->pSymCallback[0][xran_lib_ota_sym]) + p_xran_lib_ctx->pSymCallback[0][xran_lib_ota_sym](&tx_cp_dl_timer, p_xran_lib_ctx->pSymCallbackTag[0][xran_lib_ota_sym]); + + xran_lib_ota_sym++; + if(xran_lib_ota_sym >= N_SYM_PER_SLOT){ + xran_lib_ota_sym=0; + } + MLogTask(PID_SYM_OTA_CB, t1, MLogTick()); +} + +void tti_ota_cb(struct rte_timer *tim, void *arg) +{ + uint32_t frame_id = 0; + uint32_t subframe_id = 0; + uint32_t slot_id = 0; + uint32_t next_tti = 0; + + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + uint64_t t1 = MLogTick(); + uint64_t t3 = 0; + uint32_t reg_tti = 0; + struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + MLogTask(PID_TTI_TIMER, t1, MLogTick()); + + /* To match TTbox */ + if(xran_lib_ota_tti == 0) + reg_tti = 8000-1; + else + reg_tti = xran_lib_ota_tti -1; + MLogIncrementCounter(); + /* subframe and slot */ + MLogRegisterFrameSubframe(((reg_tti/SLOTNUM_PER_SUBFRAME) % SUBFRAMES_PER_SYSTEMFRAME), + reg_tti % (SLOTNUM_PER_SUBFRAME)); + MLogMark(1, t1); + + slot_id = XranGetSlotNum(xran_lib_ota_tti, SLOTNUM_PER_SUBFRAME); + subframe_id = XranGetSubFrameNum(xran_lib_ota_tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + frame_id = XranGetFrameNum(xran_lib_ota_tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + + pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process = xran_lib_ota_tti; + + mlogVar[mlogVarCnt++] = 0x11111111; + mlogVar[mlogVarCnt++] = xran_lib_ota_tti; + mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx; + mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx / 14; + mlogVar[mlogVarCnt++] = frame_id; + mlogVar[mlogVarCnt++] = subframe_id; + mlogVar[mlogVarCnt++] = slot_id; + mlogVar[mlogVarCnt++] = 0; + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + + if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == ID_LLS_CU) + next_tti = xran_lib_ota_tti + 1; + else + next_tti = xran_lib_ota_tti; + + if(next_tti>= SLOTNUM_PER_SUBFRAME*1000){ + print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id); + next_tti=0; + } + /* [0 - 7] */ + slot_id = XranGetSlotNum(next_tti, SLOTNUM_PER_SUBFRAME); + /* sf [0 - 9] */ + subframe_id = XranGetSubFrameNum(next_tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + /* frame [0 - 99] for now */ + frame_id = XranGetFrameNum(next_tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + + print_dbg("[%d]SFN %d sf %d slot %d\n",next_tti, frame_id, subframe_id, slot_id); + + if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == ID_LLS_CU){ + pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = next_tti; + } else { + pTCtx[(xran_lib_ota_tti & 1)].tti_to_process = pTCtx[(xran_lib_ota_tti & 1)^1].tti_to_process; + } + + t3 = MLogTick(); + p_xran_lib_ctx->phy_tti_cb_done = 0; + 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); + MLogTask(PID_TIME_ARM_TIMER, t3, MLogTick()); + + xran_lib_ota_tti++; + /* within 1 sec we have 8000 TTIs as 1000ms/0.125ms where TTI is 125us*/ + if(xran_lib_ota_tti >= SLOTNUM_PER_SUBFRAME*1000){ + print_dbg("[%d]SFN %d sf %d slot %d\n",xran_lib_ota_tti, frame_id, subframe_id, slot_id); + xran_lib_ota_tti=0; + } + MLogTask(PID_TTI_CB, t1, MLogTick()); +} + +void xran_timer_arm(struct rte_timer *tim, void* arg) +{ + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + if (xran_if_current_state == XRAN_RUNNING){ + rte_timer_cb_t fct = (rte_timer_cb_t)arg; + rte_timer_reset_sync(tim, 0, SINGLE, p_xran_lib_ctx->xran_init_cfg.io_cfg.pkt_proc_core, fct, timer_ctx); + } +} + +void xran_timer_arm_ex(struct rte_timer *tim, void* CbFct, void *CbArg, unsigned tim_lcore) +{ + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + if (xran_if_current_state == XRAN_RUNNING){ + rte_timer_cb_t fct = (rte_timer_cb_t)CbFct; + rte_timer_init(tim); + rte_timer_reset_sync(tim, 0, SINGLE, tim_lcore, fct, CbArg); + } +} + +void tx_cp_dl_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + int tti, sym; + uint32_t slot_id, subframe_id, frame_id; + int ant_id; + int32_t cc_id = 0; + uint16_t beam_id; + uint8_t num_eAxc, num_CCPorts; + void *pHandle; + + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg; + + + pHandle = NULL; // TODO: temp implemantation + num_eAxc = xran_get_num_eAxc(pHandle); + num_CCPorts = xran_get_num_cc(pHandle); + + if(p_xran_lib_ctx->enableCP) { + + tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process; + + slot_id = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME); + subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + frame_id = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + + print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id); + + for(ant_id = 0; ant_id < num_eAxc; ++ant_id) { + for(cc_id = 0; cc_id < num_CCPorts; cc_id++ ) { + // start new section information list + xran_cp_reset_section_info(pHandle, XRAN_DIR_DL, cc_id, ant_id); + + beam_id = xran_get_beamid(pHandle, XRAN_DIR_DL, cc_id, ant_id, slot_id); + + send_cpmsg_dlul(pHandle, XRAN_DIR_DL, + frame_id, subframe_id, slot_id, + 0, N_SYM_PER_SLOT, NUM_OF_PRB_IN_FULL_BAND, + beam_id, cc_id, ant_id, + xran_get_seqid(pHandle, XRAN_DIR_DL, cc_id, ant_id, slot_id)); + } + } + } + MLogTask(PID_CP_DL_CB, t1, MLogTick()); +} + +void rx_ul_deadline_half_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + XranStatusInt32 status; + /* half of RX for current TTI as measured against current OTA time */ + int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + + if(p_xran_lib_ctx->xran2phy_mem_ready == 0) + return; + + if(p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] == 0){ + status = (rx_tti << 16) | 0; /* base on PHY side implementation first 7 sym of slot */ + if(p_xran_lib_ctx->pCallback[0]) + p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status); + } else { + p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] = 0; + } + MLogTask(PID_UP_UL_HALF_DEAD_LINE_CB, t1, MLogTick()); +} + +void rx_ul_deadline_full_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + XranStatusInt32 status; + int32_t rx_tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + + if(rx_tti >= 8000-1) + rx_tti = 0; + else + rx_tti -= 1; /* end of RX for prev TTI as measured against current OTA time */ + + if(p_xran_lib_ctx->xran2phy_mem_ready == 0) + return; + + if(p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] == 0){ + status = (rx_tti << 16) | 7; /* last 7 sym means full slot of Symb */ + if(p_xran_lib_ctx->pCallback[0]) + p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status); + } else { + p_xran_lib_ctx->rx_packet_callback_tracker[rx_tti % XRAN_N_FE_BUF_LEN][0] = 0; + } + + MLogTask(PID_UP_UL_FULL_DEAD_LINE_CB, t1, MLogTick()); +} + + +void tx_cp_ul_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + int sym, tti; + uint32_t frame_id = 0; + uint32_t subframe_id = 0; + uint32_t slot_id = 0; + + int32_t cc_id; + int ant_id, prach_port_id; + uint16_t beam_id; + uint8_t num_eAxc, num_CCPorts; + + void *pHandle; + + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + xRANPrachCPConfigStruct *pPrachCPConfig = &(p_xran_lib_ctx->PrachCPConfig); + struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg; + + pHandle = NULL; // TODO: temp implemantation + num_eAxc = xran_get_num_eAxc(pHandle); + num_CCPorts = xran_get_num_cc(pHandle); + + if (p_xran_lib_ctx->enableCP){ + tti = pTCtx[(xran_lib_ota_tti & 1) ^ 1].tti_to_process; + slot_id = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME); + subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + frame_id = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id); + + + for(ant_id = 0; ant_id < num_eAxc; ++ant_id) { + for(cc_id = 0; cc_id < num_CCPorts; cc_id++ ) { + // start new section information list + xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, ant_id); + + beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, ant_id, slot_id); + send_cpmsg_dlul(pHandle, XRAN_DIR_UL, + frame_id, subframe_id, slot_id, + 0, N_SYM_PER_SLOT, NUM_OF_PRB_IN_FULL_BAND, + beam_id, cc_id, ant_id, + xran_get_seqid(pHandle, XRAN_DIR_UL, cc_id, ant_id, slot_id)); + } + } + + if ((frame_id % pPrachCPConfig->x == pPrachCPConfig->y[0]) && (pPrachCPConfig->isPRACHslot[slot_id]==1)) //is prach slot + { + for(ant_id = 0; ant_id < num_eAxc; ant_id++) { + for(cc_id = 0; cc_id < num_CCPorts; cc_id++) { +#if !defined(PRACH_USES_SHARED_PORT) + prach_port_id = ant_id + num_eAxc; + // start new section information list + xran_cp_reset_section_info(pHandle, XRAN_DIR_UL, cc_id, prach_port_id); +#else + prach_port_id = ant_id; +#endif + beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id); + send_cpmsg_prach(pHandle, + frame_id, subframe_id, slot_id, + beam_id, cc_id, prach_port_id, + xran_get_seqid(pHandle, XRAN_DIR_UL, cc_id, prach_port_id, slot_id)); + } + } + } + + } + MLogTask(PID_CP_UL_CB, t1, MLogTick()); +} + +void ul_up_full_slot_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + rte_pause(); + MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick()); +} + +void tti_to_phy_cb(struct rte_timer *tim, void *arg) +{ + long t1 = MLogTick(); + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + static int first_call = 0; + p_xran_lib_ctx->phy_tti_cb_done = 1; /* DPDK called CB */ + if (first_call){ + if(p_xran_lib_ctx->ttiCb[XRAN_CB_TTI]){ + if(p_xran_lib_ctx->SkipTti[XRAN_CB_TTI] <= 0){ + p_xran_lib_ctx->ttiCb[XRAN_CB_TTI](p_xran_lib_ctx->TtiCbParam[XRAN_CB_TTI]); + }else{ + p_xran_lib_ctx->SkipTti[XRAN_CB_TTI]--; + } + } + } else { + if(p_xran_lib_ctx->ttiCb[XRAN_CB_TTI]){ + int32_t tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + if(tti == 8000-1) + first_call = 1; + } + } + + + MLogTask(PID_TTI_CB_TO_PHY, t1, MLogTick()); +} + +int xran_timing_source_thread(void *args) +{ + cpu_set_t cpuset; + int32_t do_reset = 0; + uint64_t t1 = 0; + uint64_t delta; + int32_t result1; + uint32_t delay_cp_dl; + uint32_t delay_cp_ul; + uint32_t delay_up; + uint32_t delay_up_ul; + uint32_t delay_cp2up; + uint32_t sym_cp_dl; + uint32_t sym_cp_ul; + uint32_t sym_up_ul; + int32_t sym_up; + struct sched_param sched_param; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + /* ToS = Top of Second start +- 1.5us */ + struct timespec ts; + + char buff[100]; + + printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid()); + + /* set main thread affinity mask to CPU2 */ + sched_param.sched_priority = 98; + + CPU_ZERO(&cpuset); + CPU_SET(p_xran_lib_ctx->xran_init_cfg.io_cfg.timing_core, &cpuset); + if (result1 = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) + { + printf("pthread_setaffinity_np failed: coreId = 2, result1 = %d\n",result1); + } + if ((result1 = pthread_setschedparam(pthread_self(), 1, &sched_param))) + { + printf("priority is not changed: coreId = 2, result1 = %d\n",result1); + } + + if (p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU) { + do { + timespec_get(&ts, TIME_UTC); + }while (ts.tv_nsec >1500); + struct tm * ptm = gmtime(&ts.tv_sec); + if(ptm){ + strftime(buff, sizeof buff, "%D %T", ptm); + printf("lls-CU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us); + } + + delay_cp_dl = p_xran_lib_ctx->xran_init_cfg.ttiPeriod - p_xran_lib_ctx->xran_init_cfg.T1a_max_cp_dl; + delay_cp_ul = p_xran_lib_ctx->xran_init_cfg.ttiPeriod - p_xran_lib_ctx->xran_init_cfg.T1a_max_cp_ul; + delay_up = p_xran_lib_ctx->xran_init_cfg.T1a_max_up; + delay_up_ul = p_xran_lib_ctx->xran_init_cfg.Ta4_max; + + delay_cp2up = delay_up-delay_cp_dl; + + sym_cp_dl = delay_cp_dl*1000/(interval_us*1000/N_SYM_PER_SLOT)+1; + sym_cp_ul = delay_cp_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1; + sym_up_ul = delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT); + p_xran_lib_ctx->sym_up = sym_up = -(delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT)+1); + p_xran_lib_ctx->sym_up_ul = sym_up_ul = (delay_up_ul*1000/(interval_us*1000/N_SYM_PER_SLOT)+1); + + printf("Start C-plane DL %d us after TTI [trigger on sym %d]\n", delay_cp_dl, sym_cp_dl); + printf("Start C-plane UL %d us after TTI [trigger on sym %d]\n", delay_cp_ul, sym_cp_ul); + printf("Start U-plane DL %d us before OTA [offset in sym %d]\n", delay_up, sym_up); + printf("Start U-plane UL %d us OTA [offset in sym %d]\n", delay_up_ul, sym_up_ul); + + printf("C-plane to U-plane delay %d us after TTI\n", delay_cp2up); + printf("Start Sym timer %ld ns\n", TX_TIMER_INTERVAL/N_SYM_PER_SLOT); + + p_xran_lib_ctx->pSymCallback[0][sym_cp_dl] = xran_timer_arm; + p_xran_lib_ctx->pSymCallbackTag[0][sym_cp_dl] = tx_cp_dl_cb; + + p_xran_lib_ctx->pSymCallback[0][sym_cp_ul] = xran_timer_arm; + p_xran_lib_ctx->pSymCallbackTag[0][sym_cp_ul] = tx_cp_ul_cb; + + /* Full slot UL OTA + delay_up_ul */ + p_xran_lib_ctx->pSymCallback[0][sym_up_ul] = xran_timer_arm; + p_xran_lib_ctx->pSymCallbackTag[0][sym_up_ul] = rx_ul_deadline_full_cb; + + /* Half slot UL OTA + delay_up_ul*/ + p_xran_lib_ctx->pSymCallback[0][sym_up_ul + N_SYM_PER_SLOT/2] = xran_timer_arm; + p_xran_lib_ctx->pSymCallbackTag[0][sym_up_ul + N_SYM_PER_SLOT/2] = rx_ul_deadline_half_cb; + + } else { // APP_RU + /* calcualte when to send UL U-plane */ + delay_up = p_xran_lib_ctx->xran_init_cfg.Ta3_min; + p_xran_lib_ctx->sym_up = sym_up = delay_up*1000/(interval_us*1000/N_SYM_PER_SLOT)+1; + printf("Start UL U-plane %d us after OTA [offset in sym %d]\n", delay_up, sym_up); + do { + timespec_get(&ts, TIME_UTC); + }while (ts.tv_nsec >1500); + struct tm * ptm = gmtime(&ts.tv_sec); + if(ptm){ + strftime(buff, sizeof buff, "%D %T", ptm); + printf("RU: thread_run start time: %s.%09ld UTC [%ld]\n", buff, ts.tv_nsec, interval_us); + } + } + + do { + timespec_get(&ts, TIME_UTC); + }while (ts.tv_nsec == 0); + + while(1) { + delta = poll_next_tick(interval_us*1000L/N_SYM_PER_SLOT); + if (XRAN_STOPPED == xran_if_current_state) + break; + sym_ota_cb(&sym_timer, timer_ctx); + } + printf("Closing timing source thread...\n"); + + return 0; +} + +/* Handle ecpri format. */ +int handle_ecpri_ethertype(struct rte_mbuf *pkt, uint64_t rx_time) +{ + const struct xran_ecpri_hdr *ecpri_hdr; + unsigned long t1; + + if (rte_pktmbuf_data_len(pkt) < sizeof(struct xran_ecpri_hdr)) { + wlog("Packet too short - %d bytes", rte_pktmbuf_data_len(pkt)); + return 0; + } + + /* check eCPRI header. */ + ecpri_hdr = rte_pktmbuf_mtod(pkt, struct xran_ecpri_hdr *); + if(ecpri_hdr == NULL) + return MBUF_FREE; + + switch(ecpri_hdr->ecpri_mesg_type) { + case ECPRI_IQ_DATA: + t1 = MLogTick(); + process_mbuf(pkt); + MLogTask(PID_PROCESS_UP_PKT, t1, MLogTick()); + break; + // For RU emulation + case ECPRI_RT_CONTROL_DATA: + t1 = MLogTick(); + if(xran_lib_get_ctx()->xran_init_cfg.io_cfg.id == APP_RU) { + process_cplane(pkt); + } else { + print_err("LLS-CU recevied CP message!"); + } + MLogTask(PID_PROCESS_CP_PKT, t1, MLogTick()); + break; + default: + wlog("Invalid eCPRI message type - %d", ecpri_hdr->ecpri_mesg_type); + } +#if 0 +//def DEBUG + return MBUF_KEEP; +#else + return MBUF_FREE; +#endif +} + +int xran_process_rx_sym(void *arg, + void *iq_data_start, + uint16_t size, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t frame_id, + uint8_t subframe_id, + uint8_t slot_id, + uint8_t symb_id) +{ + char *pos = NULL; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + uint32_t tti=0; + XranStatusInt32 status; + void *pHandle = NULL; + + if(p_xran_lib_ctx->xran2phy_mem_ready == 0) + return 0; + + tti = frame_id * SLOTS_PER_SYSTEMFRAME + subframe_id * SLOTNUM_PER_SUBFRAME + slot_id; + + status = tti << 16 | symb_id; + + 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){ + pos = (char*) p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData; + if(pos && iq_data_start && size){ +#ifdef XRAN_BYTE_ORDER_SWAP + int idx = 0; + uint16_t *restrict psrc = (uint16_t *)iq_data_start; + uint16_t *restrict pdst = (uint16_t *)pos; + /* network byte (be) order of IQ to CPU byte order (le) */ + for (idx = 0; idx < size/sizeof(int16_t); idx++){ + pdst[idx] = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_be_to_cpu_16(psrc[idx]); + } +#else +#error xran spec is network byte order + /* for debug */ + rte_memcpy(pdst, psrc, size); +#endif +#ifdef DEBUG_XRAN_BUFFERS + if (pos[0] != tti % XRAN_N_FE_BUF_LEN || + pos[1] != CC_ID || + pos[2] != Ant_ID || + pos[3] != symb_id){ + printf("%d %d %d %d\n", pos[0], pos[1], pos[2], pos[3]); + } +#endif + } else { + print_err("pos %p iq_data_start %p size %d\n",pos, iq_data_start, size); + } + } else { + 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); + } + if (symb_id == 7 || symb_id == 13){ + p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id]++; + + if(p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] >= xran_get_num_eAxc(pHandle)){ + if(p_xran_lib_ctx->pCallback[0]) + p_xran_lib_ctx->pCallback[0](p_xran_lib_ctx->pCallbackTag[0], status); + p_xran_lib_ctx->rx_packet_callback_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID] = 1; + p_xran_lib_ctx->rx_packet_symb_tracker[tti % XRAN_N_FE_BUF_LEN][CC_ID][symb_id] = 0; + } + } + return size; +} + + +int xran_process_tx_sym(void *arg) +{ + uint32_t tti=0; + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + unsigned long t1 = MLogTick(); + + void *pHandle = NULL; + int32_t ant_id; + int32_t cc_id = 0; + uint8_t num_eAxc = 0; + uint8_t num_CCPorts = 0; + + uint32_t frame_id = 0; + uint32_t subframe_id = 0; + uint32_t slot_id = 0; + uint32_t sym_id = 0; + uint32_t sym_idx = 0; + + char *pos = NULL; + int prb_num = 0; + + struct xran_section_info *sectinfo; + uint32_t next; + + enum xran_pkt_dir direction; + + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + struct xran_timer_ctx *pTCtx = (struct xran_timer_ctx *)arg; + + + if(p_xran_lib_ctx->xran2phy_mem_ready == 0) + return 0; + + if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU) { + direction = XRAN_DIR_DL; /* lls-CU */ + prb_num = NUM_OF_PRB_IN_FULL_BAND; + } + else { + direction = XRAN_DIR_UL; /* RU */ + prb_num = NUM_OF_PRB_IN_FULL_BAND; /*TODO: simulation on D-1541 @ 2.10GHz has issue with performace. reduce copy size */ + } + + /* RU: send symb after OTA time with delay (UL) */ + /* lls-CU:send symb in advance of OTA time (DL) */ + sym_idx = XranOffsetSym(p_xran_lib_ctx->sym_up, xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT*SLOTNUM_PER_SUBFRAME*1000); + + tti = XranGetTtiNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + slot_id = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME); + subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + frame_id = XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + sym_id = XranGetSymNum(sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + + print_dbg("[%d]SFN %d sf %d slot %d\n", tti, frame_id, subframe_id, slot_id); + + mlogVar[mlogVarCnt++] = 0xAAAAAAAA; + mlogVar[mlogVarCnt++] = xran_lib_ota_sym_idx; + mlogVar[mlogVarCnt++] = sym_idx; + mlogVar[mlogVarCnt++] = abs(p_xran_lib_ctx->sym_up); + mlogVar[mlogVarCnt++] = tti; + mlogVar[mlogVarCnt++] = frame_id; + mlogVar[mlogVarCnt++] = subframe_id; + mlogVar[mlogVarCnt++] = slot_id; + mlogVar[mlogVarCnt++] = sym_id; + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + + if(frame_id > 99) { + 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); + xran_if_current_state =XRAN_STOPPED; + } + + num_eAxc = xran_get_num_eAxc(pHandle); + num_CCPorts = xran_get_num_cc(pHandle); + + /* U-Plane */ + for(ant_id = 0; ant_id < num_eAxc; ant_id++) { + for(cc_id = 0; cc_id < num_CCPorts; cc_id++) { + if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU && p_xran_lib_ctx->enableCP) { + next = 0; + while(next < xran_cp_getsize_section_info(pHandle, direction, cc_id, ant_id)) { + sectinfo = xran_cp_iterate_section_info(pHandle, direction, + cc_id, ant_id, subframe_id, slot_id, &next); + if(sectinfo == NULL) + break; + + /* pointer to IQs input */ + /* TODO: need to implement the case of partial RB assignment */ + pos = (char*) p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData; + print_dbg(">>> [%d] type%d, id %d, startPrbc=%d, numPrbc=%d, numSymbol=%d\n", next, + sectinfo->type, sectinfo->id, sectinfo->startPrbc, + sectinfo->numPrbc, sectinfo->numSymbol); + + if(sectinfo->type != XRAN_CP_SECTIONTYPE_1) { + print_err("Invalid section type in section DB - %d", sectinfo->type); + continue; + } + + send_symbol_ex(direction, sectinfo->id, + (struct rb_map *)pos, + frame_id, subframe_id, slot_id, sym_id, + sectinfo->startPrbc, sectinfo->numPrbc, + cc_id, ant_id, + xran_get_seqid(pHandle, direction, cc_id, ant_id, slot_id)); + } + } + + else { /* if(p_xran_lib_ctx->xran_init_cfg.io_cfg.id == APP_LLS_CU && p_xran_lib_ctx->enableCP) */ + /* pointer to IQs input */ + pos = (char*) p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData; +#ifdef DEBUG_XRAN_BUFFERS + if (pos[0] != tti % XRAN_N_FE_BUF_LEN || + pos[1] != cc_id || + pos[2] != ant_id || + pos[3] != sym_id) + printf("%d %d %d %d\n", pos[0], pos[1], pos[2], pos[3]); +#endif + send_symbol_ex(direction, + xran_alloc_sectionid(pHandle, direction, cc_id, ant_id, slot_id), + (struct rb_map *)pos, + frame_id, subframe_id, slot_id, sym_id, + 0, prb_num, + cc_id, ant_id, + xran_get_seqid(pHandle, direction, cc_id, ant_id, slot_id)); + } + } + } + + MLogTask(PID_PROCESS_TX_SYM, t1, MLogTick()); + return 0; +} + +int xran_packet_and_dpdk_timer_thread(void *args) +{ + struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx(); + + uint64_t prev_tsc = 0; + uint64_t cur_tsc = rte_rdtsc(); + uint64_t diff_tsc = cur_tsc - prev_tsc; + cpu_set_t cpuset; + struct sched_param sched_param; + int res = 0; + printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, rte_lcore_id(), getpid()); + + sched_param.sched_priority = XRAN_THREAD_DEFAULT_PRIO; + + if ((res = pthread_setschedparam(pthread_self(), 1, &sched_param))) + { + printf("priority is not changed: coreId = %d, result1 = %d\n",rte_lcore_id(), res); + } + + while(1){ + + cur_tsc = rte_rdtsc(); + diff_tsc = cur_tsc - prev_tsc; + if (diff_tsc > TIMER_RESOLUTION_CYCLES) { + rte_timer_manage(); + prev_tsc = cur_tsc; + } + + if (XRAN_STOPPED == xran_if_current_state) + break; + } + + printf("Closing pkts timer thread...\n"); + return 0; +} + + +int32_t xran_init(int argc, char *argv[], PXRANFHINIT p_xran_fh_init, char *appName, void ** pHandle) +{ + int i; + int j; + + struct xran_io_loop_cfg *p_io_cfg = (struct xran_io_loop_cfg *)&p_xran_fh_init->io_cfg; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + int lcore_id = 0; + char filename[64]; + + memset(p_xran_lib_ctx, 0, sizeof(struct xran_lib_ctx)); + /* copy init */ + p_xran_lib_ctx->xran_init_cfg = *p_xran_fh_init; + + xran_if_current_state = XRAN_RUNNING; + interval_us = p_xran_fh_init->ttiPeriod; + + p_xran_lib_ctx->llscu_id = p_xran_fh_init->llscuId; + memcpy(&(p_xran_lib_ctx->eAxc_id_cfg), &(p_xran_fh_init->eAxCId_conf), sizeof(XRANEAXCIDCONFIG)); + + p_xran_lib_ctx->enableCP = p_xran_fh_init->enableCP; + + xran_register_ethertype_handler(ETHER_TYPE_ECPRI, handle_ecpri_ethertype); + if (p_io_cfg->id == 0) + xran_ethdi_init_dpdk_io(basename(appName), + p_io_cfg, + &lcore_id, + (struct ether_addr *)p_xran_fh_init->p_lls_cu_addr, + (struct ether_addr *)p_xran_fh_init->p_ru_addr, + p_xran_fh_init->cp_vlan_tag, + p_xran_fh_init->up_vlan_tag); + else + xran_ethdi_init_dpdk_io(basename(appName), + p_io_cfg, + &lcore_id, + (struct ether_addr *)p_xran_fh_init->p_ru_addr, + (struct ether_addr *)p_xran_fh_init->p_lls_cu_addr, + p_xran_fh_init->cp_vlan_tag, + p_xran_fh_init->up_vlan_tag); + + for(i = 0; i < 10; i++ ) + rte_timer_init(&tti_to_phy_timer[i]); + + rte_timer_init(&tti_timer); + rte_timer_init(&sym_timer); + rte_timer_init(&tx_cp_dl_timer); + rte_timer_init(&tx_cp_ul_timer); + rte_timer_init(&tx_up_timer); + + for(i = 0; i < XRAN_MAX_SECTOR_NR; i++ ){ + unsigned n = snprintf(&p_xran_lib_ctx->ring_name[0][i][0], RTE_RING_NAMESIZE, "dl_sym_ring_%u", i); + p_xran_lib_ctx->dl_sym_idx_ring[i] = rte_ring_create(&p_xran_lib_ctx->ring_name[0][i][0], XRAN_RING_SIZE, + rte_lcore_to_socket_id(lcore_id), RING_F_SP_ENQ | RING_F_SC_DEQ); + } + + + lcore_id = rte_get_next_lcore(lcore_id, 0, 0); + PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()"); + + /* Start packet processing thread */ + if (rte_eal_remote_launch(ring_processing_thread, NULL, lcore_id)) + rte_panic("ring_processing_thread() failed to start\n"); + + if(p_io_cfg->pkt_aux_core > 0){ + lcore_id = rte_get_next_lcore(lcore_id, 0, 0); + PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()"); + + /* Start packet processing thread */ + if (rte_eal_remote_launch(xran_packet_and_dpdk_timer_thread, NULL, lcore_id)) + rte_panic("ring_processing_thread() failed to start\n"); + } + + lcore_id = rte_get_next_lcore(lcore_id, 0, 0); + PANIC_ON(lcore_id == RTE_MAX_LCORE, "out of lcores for io_loop()"); + + /* Start packet processing thread */ + if (rte_eal_remote_launch(xran_timing_source_thread, xran_lib_get_ctx(), lcore_id)) + rte_panic("thread_run() failed to start\n"); + + printf("Set debug stop %d\n", p_xran_fh_init->debugStop); + timing_set_debug_stop(p_xran_fh_init->debugStop); + + memset(&DevHandle, 0, sizeof(XranLibHandleInfoStruct)); + + *pHandle = &DevHandle; + + return 0; +} + +int32_t xran_sector_get_instances (void * pHandle, uint16_t nNumInstances, + XranCcInstanceHandleVoidP * pSectorInstanceHandles) +{ + int i; + + /* only one handle as only one CC is currently supported */ + for(i = 0; i < nNumInstances; i++ ) + pSectorInstanceHandles[i] = pHandle; + + return 0; +} + +int32_t xran_mm_init (void * pHandle, uint64_t nMemorySize, + uint32_t nMemorySegmentSize) +{ + /* we use mbuf from dpdk memory */ + return 0; +} + +int32_t xran_bm_init (void * pHandle, uint32_t * pPoolIndex, uint32_t nNumberOfBuffers, uint32_t nBufferSize) +{ + XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle; + + char pool_name[RTE_MEMPOOL_NAMESIZE]; + + snprintf(pool_name, RTE_MEMPOOL_NAMESIZE, "bm_mempool_%ld", pPoolIndex); + + pXran->p_bufferPool[pXran->nBufferPoolIndex] = rte_pktmbuf_pool_create(pool_name, nNumberOfBuffers, + MBUF_CACHE, 0, XRAN_MAX_MBUF_LEN, rte_socket_id()); + + pXran->bufferPoolElmSz[pXran->nBufferPoolIndex] = nBufferSize; + pXran->bufferPoolNumElm[pXran->nBufferPoolIndex] = nNumberOfBuffers; + + print_dbg("[nPoolIndex %d] mb pool %p \n", pXran->nBufferPoolIndex, pXran->p_bufferPool[pXran->nBufferPoolIndex]); + + *pPoolIndex = pXran->nBufferPoolIndex++; + + return 0; +} + +int32_t xran_bm_allocate_buffer(void * pHandle, uint32_t nPoolIndex, void **ppVirtAddr) +{ + XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle; + *ppVirtAddr = NULL; + + struct rte_mbuf * mb = rte_pktmbuf_alloc(pXran->p_bufferPool[nPoolIndex]); + + if(mb){ + *ppVirtAddr = rte_pktmbuf_append(mb, pXran->bufferPoolElmSz[nPoolIndex]); + + }else { + print_err("[nPoolIndex %d] mb alloc failed \n", nPoolIndex ); + return -1; + } + + if (*ppVirtAddr == NULL){ + print_err("[nPoolIndex %d] rte_pktmbuf_append for %d failed \n", nPoolIndex, pXran->bufferPoolElmSz[nPoolIndex]); + return -1; + } + + return 0; +} + +int32_t xran_bm_free_buffer(void * pHandle, void *pVirtAddr) +{ + XranLibHandleInfoStruct* pXran = (XranLibHandleInfoStruct*) pHandle; + rte_pktmbuf_free(pVirtAddr); + + return 0; +} + +int32_t xran_5g_fronthault_config (void * pHandle, + XRANBufferListStruct *pSrcBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XranTransportBlockCallbackFn pCallback, + void *pCallbackTag) +{ + XranLibHandleInfoStruct *pInfo = (XranLibHandleInfoStruct *) pHandle; + XranStatusInt32 nStatus = XRAN_STATUS_SUCCESS; + int j, i = 0, z, k; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + print_dbg("%s\n", __FUNCTION__); + + if(NULL == pHandle) + { + printf("Handle is NULL!\n"); + return XRAN_STATUS_FAIL; + } + if (pCallback == NULL) + { + printf ("no callback\n"); + return XRAN_STATUS_FAIL; + } + + for(j=0; jsFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0; + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT; + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFrontHaulTxBuffers[j][i][z][0]; + + p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList = *pSrcBuffer[z][j]; + + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFrontHaulRxBuffers[j][i][z][0]; + p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList = *pDstBuffer[z][j]; + } + } + +#if 0 + for(j=0; jsFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData; + 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]); + } + } + + for(j=0; jsFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData; + 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]); + } + } +#endif + + p_xran_lib_ctx->pCallback[i] = pCallback; + p_xran_lib_ctx->pCallbackTag[i] = pCallbackTag; + + p_xran_lib_ctx->xran2phy_mem_ready = 1; + + return nStatus; +} + +int32_t xran_5g_prach_req (void * pHandle, + XRANBufferListStruct *pDstBuffer[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN], + XranTransportBlockCallbackFn pCallback, + void *pCallbackTag) +{ + XranLibHandleInfoStruct *pInfo = (XranLibHandleInfoStruct *) pHandle; + XranStatusInt32 nStatus = XRAN_STATUS_SUCCESS; + int j, i = 0, z; + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + if(NULL == pHandle) + { + printf("Handle is NULL!\n"); + return XRAN_STATUS_FAIL; + } + if (pCallback == NULL) + { + printf ("no callback\n"); + return XRAN_STATUS_FAIL; + } + + for(j=0; jsFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0; + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1; + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1; + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0; + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number. + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &p_xran_lib_ctx->sFHPrachRxBuffers[j][i][z][0]; + p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList = *pDstBuffer[z][j]; + } + } + + p_xran_lib_ctx->pPrachCallback[i] = pCallback; + p_xran_lib_ctx->pPrachCallbackTag[i] = pCallbackTag; + + return 0; +} + +int32_t xran_5g_pre_compenstor_cfg(void* pHandle, + uint32_t nTxPhaseCps, + uint32_t nRxPhaseCps, + uint8_t nSectorId) +{ + /* functionality is not yet implemented */ + return 0; +} + +int32_t xran_open(void *pHandle, PXRANFHCONFIG pConf) +{ + int i; + uint8_t slotNr; + XRANFHCONFIG *pFhCfg; + xRANPrachCPConfigStruct *pPrachCPConfig = &(xran_lib_get_ctx()->PrachCPConfig); + pFhCfg = &(xran_lib_get_ctx()->xran_fh_cfg); + memcpy(pFhCfg, pConf, sizeof(XRANFHCONFIG)); + PXRANPRACHCONFIG pPRACHConfig = &pFhCfg->prach_conf; + uint8_t nPrachConfIdx = pPRACHConfig->nPrachConfIdx; + const xRANPrachConfigTableStruct *pxRANPrachConfigTable = &gxranPrachDataTable_mmw[nPrachConfIdx]; + uint8_t preambleFmrt = pxRANPrachConfigTable->preambleFmrt[0]; + const xRANPrachPreambleLRAStruct *pxranPreambleforLRA = &gxranPreambleforLRA[preambleFmrt - FORMAT_A1]; + memset(pPrachCPConfig, 0, sizeof(xRANPrachCPConfigStruct)); + + //setup PRACH configuration for C-Plane + pPrachCPConfig->filterIdx = XRAN_FILTERINDEX_PRACH_ABC; // 3, PRACH preamble format A1~3, B1~4, C0, C2 + pPrachCPConfig->startSymId = pxRANPrachConfigTable->startingSym; + pPrachCPConfig->startPrbc = pPRACHConfig->nPrachFreqStart; + pPrachCPConfig->numPrbc = (preambleFmrt >= FORMAT_A1)? 12 : 70; + pPrachCPConfig->numSymbol = pxRANPrachConfigTable->duration; + pPrachCPConfig->timeOffset = pxranPreambleforLRA->nRaCp; + pPrachCPConfig->freqOffset = xran_get_freqoffset(pPRACHConfig->nPrachFreqOffset, pPRACHConfig->nPrachSubcSpacing); + pPrachCPConfig->occassionsInPrachSlot = pxRANPrachConfigTable->occassionsInPrachSlot; + pPrachCPConfig->x = pxRANPrachConfigTable->x; + pPrachCPConfig->y[0] = pxRANPrachConfigTable->y[0]; + pPrachCPConfig->y[1] = pxRANPrachConfigTable->y[1]; + + pPrachCPConfig->isPRACHslot[pxRANPrachConfigTable->slotNr[0]] = 1; + for (i=1; i < XRAN_PRACH_CANDIDATE_SLOT; i++) + { + slotNr = pxRANPrachConfigTable->slotNr[i]; + if (slotNr > 0) + pPrachCPConfig->isPRACHslot[slotNr] = 1; + } + + xran_cp_init_sectiondb(pHandle); + xran_init_sectionid(pHandle); + xran_init_seqid(pHandle); + + return 0; +} + +int32_t xran_start(void *pHandle) +{ + xran_if_current_state = XRAN_RUNNING; + return 0; +} + +int32_t xran_stop(void *pHandle) +{ + xran_if_current_state = XRAN_STOPPED; + return 0; +} + +int32_t xran_close(void *pHandle) +{ + xran_if_current_state = XRAN_STOPPED; + xran_cp_free_sectiondb(pHandle); + rte_eal_mp_wait_lcore(); + return 0; +} + +int32_t xran_mm_destroy (void * pHandle) +{ + /* functionality is not yet implemented */ + return -1; +} + +int32_t xran_reg_sym_cb(void *pHandle, XRANFHSYMPROCCB symCb, void * symCbParam, uint8_t symb, uint8_t ant) +{ + /* functionality is not yet implemented */ + return -1; +} + +int32_t xran_reg_physide_cb(void *pHandle, XRANFHTTIPROCCB Cb, void *cbParam, int skipTtiNum, enum callback_to_phy_id id) +{ + struct xran_lib_ctx * p_xran_lib_ctx = xran_lib_get_ctx(); + + p_xran_lib_ctx->ttiCb[id] = Cb; + p_xran_lib_ctx->TtiCbParam[id] = cbParam; + p_xran_lib_ctx->SkipTti[id] = skipTtiNum; + + return 0; +} + +int32_t xran_get_slot_idx (uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond) +{ + int32_t tti = 0; + + tti = (int32_t)XranGetTtiNum(xran_lib_ota_sym_idx, XRAN_NUM_OF_SYMBOL_PER_SLOT); + *nSlotIdx = (uint32_t)XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME); + *nSubframeIdx = (uint32_t)XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME, SUBFRAMES_PER_SYSTEMFRAME); + *nFrameIdx = (uint32_t)XranGetFrameNum(tti,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME); + *nSecond = timing_get_current_second(); + + return tti; +} + +/** + * @brief Get supported maximum number of sections + * + * @return maximum number of sections + */ +inline uint8_t xran_get_max_sections(void *pHandle) +{ + return (XRAN_MAX_NUM_SECTIONS); +} + +/** + * @brief Get the configuration of eAxC ID + * + * @return the pointer of configuration + */ +inline XRANEAXCIDCONFIG *xran_get_conf_eAxC(void *pHandle) +{ + return (&(xran_lib_get_ctx()->eAxc_id_cfg)); +} + +/** + * @brief Get the configuration of subcarrier spacing for PRACH + * + * @return subcarrier spacing value for PRACH + */ +inline uint8_t xran_get_conf_prach_scs(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->prach_conf.nPrachSubcSpacing); +} + +/** + * @brief Get the configuration of FFT size for RU + * + * @return FFT size value for RU + */ +inline uint8_t xran_get_conf_fftsize(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->ru_conf.fftSize); +} + +/** + * @brief Get the configuration of nummerology + * + * @return subcarrier spacing value for PRACH + */ +inline uint8_t xran_get_conf_numerology(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->frame_conf.nNumerology); +} + +/** + * @brief Get the configuration of IQ bit width for RU + * + * @return IQ bit width for RU + */ +inline uint8_t xran_get_conf_iqwidth(void *pHandle) +{ + XRANFHCONFIG *pFhCfg; + + pFhCfg = xran_lib_get_ctx_fhcfg(); + return ((pFhCfg->ru_conf.iqWidth==16)?0:pFhCfg->ru_conf.iqWidth); +} + +/** + * @brief Get the configuration of compression method for RU + * + * @return Compression method for RU + */ +inline uint8_t xran_get_conf_compmethod(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->ru_conf.compMeth); +} + +/** + * @brief Get the configuration of lls-cu ID + * + * @return Configured lls-cu ID + */ +inline uint8_t xran_get_llscuid(void *pHandle) +{ + return (xran_lib_get_ctx()->llscu_id); +} + +/** + * @brief Get the configuration of lls-cu ID + * + * @return Configured lls-cu ID + */ +inline uint8_t xran_get_sectorid(void *pHandle) +{ + return (xran_lib_get_ctx()->sector_id); +} + +/** + * @brief Get the configuration of the number of component carriers + * + * @return Configured the number of componen carriers + */ +inline uint8_t xran_get_num_cc(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->nCC); +} + +/** + * @brief Get the configuration of the number of antenna + * + * @return Configured the number of antenna + */ +inline uint8_t xran_get_num_eAxc(void *pHandle) +{ + return (xran_lib_get_ctx_fhcfg()->neAxc); +} + + diff --git a/fhi_lib/lib/src/xran_printf.h b/fhi_lib/lib/src/xran_printf.h new file mode 100644 index 0000000..6caee87 --- /dev/null +++ b/fhi_lib/lib/src/xran_printf.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief Modules provide debug prints and utility functions + * @file xran_printf.h + * @ingroup group_source_xran + * @author Intel Corporation + **/ + +#ifndef XRAN_PRINTF_H +#define XRAN_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include + +#define PRINTF_LOG_OK +#define PRINTF_INF_OK +#define PRINTF_ERR_OK +//#define PRINTF_DBG_OK + +#ifndef WIN32 +#ifdef PRINTF_LOG_OK +#define print_log(fmt, args...) printf("%s:" fmt "\n", __FUNCTION__, ## args) +#else /* PRINTF_LOG_OK */ +#define print_log(fmt, args...) +#endif /* PRINTF_LOG_OK */ +#else +#define print_log(fmt, ...) printf("%s:" fmt "\n", __FUNCTION__, __VA_ARGS__) +#endif + +#ifndef WIN32 +#ifdef PRINTF_DBG_OK +#define print_dbg(fmt, args...) printf("%s:[dbg] " fmt "\n", __FUNCTION__, ## args) +#else /* PRINTF_LOG_OK */ +#define print_dbg(fmt, args...) +#endif /* PRINTF_LOG_OK */ +#else +#define print_dbg(fmt, ...) printf("%s:[dbg] " fmt "\n", __FUNCTION__, __VA_ARGS__) +#endif + +#ifndef WIN32 +#ifdef PRINTF_ERR_OK +#define print_err(fmt, args...) printf("%s:[err] " fmt "\n", __FUNCTION__, ## args) +#else /* PRINTF_LOG_OK */ +#define print_err(fmt, args...) +#endif /* PRINTF_LOG_OK */ +#else +#define print_err(fmt, ...) printf("%s:[err] " fmt "\n", __FUNCTION__, __VA_ARGS__) +#endif + +#ifndef WIN32 +#ifdef PRINTF_INF_OK +#define print_inf printf +#else /* PRINTF_LOG_OK */ +#define print_inf +#endif /* PRINTF_LOG_OK */ +#else +#define print_inf printf +#endif + +#ifdef __cplusplus +} +#endif + +#ifndef _IASSERT_ +#define _IASSERT_ + +#ifdef _DEBUG +#define iAssert(p) if(!(p)){fprintf(stderr,\ + "Assertion failed: %s, file %s, line %d, val %d\n",\ + #p, __FILE__, __LINE__, p);exit(-1);} +#else /* _DEBUG */ +#define iAssert(p) +#endif /* _DEBUG */ + +#ifndef PHY_APP +#ifndef _assert +#define _assert(x) +#endif +#endif + +#endif /* _IASSERT_*/ + + + +#ifdef __cplusplus +} +#endif + +#endif // PHY_PRINTF_H diff --git a/fhi_lib/lib/src/xran_sync_api.c b/fhi_lib/lib/src/xran_sync_api.c new file mode 100644 index 0000000..e030a86 --- /dev/null +++ b/fhi_lib/lib/src/xran_sync_api.c @@ -0,0 +1,132 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief This file provides implementation of synchronization related APIs (PTP/1588) + * for XRAN. + * + * @file xran_sync_api.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xran_sync_api.h" +#include "xran_printf.h" + +#define BUF_LEN 256 +#define PROC_DIR "/proc" +#define COMM_FILE "comm" +#define PMC_CMD "pmc -u -b 0 'GET PORT_DATA_SET'" +#define PTP4L_PROC_NAME "ptp4l" +#define PHC2SYS_PROC_NAME "phc2sys" + +static int find_substr(const char *str, const unsigned int str_len, + const char *substr, const unsigned int substr_len) +{ + assert(str); + assert(substr); + unsigned int ind = 0; + + while (ind + substr_len <= str_len) { + if (0 == strncmp(&str[ind], substr, substr_len)) + return 0; + ++ind; + } + return 1; +} + +static int is_process_running(char *pname) +{ + char full_path[BUF_LEN] = {0}; + char read_proc_name[BUF_LEN] = {0}; + int res = 1; + int null = 0; + int dir_fd = dirfd((DIR*)PROC_DIR); + DIR *dir = fdopendir(dir_fd); + if (NULL == dir) { + return 1; + } + + struct dirent *entry = NULL; + while ((entry = readdir(dir))) { + long pid = atol(entry->d_name); + if (0 == pid) + continue; + + snprintf(full_path, BUF_LEN,"%s/%ld/%s", PROC_DIR, pid, COMM_FILE); + int proc_name_file = open(full_path, O_RDONLY); + if (null == proc_name_file) + continue; + fgets( read_proc_name, BUF_LEN, (FILE*)proc_name_file); + if (0 == strncmp(read_proc_name, pname, strlen(pname))) { + res = 0; + close(proc_name_file); + break; + } + close(proc_name_file); + } + closedir(dir); + return res; +} + +static int check_ptp_status() +{ + char pmc_out_line[BUF_LEN]; + const char *keywords[2] = {"portState", "SLAVE"}; + int res = 1; + FILE *pmc_pipe = popen(PMC_CMD, "r"); + if (NULL == pmc_pipe) + return 1; + + while(fgets(pmc_out_line, BUF_LEN, pmc_pipe)) { + if (0 == find_substr(pmc_out_line, strlen(pmc_out_line), keywords[0], + strlen(keywords[0]))) { + if (0 == find_substr(pmc_out_line, strlen(pmc_out_line), + keywords[1], strlen(keywords[1]))) { + res = 0; + break; + } + } + } + fclose(pmc_pipe); + return res; +} + +int xran_is_synchronized() +{ + int res = 0; + res |= is_process_running(PTP4L_PROC_NAME); + print_dbg("PTP4L_PROC_NAME %d\n", res); + res |= is_process_running(PHC2SYS_PROC_NAME); + print_dbg("PHC2SYS_PROC_NAME %d\n", res); + res |= check_ptp_status(); + print_dbg("check_ptp_status %d\n", res); + return res; +} diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c new file mode 100644 index 0000000..875b0b6 --- /dev/null +++ b/fhi_lib/lib/src/xran_timer.c @@ -0,0 +1,185 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides implementation to Timing for XRAN. + * + * @file xran_timer.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include +#include +#include +#include + +#include "xran_timer.h" +#include "xran_printf.h" +#ifndef MLOG_ENABLED +#include "mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif +#include "xran_lib_mlog_tasks_id.h" +#include "ethdi.h" + +#define NSEC_PER_SEC 1000000000L +#define NSEC_PER_USEC 1000L +#define THRESHOLD 35 /**< the avg cost of clock_gettime() in ns */ +#define TIMECOMPENSATION 2 /**< time compensation in us, avg latency of clock_nanosleep */ + +#define SEC_MOD_STOP (30) + +static struct timespec started_time; +static struct timespec last_time; +static struct timespec cur_time; + +static struct timespec* p_cur_time = &cur_time; +static struct timespec* p_last_time = &last_time; + +static struct timespec* p_temp_time; + +static unsigned long current_second = 0; +static unsigned long started_second = 0; +extern uint32_t xran_lib_ota_sym; +extern uint32_t xran_lib_ota_tti; +extern uint32_t xran_lib_ota_sym_idx; + +static int debugStop = 0; + +uint64_t timing_get_current_second(void) +{ + return current_second; +} + +int timing_set_debug_stop(int value) +{ + debugStop = value; + + if(debugStop){ + clock_gettime(CLOCK_REALTIME, &started_time); + started_second =started_time.tv_sec; + } + return debugStop; +} + +int timing_get_debug_stop(void) +{ + return debugStop; +} + +long poll_next_tick(long interval_ns) +{ + long target_time; + long delta; + static int counter = 0; + static long sym_acc = 0; + static long sym_cnt = 0; + + if(counter){ + clock_gettime(CLOCK_REALTIME, p_last_time); + current_second = p_last_time->tv_sec; + counter = 1; + } + + target_time = (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec + interval_ns); + + while(1) + { + clock_gettime(CLOCK_REALTIME, p_cur_time); + delta = (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec) - target_time; + if(delta > 0 || (delta < 0 && abs(delta) < THRESHOLD)) { + if(current_second != p_cur_time->tv_sec){ + current_second = p_cur_time->tv_sec; + xran_lib_ota_sym_idx = 0; + xran_lib_ota_tti = 0; + xran_lib_ota_sym = 0; + sym_cnt = 0; + sym_acc = 0; + print_dbg("ToS:C Sync timestamp: [%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); + if(debugStop){ + if(p_cur_time->tv_sec > started_second && ((p_cur_time->tv_sec % SEC_MOD_STOP) == 0)){ + uint64_t t1; + printf("STOP:[%ld.%09ld]\n", p_cur_time->tv_sec, p_cur_time->tv_nsec); + t1 = MLogTick(); + rte_pause(); + MLogTask(PID_TIME_SYSTIME_STOP, t1, MLogTick()); + xran_if_current_state = XRAN_STOPPED; + } + } + p_cur_time->tv_nsec = 0; // adjust to 1pps + } else { + xran_lib_ota_sym_idx = XranIncrementSymIdx(xran_lib_ota_sym_idx, 14*8); + /* adjust to sym boundary */ + if(sym_cnt & 1) + sym_acc += 8928L; + else + sym_acc += 8929L; + /* fine tune to second boundary */ + if(sym_cnt % 13 == 0) + sym_acc += 1; + + p_cur_time->tv_nsec = sym_acc; + sym_cnt++; + } + if(debugStop && delta < interval_ns*10) + MLogTask(PID_TIME_SYSTIME_POLL, (p_last_time->tv_sec * NSEC_PER_SEC + p_last_time->tv_nsec), (p_cur_time->tv_sec * NSEC_PER_SEC + p_cur_time->tv_nsec)); + p_temp_time = p_last_time; + p_last_time = p_cur_time; + p_cur_time = p_temp_time; + break; + } + } + + return delta; +} + +long sleep_next_tick(long interval) +{ + struct timespec start_time; + struct timespec cur_time; + //struct timespec target_time_convert; + struct timespec sleep_target_time_convert; + long target_time; + long sleep_target_time; + long delta; + + clock_gettime(CLOCK_REALTIME, &start_time); + target_time = (start_time.tv_sec * NSEC_PER_SEC + start_time.tv_nsec + interval * NSEC_PER_USEC) / (interval * NSEC_PER_USEC) * interval; + //printf("target: %ld, current: %ld, %ld\n", target_time, start_time.tv_sec, start_time.tv_nsec); + sleep_target_time = target_time - TIMECOMPENSATION; + sleep_target_time_convert.tv_sec = sleep_target_time * NSEC_PER_USEC / NSEC_PER_SEC; + sleep_target_time_convert.tv_nsec = (sleep_target_time * NSEC_PER_USEC) % NSEC_PER_SEC; + + //target_time_convert.tv_sec = target_time * NSEC_PER_USEC / NSEC_PER_SEC; + //target_time_convert.tv_nsec = (target_time * NSEC_PER_USEC) % NSEC_PER_SEC; + + clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleep_target_time_convert, NULL); + + clock_gettime(CLOCK_REALTIME, &cur_time); + + delta = (cur_time.tv_sec * NSEC_PER_SEC + cur_time.tv_nsec) - target_time * NSEC_PER_USEC; + + return delta; +} + + + diff --git a/fhi_lib/lib/src/xran_transport.c b/fhi_lib/lib/src/xran_transport.c new file mode 100644 index 0000000..9e1d192 --- /dev/null +++ b/fhi_lib/lib/src/xran_transport.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file provides the implementation for Transport lyaer (eCPRI) API. + * + * @file xran_transport.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include +#include +#include +#include + +#include "xran_fh_lls_cu.h" +#include "xran_common.h" +#include "xran_transport.h" +#include "xran_up_api.h" + + +/** + * @brief Compose ecpriRtcid/ecpriPcid + * + * @param CU_Port_ID CU Port ID + * @param BanbSector_ID Band Sector ID + * @param CC_ID Component Carrier ID + * @param Ant_ID RU Port ID (antenna ID) + * @return uint16_t composed ecpriRtcid/ecpriPcid (network byte order) + */ +inline uint16_t xran_compose_cid(uint8_t CU_Port_ID, uint8_t BandSector_ID, uint8_t CC_ID, uint8_t Ant_ID) +{ + uint16_t cid; + XRANEAXCIDCONFIG *conf; + + conf = xran_get_conf_eAxC(NULL); + + cid = ((CU_Port_ID << conf->bit_cuPortId) & conf->mask_cuPortId) + | ((BandSector_ID << conf->bit_bandSectorId) & conf->mask_bandSectorId) + | ((CC_ID << conf->bit_ccId) & conf->mask_ccId) + | ((Ant_ID << conf->bit_ruPortId) & conf->mask_ruPortId); + + return (rte_cpu_to_be_16(cid)); +} + +/** + * @brief Decompose ecpriRtcid/ecpriPcid + * + * @param cid composed ecpriRtcid/ecpriPcid (network byte order) + * @param result the pointer of the structure to store decomposed values + * @return none + */ +inline void xran_decompose_cid(uint16_t cid, struct xran_eaxc_info *result) +{ + XRANEAXCIDCONFIG *conf; + + conf = xran_get_conf_eAxC(NULL); + cid = rte_be_to_cpu_16(cid); + + result->cuPortId = (cid&conf->mask_cuPortId) >> conf->bit_cuPortId; + result->bandSectorId = (cid&conf->mask_bandSectorId) >> conf->bit_bandSectorId; + result->ccId = (cid&conf->mask_ccId) >> conf->bit_ccId; + result->ruPortId = (cid&conf->mask_ruPortId) >> conf->bit_ruPortId; + + return; +} + +/** + * @brief modify the payload size of eCPRI header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet which has eCPRI header already + * @param size payload size to be updated + * @return none + */ +inline void xran_update_ecpri_payload_size(struct rte_mbuf *mbuf, int size) +{ + struct xran_ecpri_hdr *ecpri_hdr; + + ecpri_hdr = rte_pktmbuf_mtod(mbuf, struct xran_ecpri_hdr *); + + ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(size); +} + diff --git a/fhi_lib/lib/src/xran_ul_tables.c b/fhi_lib/lib/src/xran_ul_tables.c new file mode 100644 index 0000000..99feefb --- /dev/null +++ b/fhi_lib/lib/src/xran_ul_tables.c @@ -0,0 +1,858 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + + +/** + * @brief This file defines those table used in 5G NR spec. + * @file xran_ul_tables.c + * @author Intel Corporation + **/ + +#include +#include +#include + +#include "xran_common.h" + +/* 3GPP 38.211-f20 Table - 6.3.3.2-2 */ +const xRANPrachConfigTableStruct gxranPrachDataTable_sub6_fdd[XRAN_PRACH_CONFIG_TABLE_SIZE] = +{ + { 0, { 0 }, 16, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 1, { 0 }, 16, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 2, { 0 }, 16, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 3, { 0 }, 16, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 4, { 0 }, 8, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 5, { 0 }, 8, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 6, { 0 }, 8, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 7, { 0 }, 8, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 8, { 0 }, 4, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 9, { 0 }, 4, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 10, { 0 }, 4, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 11, { 0 }, 4, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 12, { 0 }, 2, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 13, { 0 }, 2, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 14, { 0 }, 2, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 15, { 0 }, 2, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 16, { 0 }, 1, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 17, { 0 }, 1, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 18, { 0 }, 1, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 19, { 0 }, 1, { 0 }, { 1, 6 }, 2, 0, 0, 0, 0 }, + { 20, { 0 }, 1, { 0 }, { 2, 7 }, 2, 0, 0, 0, 0 }, + { 21, { 0 }, 1, { 0 }, { 3, 8 }, 2, 0, 0, 0, 0 }, + { 22, { 0 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 0, 0, 0 }, + { 23, { 0 }, 1, { 0 }, { 2, 5, 8 }, 3, 0, 0, 0, 0 }, + { 24, { 0 }, 1, { 0 }, { 3, 6, 9 }, 3, 0, 0, 0, 0 }, + { 25, { 0 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 0, 0, 0 }, + { 26, { 0 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 0, 0, 0 }, + { 27, { 0 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 0, 0, 0 }, + { 28, { 1 }, 16, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 29, { 1 }, 16, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 30, { 1 }, 16, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 31, { 1 }, 16, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 32, { 1 }, 8, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 33, { 1 }, 8, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 34, { 1 }, 8, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 35, { 1 }, 8, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 36, { 1 }, 4, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 37, { 1 }, 4, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 38, { 1 }, 4, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 39, { 1 }, 4, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 40, { 1 }, 2, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 41, { 1 }, 2, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 42, { 1 }, 2, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 43, { 1 }, 2, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 44, { 1 }, 1, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 45, { 1 }, 1, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 46, { 1 }, 1, { 0 }, { 9 }, 1, 0, 0, 0, 0 }, + { 47, { 1 }, 1, { 0 }, { 1, 6 }, 2, 0, 0, 0, 0 }, + { 48, { 1 }, 1, { 0 }, { 2, 7 }, 2, 0, 0, 0, 0 }, + { 49, { 1 }, 1, { 0 }, { 3, 8 }, 2, 0, 0, 0, 0 }, + { 50, { 1 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 0, 0, 0 }, + { 51, { 1 }, 1, { 0 }, { 2, 5, 8 }, 3, 0, 0, 0, 0 }, + { 52, { 1 }, 1, { 0 }, { 3, 6, 9 }, 3, 0, 0, 0, 0 }, + { 53, { 2 }, 16, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 54, { 2 }, 8, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 55, { 2 }, 4, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 56, { 2 }, 2, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 57, { 2 }, 2, { 0 }, { 5 }, 1, 0, 0, 0, 0 }, + { 58, { 2 }, 1, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 59, { 2 }, 1, { 0 }, { 5 }, 1, 0, 0, 0, 0 }, + { 60, { 3 }, 16, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 61, { 3 }, 16, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 62, { 3 }, 16, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 63, { 3 }, 16, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 64, { 3 }, 8, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 65, { 3 }, 8, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 66, { 3 }, 8, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 67, { 3 }, 8, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 68, { 3 }, 4, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 69, { 3 }, 4, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 70, { 3 }, 4, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 71, { 3 }, 4, { 1 }, { 1 }, 1, 0, 0, 0, 0 }, + { 72, { 3 }, 2, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 73, { 3 }, 2, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 74, { 3 }, 2, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 75, { 3 }, 2, { 0 }, { 1 }, 1, 0, 0, 0, 0 }, + { 76, { 3 }, 1, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 77, { 3 }, 1, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 78, { 3 }, 1, { 0 }, { 1, 6 }, 2, 0, 0, 0, 0 }, + { 79, { 3 }, 1, { 0 }, { 2, 7 }, 2, 0, 0, 0, 0 }, + { 80, { 3 }, 1, { 0 }, { 3, 8 }, 2, 0, 0, 0, 0 }, + { 81, { 3 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 0, 0, 0 }, + { 82, { 3 }, 1, { 0 }, { 2, 5, 8 }, 3, 0, 0, 0, 0 }, + { 83, { 3 }, 1, { 0 }, { 3, 6, 9 }, 3, 0, 0, 0, 0 }, + { 84, { 3 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 0, 0, 0 }, + { 85, { 3 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 0, 0, 0 }, + { 86, { 3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 0, 0, 0 }, + { 87, { FORMAT_A1 }, 16, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 88, { FORMAT_A1 }, 16, { 1 }, { 4 }, 1, 0, 2, 6, 2 }, + { 89, { FORMAT_A1 }, 8, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 90, { FORMAT_A1 }, 8, { 1 }, { 4 }, 1, 0, 2, 6, 2 }, + { 91, { FORMAT_A1 }, 4, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 92, { FORMAT_A1 }, 4, { 1 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 93, { FORMAT_A1 }, 4, { 0 }, { 4 }, 1, 0, 2, 6, 2 }, + { 94, { FORMAT_A1 }, 2, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 95, { FORMAT_A1 }, 2, { 0 }, { 1 }, 1, 0, 2, 6, 2 }, + { 96, { FORMAT_A1 }, 2, { 0 }, { 4 }, 1, 0, 2, 6, 2 }, + { 97, { FORMAT_A1 }, 2, { 0 }, { 7 }, 1, 0, 2, 6, 2 }, + { 98, { FORMAT_A1 }, 1, { 0 }, { 4 }, 1, 0, 1, 6, 2 }, + { 99, { FORMAT_A1 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 6, 2 }, + { 100, { FORMAT_A1 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 101, { FORMAT_A1 }, 1, { 0 }, { 1 }, 1, 0, 2, 6, 2 }, + { 102, { FORMAT_A1 }, 1, { 0 }, { 7 }, 1, 0, 2, 6, 2 }, + { 103, { FORMAT_A1 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 6, 2 }, + { 104, { FORMAT_A1 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 6, 2 }, + { 105, { FORMAT_A1 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 6, 2 }, + { 106, { FORMAT_A1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 6, 2 }, + { 107, { FORMAT_A1 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 6, 2 }, + { 108, { FORMAT_A1, FORMAT_B1 }, 2, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 109, { FORMAT_A1, FORMAT_B1 }, 2, { 0 }, { 4 }, 1, 0, 2, 7, 2 }, + { 110, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 4 }, 1, 0, 1, 7, 2 }, + { 111, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 7, 2 }, + { 112, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 113, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 1 }, 1, 0, 2, 7, 2 }, + { 114, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 7 }, 1, 0, 2, 7, 2 }, + { 115, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 7, 2 }, + { 116, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 7, 2 }, + { 117, { FORMAT_A2 }, 16, { 1 }, { 2, 6, 9 }, 3, 0, 1, 3, 4 }, + { 118, { FORMAT_A2 }, 16, { 1 }, { 4 }, 1, 0, 2, 3, 4 }, + { 119, { FORMAT_A2 }, 8, { 1 }, { 2, 6, 9 }, 3, 0, 1, 3, 4 }, + { 120, { FORMAT_A2 }, 8, { 1 }, { 4 }, 1, 0, 2, 3, 4 }, + { 121, { FORMAT_A2 }, 4, { 0 }, { 2, 6, 9 }, 3, 0, 1, 3, 4 }, + { 122, { FORMAT_A2 }, 4, { 0 }, { 4 }, 1, 0, 2, 3, 4 }, + { 123, { FORMAT_A2 }, 2, { 1 }, { 2, 6, 9 }, 3, 0, 1, 3, 4 }, + { 124, { FORMAT_A2 }, 2, { 0 }, { 1 }, 1, 0, 2, 3, 4 }, + { 125, { FORMAT_A2 }, 2, { 0 }, { 4 }, 1, 0, 2, 3, 4 }, + { 126, { FORMAT_A2 }, 2, { 0 }, { 7 }, 1, 0, 2, 3, 4 }, + { 127, { FORMAT_A2 }, 1, { 0 }, { 4 }, 1, 0, 1, 3, 4 }, + { 128, { FORMAT_A2 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 3, 4 }, + { 129, { FORMAT_A2 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 3, 4 }, + { 130, { FORMAT_A2 }, 1, { 0 }, { 1 }, 1, 0, 2, 3, 4 }, + { 131, { FORMAT_A2 }, 1, { 0 }, { 7 }, 1, 0, 2, 3, 4 }, + { 132, { FORMAT_A2 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 3, 4 }, + { 133, { FORMAT_A2 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 3, 4 }, + { 134, { FORMAT_A2 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 3, 4 }, + { 135, { FORMAT_A2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 3, 4 }, + { 136, { FORMAT_A2 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 3, 4 }, + { 137, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 2, 6, 9 }, 3, 0, 1, 3, 4 }, + { 138, { FORMAT_A2, FORMAT_B2 }, 2, { 0 }, { 4 }, 1, 0, 2, 3, 4 }, + { 139, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 4 }, 1, 0, 1, 3, 4 }, + { 140, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 3, 4 }, + { 141, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 3, 4 }, + { 142, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 1 }, 1, 0, 2, 3, 4 }, + { 143, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 7 }, 1, 0, 2, 3, 4 }, + { 144, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 3, 4 }, + { 145, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 3, 4 }, + { 146, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 3, 4 }, + { 147, { FORMAT_A3 }, 16, { 1 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 148, { FORMAT_A3 }, 16, { 1 }, { 4 }, 1, 0, 2, 2, 6 }, + { 149, { FORMAT_A3 }, 8, { 1 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 150, { FORMAT_A3 }, 8, { 1 }, { 4 }, 1, 0, 2, 2, 6 }, + { 151, { FORMAT_A3 }, 4, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 152, { FORMAT_A3 }, 4, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 153, { FORMAT_A3 }, 2, { 1 }, { 2, 6, 9 }, 3, 0, 2, 2, 6 }, + { 154, { FORMAT_A3 }, 2, { 0 }, { 1 }, 1, 0, 2, 2, 6 }, + { 155, { FORMAT_A3 }, 2, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 156, { FORMAT_A3 }, 2, { 0 }, { 7 }, 1, 0, 2, 2, 6 }, + { 157, { FORMAT_A3 }, 1, { 0 }, { 4 }, 1, 0, 1, 2, 6 }, + { 158, { FORMAT_A3 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 2, 6 }, + { 159, { FORMAT_A3 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 160, { FORMAT_A3 }, 1, { 0 }, { 1 }, 1, 0, 2, 2, 6 }, + { 161, { FORMAT_A3 }, 1, { 0 }, { 7 }, 1, 0, 2, 2, 6 }, + { 162, { FORMAT_A3 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 2, 6 }, + { 163, { FORMAT_A3 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 2, 6 }, + { 164, { FORMAT_A3 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 2, 6 }, + { 165, { FORMAT_A3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 2, 6 }, + { 166, { FORMAT_A3 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 2, 6 }, + { 167, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 2, 6, 9 }, 3, 0, 2, 2, 6 }, + { 168, { FORMAT_A3, FORMAT_B3 }, 2, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 169, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 170, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 2, 6 }, + { 171, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 172, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 1 }, 1, 0, 1, 2, 6 }, + { 173, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 7 }, 1, 0, 2, 2, 6 }, + { 174, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 2, 6 }, + { 175, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 2, 6 }, + { 176, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 2, 6 }, + { 177, { FORMAT_B1 }, 16, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 178, { FORMAT_B1 }, 16, { 1 }, { 4 }, 1, 0, 2, 7, 2 }, + { 179, { FORMAT_B1 }, 8, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 180, { FORMAT_B1 }, 8, { 1 }, { 4 }, 1, 0, 2, 7, 2 }, + { 181, { FORMAT_B1 }, 4, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 182, { FORMAT_B1 }, 4, { 1 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 183, { FORMAT_B1 }, 4, { 0 }, { 4 }, 1, 0, 2, 7, 2 }, + { 184, { FORMAT_B1 }, 2, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 185, { FORMAT_B1 }, 2, { 0 }, { 1 }, 1, 0, 2, 7, 2 }, + { 186, { FORMAT_B1 }, 2, { 0 }, { 4 }, 1, 0, 2, 7, 2 }, + { 187, { FORMAT_B1 }, 2, { 0 }, { 7 }, 1, 0, 2, 7, 2 }, + { 188, { FORMAT_B1 }, 1, { 0 }, { 4 }, 1, 0, 1, 7, 2 }, + { 189, { FORMAT_B1 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 7, 2 }, + { 190, { FORMAT_B1 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 191, { FORMAT_B1 }, 1, { 0 }, { 1 }, 1, 0, 2, 7, 2 }, + { 192, { FORMAT_B1 }, 1, { 0 }, { 7 }, 1, 0, 2, 7, 2 }, + { 193, { FORMAT_B1 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 7, 2 }, + { 194, { FORMAT_B1 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 7, 2 }, + { 195, { FORMAT_B1 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 7, 2 }, + { 196, { FORMAT_B1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 7, 2 }, + { 197, { FORMAT_B1 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 7, 12 }, + { 198, { FORMAT_B4 }, 16, { 0 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 199, { FORMAT_B4 }, 16, { 1 }, { 4 }, 1, 0, 2, 1, 12 }, + { 200, { FORMAT_B4 }, 8, { 0 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 201, { FORMAT_B4 }, 8, { 1 }, { 4 }, 1, 0, 2, 1, 12 }, + { 202, { FORMAT_B4 }, 4, { 0 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 203, { FORMAT_B4 }, 4, { 0 }, { 4 }, 1, 0, 2, 1, 12 }, + { 204, { FORMAT_B4 }, 4, { 1 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 205, { FORMAT_B4 }, 2, { 0 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 206, { FORMAT_B4 }, 2, { 0 }, { 1 }, 1, 0, 2, 1, 12 }, + { 207, { FORMAT_B4 }, 2, { 0 }, { 4 }, 1, 0, 2, 1, 12 }, + { 208, { FORMAT_B4 }, 2, { 0 }, { 7 }, 1, 0, 2, 1, 12 }, + { 209, { FORMAT_B4 }, 1, { 0 }, { 1 }, 1, 0, 2, 1, 12 }, + { 210, { FORMAT_B4 }, 1, { 0 }, { 4 }, 1, 0, 2, 1, 12 }, + { 211, { FORMAT_B4 }, 1, { 0 }, { 7 }, 1, 0, 2, 1, 12 }, + { 212, { FORMAT_B4 }, 1, { 0 }, { 1, 6 }, 2, 0, 2, 1, 12 }, + { 213, { FORMAT_B4 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 1, 12 }, + { 214, { FORMAT_B4 }, 1, { 0 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 215, { FORMAT_B4 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 1, 12 }, + { 216, { FORMAT_B4 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 1, 12 }, + { 217, { FORMAT_B4 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 1, 12 }, + { 218, { FORMAT_B4 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 1, 12 }, + { 219, { FORMAT_C0 }, 8, { 1 }, { 4 }, 1, 0, 2, 7, 2 }, + { 220, { FORMAT_C0 }, 4, { 1 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 221, { FORMAT_C0 }, 4, { 0 }, { 4 }, 1, 0, 2, 7, 2 }, + { 222, { FORMAT_C0 }, 2, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 223, { FORMAT_C0 }, 2, { 0 }, { 1 }, 1, 0, 2, 7, 2 }, + { 224, { FORMAT_C0 }, 2, { 0 }, { 4 }, 1, 0, 2, 7, 2 }, + { 225, { FORMAT_C0 }, 2, { 0 }, { 7 }, 1, 0, 2, 7, 2 }, + { 226, { FORMAT_C0 }, 1, { 0 }, { 4 }, 1, 0, 1, 7, 2 }, + { 227, { FORMAT_C0 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 7, 2 }, + { 228, { FORMAT_C0 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 7, 2 }, + { 229, { FORMAT_C0 }, 1, { 0 }, { 1 }, 1, 0, 2, 7, 2 }, + { 230, { FORMAT_C0 }, 1, { 0 }, { 7 }, 1, 0, 2, 7, 2 }, + { 231, { FORMAT_C0 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 7, 2 }, + { 232, { FORMAT_C0 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 7, 2 }, + { 233, { FORMAT_C0 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 7, 2 }, + { 234, { FORMAT_C0 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 7, 2 }, + { 235, { FORMAT_C0 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 7, 2 }, + { 236, { FORMAT_C2 }, 16, { 1 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 237, { FORMAT_C2 }, 16, { 1 }, { 4 }, 1, 0, 2, 2, 6 }, + { 238, { FORMAT_C2 }, 8, { 1 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 239, { FORMAT_C2 }, 8, { 1 }, { 4 }, 1, 0, 2, 2, 6 }, + { 240, { FORMAT_C2 }, 4, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 241, { FORMAT_C2 }, 4, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 242, { FORMAT_C2 }, 2, { 1 }, { 2, 6, 9 }, 3, 0, 2, 2, 6 }, + { 243, { FORMAT_C2 }, 2, { 0 }, { 1 }, 1, 0, 2, 2, 6 }, + { 244, { FORMAT_C2 }, 2, { 0 }, { 4 }, 1, 0, 2, 2, 6 }, + { 245, { FORMAT_C2 }, 2, { 0 }, { 7 }, 1, 0, 2, 2, 6 }, + { 246, { FORMAT_C2 }, 1, { 0 }, { 4 }, 1, 0, 1, 2, 6 }, + { 247, { FORMAT_C2 }, 1, { 0 }, { 1, 6 }, 2, 0, 1, 2, 6 }, + { 248, { FORMAT_C2 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 249, { FORMAT_C2 }, 1, { 0 }, { 1 }, 1, 0, 2, 2, 6 }, + { 250, { FORMAT_C2 }, 1, { 0 }, { 7 }, 1, 0, 2, 2, 6 }, + { 251, { FORMAT_C2 }, 1, { 0 }, { 2, 7 }, 2, 0, 2, 2, 6 }, + { 252, { FORMAT_C2 }, 1, { 0 }, { 1, 4, 7 }, 3, 0, 2, 2, 6 }, + { 253, { FORMAT_C2 }, 1, { 0 }, { 0, 2, 4, 6, 8 }, 5, 0, 2, 2, 6 }, + { 254, { FORMAT_C2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 2, 6 }, + { 255, { FORMAT_C2 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 2, 2, 6 }, +}; +/* 3GPP 38.211-f20 Table - 6.3.3.2-3 */ +const xRANPrachConfigTableStruct gxranPrachDataTable_sub6_tdd[XRAN_PRACH_CONFIG_TABLE_SIZE] = +{ + { 0, { 0 }, 16, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 1, { 0 }, 8, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 2, { 0 }, 4, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 3, { 0 }, 2, { 0 }, { 9 }, 1, 0, 0, 0, 0 }, + { 4, { 0 }, 2, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 5, { 0 }, 2, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 6, { 0 }, 2, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 7, { 0 }, 1, { 0 }, { 9 }, 1, 0, 0, 0, 0 }, + { 8, { 0 }, 1, { 0 }, { 8 }, 1, 0, 0, 0, 0 }, + { 9, { 0 }, 1, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 10, { 0 }, 1, { 0 }, { 6 }, 1, 0, 0, 0, 0 }, + { 11, { 0 }, 1, { 0 }, { 5 }, 1, 0, 0, 0, 0 }, + { 12, { 0 }, 1, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 13, { 0 }, 1, { 0 }, { 3 }, 1, 0, 0, 0, 0 }, + { 14, { 0 }, 1, { 0 }, { 2 }, 1, 0, 0, 0, 0 }, + { 15, { 0 }, 1, { 0 }, { 1, 6 }, 2, 0, 0, 0, 0 }, + { 16, { 0 }, 1, { 0 }, { 1, 6 }, 2, 7, 0, 0, 0 }, + { 17, { 0 }, 1, { 0 }, { 4, 9 }, 2, 0, 0, 0, 0 }, + { 18, { 0 }, 1, { 0 }, { 3, 8 }, 2, 0, 0, 0, 0 }, + { 19, { 0 }, 1, { 0 }, { 2, 7 }, 2, 0, 0, 0, 0 }, + { 20, { 0 }, 1, { 0 }, { 8, 9 }, 2, 0, 0, 0, 0 }, + { 21, { 0 }, 1, { 0 }, { 4, 8, 9 }, 3, 0, 0, 0, 0 }, + { 22, { 0 }, 1, { 0 }, { 3, 4, 9 }, 3, 0, 0, 0, 0 }, + { 23, { 0 }, 1, { 0 }, { 7, 8, 9 }, 3, 0, 0, 0, 0 }, + { 24, { 0 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 0, 0, 0 }, + { 25, { 0 }, 1, { 0 }, { 6, 7, 8, 9 }, 4, 0, 0, 0, 0 }, + { 26, { 0 }, 1, { 0 }, { 1, 4, 6, 9 }, 4, 0, 0, 0, 0 }, + { 27, { 0 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 0, 0, 0 }, + { 28, { 1 }, 16, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 29, { 1 }, 8, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 30, { 1 }, 4, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 31, { 1 }, 2, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 32, { 1 }, 2, { 1 }, { 7 }, 1, 0, 0, 0, 0 }, + { 33, { 1 }, 1, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 34, { 2 }, 16, { 1 }, { 6 }, 1, 0, 0, 0, 0 }, + { 35, { 2 }, 8, { 1 }, { 6 }, 1, 0, 0, 0, 0 }, + { 36, { 2 }, 4, { 1 }, { 6 }, 1, 0, 0, 0, 0 }, + { 37, { 2 }, 2, { 0 }, { 6 }, 1, 7, 0, 0, 0 }, + { 38, { 2 }, 2, { 1 }, { 6 }, 1, 7, 0, 0, 0 }, + { 39, { 2 }, 1, { 0 }, { 6 }, 1, 7, 0, 0, 0 }, + { 40, { 3 }, 16, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 41, { 3 }, 8, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 42, { 3 }, 4, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 43, { 3 }, 2, { 0 }, { 9 }, 1, 0, 0, 0, 0 }, + { 44, { 3 }, 2, { 1 }, { 9 }, 1, 0, 0, 0, 0 }, + { 45, { 3 }, 2, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 46, { 3 }, 2, { 1 }, { 4 }, 1, 0, 0, 0, 0 }, + { 47, { 3 }, 1, { 0 }, { 9 }, 1, 0, 0, 0, 0 }, + { 48, { 3 }, 1, { 0 }, { 8 }, 1, 0, 0, 0, 0 }, + { 49, { 3 }, 1, { 0 }, { 7 }, 1, 0, 0, 0, 0 }, + { 50, { 3 }, 1, { 0 }, { 6 }, 1, 0, 0, 0, 0 }, + { 51, { 3 }, 1, { 0 }, { 5 }, 1, 0, 0, 0, 0 }, + { 52, { 3 }, 1, { 0 }, { 4 }, 1, 0, 0, 0, 0 }, + { 53, { 3 }, 1, { 0 }, { 3 }, 1, 0, 0, 0, 0 }, + { 54, { 3 }, 1, { 0 }, { 2 }, 1, 0, 0, 0, 0 }, + { 55, { 3 }, 1, { 0 }, { 1, 6 }, 2, 0, 0, 0, 0 }, + { 56, { 3 }, 1, { 0 }, { 1, 6 }, 2, 7, 0, 0, 0 }, + { 57, { 3 }, 1, { 0 }, { 4, 9 }, 2, 0, 0, 0, 0 }, + { 58, { 3 }, 1, { 0 }, { 3, 8 }, 2, 0, 0, 0, 0 }, + { 59, { 3 }, 1, { 0 }, { 2, 7 }, 2, 0, 0, 0, 0 }, + { 60, { 3 }, 1, { 0 }, { 8, 9 }, 2, 0, 0, 0, 0 }, + { 61, { 3 }, 1, { 0 }, { 4, 8, 9 }, 3, 0, 0, 0, 0 }, + { 62, { 3 }, 1, { 0 }, { 3, 4, 9 }, 3, 0, 0, 0, 0 }, + { 63, { 3 }, 1, { 0 }, { 7, 8, 9 }, 3, 0, 0, 0, 0 }, + { 64, { 3 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 0, 0, 0 }, + { 65, { 3 }, 1, { 0 }, { 1, 4, 6, 9 }, 4, 0, 0, 0, 0 }, + { 66, { 3 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 0, 0, 0 }, + { 67, { FORMAT_A1 }, 18, { 1 }, { 9 }, 1, 0, 2, 6, 2 }, + { 68, { FORMAT_A1 }, 8, { 1 }, { 9 }, 1, 0, 2, 6, 2 }, + { 69, { FORMAT_A1 }, 4, { 1 }, { 9 }, 1, 0, 1, 6, 2 }, + { 70, { FORMAT_A1 }, 2, { 1 }, { 9 }, 1, 0, 1, 6, 2 }, + { 71, { FORMAT_A1 }, 2, { 1 }, { 4, 9 }, 2, 7, 1, 3, 2 }, + { 72, { FORMAT_A1 }, 2, { 1 }, { 7, 9 }, 2, 7, 1, 3, 2 }, + { 73, { FORMAT_A1 }, 2, { 1 }, { 7, 9 }, 2, 0, 1, 6, 2 }, + { 74, { FORMAT_A1 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 6, 2 }, + { 75, { FORMAT_A1 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 6, 2 }, + { 76, { FORMAT_A1 }, 2, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 0, 1, 6, 2 }, + { 77, { FORMAT_A1 }, 1, { 0 }, { 9 }, 1, 0, 2, 6, 2 }, + { 78, { FORMAT_A1 }, 1, { 0 }, { 9 }, 1, 7, 1, 3, 2 }, + { 79, { FORMAT_A1 }, 1, { 0 }, { 9 }, 1, 0, 1, 6, 2 }, + { 80, { FORMAT_A1 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 6, 2 }, + { 81, { FORMAT_A1 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 6, 2 }, + { 82, { FORMAT_A1 }, 1, { 0 }, { 7, 9 }, 2, 7, 1, 3, 2 }, + { 83, { FORMAT_A1 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 1, 6, 2 }, + { 84, { FORMAT_A1 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 2, 6, 2 }, + { 85, { FORMAT_A1 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 1, 6, 2 }, + { 86, { FORMAT_A1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 1, 3, 2 }, + { 87, { FORMAT_A2 }, 16, { 1 }, { 9 }, 1, 0, 2, 3, 4 }, + { 88, { FORMAT_A2 }, 8, { 1 }, { 9 }, 1, 0, 2, 3, 4 }, + { 89, { FORMAT_A2 }, 4, { 1 }, { 9 }, 1, 0, 1, 3, 4 }, + { 90, { FORMAT_A2 }, 2, { 1 }, { 7, 9 }, 2, 0, 1, 3, 4 }, + { 91, { FORMAT_A2 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 3, 4 }, + { 92, { FORMAT_A2 }, 2, { 1 }, { 7, 9 }, 2, 9, 1, 1, 4 }, + { 93, { FORMAT_A2 }, 2, { 1 }, { 4, 9 }, 2, 9, 1, 1, 4 }, + { 94, { FORMAT_A2 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 3, 4 }, + { 95, { FORMAT_A2 }, 16, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 0, 1, 3, 4 }, + { 96, { FORMAT_A2 }, 1, { 0 }, { 2 }, 1, 0, 1, 3, 4 }, + { 97, { FORMAT_A2 }, 1, { 0 }, { 9 }, 1, 0, 1, 3, 4 }, + { 98, { FORMAT_A2 }, 2, { 1 }, { 9 }, 1, 0, 1, 3, 4 }, + { 99, { FORMAT_A2 }, 1, { 0 }, { 9 }, 1, 0, 2, 3, 4 }, + { 100, { FORMAT_A2 }, 1, { 0 }, { 9 }, 1, 9, 1, 1, 4 }, + { 101, { FORMAT_A2 }, 1, { 0 }, { 9 }, 1, 0, 1, 3, 4 }, + { 102, { FORMAT_A2 }, 1, { 0 }, { 2, 7 }, 2, 0, 1, 3, 4 }, + { 103, { FORMAT_A2 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 3, 4 }, + { 104, { FORMAT_A2 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 3, 4 }, + { 105, { FORMAT_A2 }, 1, { 0 }, { 7, 9 }, 2, 9, 1, 1, 4 }, + { 106, { FORMAT_A2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 1, 3, 4 }, + { 107, { FORMAT_A2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 2, 3, 4 }, + { 108, { FORMAT_A2 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 1, 3, 4 }, + { 109, { FORMAT_A2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 9, 1, 1, 4 }, + { 110, { FORMAT_A3 }, 16, { 1 }, { 9 }, 1, 0, 2, 2, 6 }, + { 111, { FORMAT_A3 }, 8, { 1 }, { 9 }, 1, 0, 2, 2, 6 }, + { 112, { FORMAT_A3 }, 4, { 1 }, { 9 }, 1, 0, 1, 2, 6 }, + { 113, { FORMAT_A3 }, 2, { 1 }, { 4, 9 }, 2, 7, 1, 1, 6 }, + { 114, { FORMAT_A3 }, 2, { 1 }, { 7, 9 }, 2, 7, 1, 1, 6 }, + { 115, { FORMAT_A3 }, 2, { 1 }, { 7, 9 }, 2, 0, 1, 2, 6 }, + { 116, { FORMAT_A3 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 2, 6 }, + { 117, { FORMAT_A3 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 2, 6 }, + { 118, { FORMAT_A3 }, 2, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 0, 1, 2, 6 }, + { 119, { FORMAT_A3 }, 1, { 0 }, { 2 }, 1, 0, 1, 2, 6 }, + { 120, { FORMAT_A3 }, 1, { 0 }, { 7 }, 1, 0, 1, 2, 6 }, + { 121, { FORMAT_A3 }, 2, { 1 }, { 9 }, 1, 0, 1, 2, 6 }, + { 122, { FORMAT_A3 }, 1, { 0 }, { 9 }, 1, 0, 2, 2, 6 }, + { 123, { FORMAT_A3 }, 1, { 0 }, { 9 }, 1, 7, 1, 1, 6 }, + { 124, { FORMAT_A3 }, 1, { 0 }, { 9 }, 1, 0, 1, 2, 6 }, + { 125, { FORMAT_A3 }, 1, { 0 }, { 2, 7 }, 2, 0, 1, 2, 6 }, + { 126, { FORMAT_A3 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 2, 6 }, + { 127, { FORMAT_A3 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 128, { FORMAT_A3 }, 1, { 0 }, { 7, 9 }, 2, 7, 1, 1, 6 }, + { 129, { FORMAT_A3 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 1, 2, 6 }, + { 130, { FORMAT_A3 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 2, 2, 6 }, + { 131, { FORMAT_A3 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 1, 2, 6 }, + { 132, { FORMAT_A3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 7, 1, 1, 6 }, + { 133, { FORMAT_B1 }, 4, { 1 }, { 9 }, 1, 2, 1, 6, 2 }, + { 134, { FORMAT_B1 }, 2, { 1 }, { 9 }, 1, 2, 1, 6, 2 }, + { 135, { FORMAT_B1 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 6, 2 }, + { 136, { FORMAT_B1 }, 2, { 1 }, { 4, 9 }, 2, 8, 1, 3, 2 }, + { 137, { FORMAT_B1 }, 2, { 1 }, { 4, 9 }, 2, 2, 2, 6, 2 }, + { 138, { FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 2, 2, 6, 2 }, + { 139, { FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 8, 1, 3, 2 }, + { 140, { FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 2, 1, 6, 2 }, + { 141, { FORMAT_B1 }, 1, { 0 }, { 8, 9 }, 2, 2, 2, 6, 2 }, + { 142, { FORMAT_B1 }, 1, { 0 }, { 4, 9 }, 2, 2, 1, 6, 2 }, + { 143, { FORMAT_B1 }, 1, { 0 }, { 7, 9 }, 2, 8, 1, 3, 2 }, + { 144, { FORMAT_B1 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 2, 1, 6, 2 }, + { 145, { FORMAT_B4 }, 16, { 1 }, { 9 }, 1, 0, 2, 1, 12 }, + { 146, { FORMAT_B4 }, 8, { 1 }, { 9 }, 1, 0, 2, 1, 12 }, + { 147, { FORMAT_B4 }, 4, { 1 }, { 9 }, 1, 2, 1, 1, 12 }, + { 148, { FORMAT_B4 }, 2, { 1 }, { 9 }, 1, 0, 1, 1, 12 }, + { 149, { FORMAT_B4 }, 2, { 1 }, { 9 }, 1, 2, 1, 1, 12 }, + { 150, { FORMAT_B4 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 1, 12 }, + { 151, { FORMAT_B4 }, 2, { 1 }, { 4, 9 }, 2, 2, 1, 1, 12 }, + { 152, { FORMAT_B4 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 1, 12 }, + { 153, { FORMAT_B4 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 1, 12 }, + { 154, { FORMAT_B4 }, 2, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 0, 1, 1, 12 }, + { 155, { FORMAT_B4 }, 1, { 0 }, { 1 }, 1, 0, 1, 1, 12 }, + { 156, { FORMAT_B4 }, 1, { 0 }, { 2 }, 1, 0, 1, 1, 12 }, + { 157, { FORMAT_B4 }, 1, { 0 }, { 4 }, 1, 0, 1, 1, 12 }, + { 158, { FORMAT_B4 }, 1, { 0 }, { 7 }, 1, 0, 1, 1, 12 }, + { 159, { FORMAT_B4 }, 1, { 0 }, { 9 }, 1, 0, 1, 1, 12 }, + { 160, { FORMAT_B4 }, 1, { 0 }, { 9 }, 1, 2, 1, 1, 12 }, + { 161, { FORMAT_B4 }, 1, { 0 }, { 9 }, 1, 0, 2, 1, 12 }, + { 162, { FORMAT_B4 }, 1, { 0 }, { 4, 9 }, 2, 2, 1, 1, 12 }, + { 163, { FORMAT_B4 }, 1, { 0 }, { 7, 9 }, 2, 2, 1, 1, 12 }, + { 164, { FORMAT_B4 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 1, 12 }, + { 165, { FORMAT_B4 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 1, 1, 12 }, + { 166, { FORMAT_B4 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 2, 1, 1, 12 }, + { 167, { FORMAT_B4 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 0, 2, 1, 12 }, + { 168, { FORMAT_B4 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 2, 1, 1, 12 }, + { 169, { FORMAT_C0 }, 16, { 1 }, { 9 }, 1, 2, 2, 6, 2 }, + { 170, { FORMAT_C0 }, 8, { 1 }, { 9 }, 1, 2, 2, 6, 2 }, + { 171, { FORMAT_C0 }, 4, { 1 }, { 9 }, 1, 2, 1, 6, 2 }, + { 172, { FORMAT_C0 }, 2, { 1 }, { 9 }, 1, 2, 1, 6, 2 }, + { 173, { FORMAT_C0 }, 2, { 1 }, { 8, 9 }, 2, 2, 2, 6, 2 }, + { 174, { FORMAT_C0 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 6, 2 }, + { 175, { FORMAT_C0 }, 2, { 1 }, { 7, 9 }, 2, 8, 1, 3, 2 }, + { 176, { FORMAT_C0 }, 2, { 1 }, { 4, 9 }, 2, 8, 1, 3, 2 }, + { 177, { FORMAT_C0 }, 2, { 1 }, { 4, 9 }, 2, 2, 2, 6, 2 }, + { 178, { FORMAT_C0 }, 2, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 2, 1, 6, 2 }, + { 179, { FORMAT_C0 }, 1, { 0 }, { 9 }, 1, 2, 2, 6, 2 }, + { 180, { FORMAT_C0 }, 1, { 0 }, { 9 }, 1, 8, 1, 3, 2 }, + { 181, { FORMAT_C0 }, 1, { 0 }, { 9 }, 1, 2, 1, 6, 2 }, + { 182, { FORMAT_C0 }, 1, { 0 }, { 8, 9 }, 2, 2, 2, 6, 2 }, + { 183, { FORMAT_C0 }, 1, { 0 }, { 4, 9 }, 2, 2, 1, 6, 2 }, + { 184, { FORMAT_C0 }, 1, { 0 }, { 7, 9 }, 2, 8, 1, 3, 2 }, + { 185, { FORMAT_C0 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 1, 6, 2 }, + { 186, { FORMAT_C0 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 2, 6, 2 }, + { 187, { FORMAT_C0 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 2, 1, 6, 2 }, + { 188, { FORMAT_C0 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 8, 1, 3, 2 }, + { 189, { FORMAT_C2 }, 16, { 1 }, { 9 }, 1, 2, 2, 2, 6 }, + { 190, { FORMAT_C2 }, 8, { 1 }, { 9 }, 1, 2, 2, 2, 6 }, + { 191, { FORMAT_C2 }, 4, { 1 }, { 9 }, 1, 2, 1, 2, 6 }, + { 192, { FORMAT_C2 }, 2, { 1 }, { 9 }, 1, 2, 1, 2, 6 }, + { 193, { FORMAT_C2 }, 2, { 1 }, { 8, 9 }, 2, 2, 2, 2, 6 }, + { 194, { FORMAT_C2 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 2, 6 }, + { 195, { FORMAT_C2 }, 2, { 1 }, { 7, 9 }, 2, 8, 1, 1, 6 }, + { 196, { FORMAT_C2 }, 2, { 1 }, { 4, 9 }, 2, 8, 1, 1, 6 }, + { 197, { FORMAT_C2 }, 2, { 1 }, { 4, 9 }, 2, 2, 2, 2, 6 }, + { 198, { FORMAT_C2 }, 2, { 1 }, { 2, 3, 4, 7, 8, 9 }, 6, 2, 1, 2, 6 }, + { 199, { FORMAT_C2 }, 8, { 1 }, { 9 }, 1, 8, 2, 1, 6 }, + { 200, { FORMAT_C2 }, 4, { 1 }, { 9 }, 1, 8, 1, 1, 6 }, + { 201, { FORMAT_C2 }, 1, { 0 }, { 9 }, 1, 2, 2, 2, 6 }, + { 202, { FORMAT_C2 }, 1, { 0 }, { 9 }, 1, 8, 1, 1, 6 }, + { 203, { FORMAT_C2 }, 1, { 0 }, { 9 }, 1, 2, 1, 2, 6 }, + { 204, { FORMAT_C2 }, 1, { 0 }, { 8, 9 }, 2, 2, 2, 2, 6 }, + { 205, { FORMAT_C2 }, 1, { 0 }, { 4, 9 }, 2, 2, 1, 2, 6 }, + { 206, { FORMAT_C2 }, 1, { 0 }, { 7, 9 }, 2, 8, 1, 1, 6 }, + { 207, { FORMAT_C2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 1, 2, 6 }, + { 208, { FORMAT_C2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 2, 2, 6 }, + { 209, { FORMAT_C2 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 2, 1, 2, 6 }, + { 210, { FORMAT_C2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 8, 1, 1, 6 }, + { 211, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 9 }, 1, 2, 1, 6, 2 }, + { 212, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 4, 9 }, 2, 8, 1, 3, 2 }, + { 213, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 7, 9 }, 2, 8, 1, 3, 2 }, + { 214, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 6, 2 }, + { 215, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 4, 9 }, 2, 2, 2, 6, 2 }, + { 216, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 8, 9 }, 2, 2, 2, 6, 2 }, + { 217, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 2, 2, 6, 2 }, + { 218, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 8, 1, 3, 2 }, + { 219, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 9 }, 1, 2, 1, 6, 2 }, + { 220, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 8, 9 }, 2, 2, 2, 6, 2 }, + { 221, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 4, 9 }, 2, 2, 1, 6, 2 }, + { 222, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 7, 9 }, 2, 8, 1, 3, 2 }, + { 223, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 2, 2, 6, 2 }, + { 224, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 2, 1, 6, 2 }, + { 225, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 8, 1, 3, 2 }, + { 226, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 9 }, 1, 0, 1, 3, 4 }, + { 227, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 4, 9 }, 2, 6, 1, 2, 4 }, + { 228, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 7, 9 }, 2, 6, 1, 2, 4 }, + { 229, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 3, 4 }, + { 230, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 3, 4 }, + { 231, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 9 }, 1, 0, 2, 3, 4 }, + { 232, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 9 }, 1, 6, 1, 2, 4 }, + { 233, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 9 }, 1, 0, 1, 3, 4 }, + { 234, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 3, 4 }, + { 235, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 3, 4 }, + { 236, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 7, 9 }, 2, 6, 1, 2, 4 }, + { 237, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 1, 3, 4 }, + { 238, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 3, 4, 8, 9 }, 4, 0, 2, 3, 4 }, + { 239, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 1, 3, 4 }, + { 240, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 6, 1, 2, 4 }, + { 241, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 9 }, 1, 0, 1, 2, 6 }, + { 242, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 4, 9 }, 2, 2, 1, 2, 6 }, + { 243, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 7, 9 }, 2, 0, 1, 2, 6 }, + { 244, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 7, 9 }, 2, 2, 1, 2, 6 }, + { 245, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 4, 9 }, 2, 0, 2, 2, 6 }, + { 246, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 8, 9 }, 2, 0, 2, 2, 6 }, + { 247, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 9 }, 1, 0, 2, 2, 6 }, + { 248, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 9 }, 1, 2, 1, 2, 6 }, + { 249, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 9 }, 1, 0, 1, 2, 6 }, + { 250, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 8, 9 }, 2, 0, 2, 2, 6 }, + { 251, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 4, 9 }, 2, 0, 1, 2, 6 }, + { 252, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 7, 9 }, 2, 2, 1, 2, 6 }, + { 253, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 3, 4, 8, 9 }, 3, 0, 2, 2, 6 }, + { 254, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 1, 3, 5, 7, 9 }, 5, 0, 1, 2, 6 }, + { 255, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 10, 2, 1, 2, 6 }, +}; + +/* 3GPP 38.211-f20 Table - 6.3.3.2-4 */ +const xRANPrachConfigTableStruct gxranPrachDataTable_mmw[XRAN_PRACH_CONFIG_TABLE_SIZE] = +{ + { 0, { FORMAT_A1 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 6, 2 }, + { 1, { FORMAT_A1 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 6, 2 }, + { 2, { FORMAT_A1 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 6, 2 }, + { 3, { FORMAT_A1 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 6, 2 }, + { 4, { FORMAT_A1 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 6, 2 }, + { 5, { FORMAT_A1 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 6, 2 }, + { 6, { FORMAT_A1 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 6, 2 }, + { 7, { FORMAT_A1 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 6, 2 }, + { 8, { FORMAT_A1 }, 2, { 1 }, { 7, 15, 23, 31, 39 }, 5, 0, 2, 6, 2 }, + { 9, { FORMAT_A1 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 6, 2 }, + { 10, { FORMAT_A1 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 6, 2 }, + { 11, { FORMAT_A1 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 6, 2 }, + { 12, { FORMAT_A1 }, 1, { 0 }, { 19, 39 }, 2, 7, 1, 3, 2 }, + { 13, { FORMAT_A1 }, 1, { 0 }, { 3, 5, 7 }, 2, 0, 1, 6, 2 }, + { 14, { FORMAT_A1 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 7, 1, 3, 2 }, + { 15, { FORMAT_A1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 7, 2, 3, 2 }, + { 16, { FORMAT_A1 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 6, 2 }, + { 17, { FORMAT_A1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 0, 2, 6, 2 }, + { 18, { FORMAT_A1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 6, 2 }, + { 19, { FORMAT_A1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 7, 1, 3, 2 }, + { 20, { FORMAT_A1 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 7, 1, 3, 2 }, + { 21, { FORMAT_A1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 7, 1, 3, 2 }, + { 22, { FORMAT_A1 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 1, 6, 2 }, + { 23, { FORMAT_A1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 6, 2 }, + { 24, { FORMAT_A1 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 7, 2, 3, 2 }, + { 25, { FORMAT_A1 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 7, 1, 3, 2 }, + { 26, { FORMAT_A1 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 6, 2 }, + { 27, { FORMAT_A1 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 6, 2 }, + { 28, { FORMAT_A1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 7, 1, 3, 2 }, + { 29, { FORMAT_A2 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 3, 4 }, + { 30, { FORMAT_A2 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 3, 4 }, + { 31, { FORMAT_A2 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 10, 0, 2, 3, 4 }, + { 32, { FORMAT_A2 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 3, 4 }, + { 33, { FORMAT_A2 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 3, 4 }, + { 34, { FORMAT_A2 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 3, 4 }, + { 35, { FORMAT_A2 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 3, 4 }, + { 36, { FORMAT_A2 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 3, 4 }, + { 37, { FORMAT_A2 }, 2, { 1 }, { 7, 15, 23, 31, 39 }, 5, 0, 2, 3, 4 }, + { 38, { FORMAT_A2 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 3, 4 }, + { 39, { FORMAT_A2 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 3, 4 }, + { 40, { FORMAT_A2 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 3, 4 }, + { 41, { FORMAT_A2 }, 1, { 0 }, { 19, 39 }, 2, 5, 1, 2, 4 }, + { 42, { FORMAT_A2 }, 1, { 0 }, { 3, 5, 7 }, 3, 0, 1, 3, 4 }, + { 43, { FORMAT_A2 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 5, 1, 2, 4 }, + { 44, { FORMAT_A2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 5, 2, 2, 4 }, + { 45, { FORMAT_A2 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 3, 4 }, + { 46, { FORMAT_A2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 0, 2, 3, 4 }, + { 47, { FORMAT_A2 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 1, 3, 4 }, + { 48, { FORMAT_A2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 5, 1, 2, 4 }, + { 49, { FORMAT_A2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 3, 4 }, + { 50, { FORMAT_A2 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 5, 1, 2, 4 }, + { 51, { FORMAT_A2 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 0, 1, 3, 4 }, + { 52, { FORMAT_A2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 5, 1, 2, 4 }, + { 53, { FORMAT_A2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 3, 4 }, + { 54, { FORMAT_A2 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 5, 2, 2, 4 }, + { 55, { FORMAT_A2 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 5, 1, 2, 4 }, + { 56, { FORMAT_A2 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 3, 4 }, + { 57, { FORMAT_A2 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 3, 4 }, + { 58, { FORMAT_A2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 5, 1, 2, 4 }, + { 59, { FORMAT_A3 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 60, { FORMAT_A3 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 61, { FORMAT_A3 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 62, { FORMAT_A3 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 63, { FORMAT_A3 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 2, 6 }, + { 64, { FORMAT_A3 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 2, 6 }, + { 65, { FORMAT_A3 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 66, { FORMAT_A3 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 67, { FORMAT_A3 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 2, 6 }, + { 68, { FORMAT_A3 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 69, { FORMAT_A3 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 70, { FORMAT_A3 }, 1, { 0 }, { 19, 39 }, 2, 7, 1, 1, 6 }, + { 71, { FORMAT_A3 }, 1, { 0 }, { 3, 5, 7 }, 3, 0, 1, 2, 6 }, + { 72, { FORMAT_A3 }, 1, { 0 }, { 9, 11, 13 }, 3, 2, 1, 2, 6 }, + { 73, { FORMAT_A3 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 7, 1, 1, 6 }, + { 74, { FORMAT_A3 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 7, 2, 1, 6 }, + { 75, { FORMAT_A3 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 2, 6 }, + { 76, { FORMAT_A3 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 0, 2, 2, 6 }, + { 77, { FORMAT_A3 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 1, 2, 6 }, + { 78, { FORMAT_A3 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 7, 1, 1, 6 }, + { 79, { FORMAT_A3 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 2, 6 }, + { 80, { FORMAT_A3 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 0, 1, 2, 6 }, + { 81, { FORMAT_A3 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 7, 1, 1, 6 }, + { 82, { FORMAT_A3 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 2, 6 }, + { 83, { FORMAT_A3 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 7, 1, 1, 6 }, + { 84, { FORMAT_A3 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 7, 2, 1, 6 }, + { 85, { FORMAT_A3 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 7, 1, 1, 6 }, + { 86, { FORMAT_A3 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 87, { FORMAT_A3 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 2, 6 }, + { 88, { FORMAT_A3 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 7, 1, 1, 6 }, + { 89, { FORMAT_B1 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 6, 2 }, + { 90, { FORMAT_B1 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 6, 2 }, + { 91, { FORMAT_B1 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 2, 2, 6, 2 }, + { 92, { FORMAT_B1 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 6, 2 }, + { 93, { FORMAT_B1 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 6, 2 }, + { 94, { FORMAT_B1 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 95, { FORMAT_B1 }, 1, { 0 }, { 19, 39 }, 2, 8, 1, 3, 2 }, + { 96, { FORMAT_B1 }, 1, { 0 }, { 3, 5, 7 }, 3, 2, 1, 6, 2 }, + { 97, { FORMAT_B1 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 8, 1, 3, 2 }, + { 98, { FORMAT_B1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 8, 2, 3, 2 }, + { 99, { FORMAT_B1 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 2, 1, 6, 2 }, + { 100, { FORMAT_B1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 6, 2 }, + { 101, { FORMAT_B1 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 2, 1, 6, 2 }, + { 102, { FORMAT_B1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 8, 1, 3, 2 }, + { 103, { FORMAT_B1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 1, 6, 2 }, + { 104, { FORMAT_B1 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 8, 1, 3, 2 }, + { 105, { FORMAT_B1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 8, 1, 3, 2 }, + { 106, { FORMAT_B1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 107, { FORMAT_B1 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 8, 1, 3, 2 }, + { 108, { FORMAT_B1 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 8, 2, 3, 2 }, + { 109, { FORMAT_B1 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 110, { FORMAT_B1 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 2, 1, 6, 2 }, + { 111, { FORMAT_B1 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 8, 1, 3, 2 }, + { 112, { FORMAT_B4 }, 16, { 1, 2 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 1, 12 }, + { 113, { FORMAT_B4 }, 16, { 1, 2 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 1, 12 }, + { 114, { FORMAT_B4 }, 8, { 1, 2 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 1, 12 }, + { 115, { FORMAT_B4 }, 8, { 1, 2 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 1, 12 }, + { 116, { FORMAT_B4 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 1, 12 }, + { 117, { FORMAT_B4 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 1, 12 }, + { 118, { FORMAT_B4 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 1, 12 }, + { 119, { FORMAT_B4 }, 4, { 1, 2 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 1, 12 }, + { 120, { FORMAT_B4 }, 2, { 1 }, { 7, 15, 23, 31, 39 }, 5, 2, 2, 1, 12 }, + { 121, { FORMAT_B4 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 1, 12 }, + { 122, { FORMAT_B4 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 1, 12 }, + { 123, { FORMAT_B4 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 1, 12 }, + { 124, { FORMAT_B4 }, 1, { 0 }, { 19, 39 }, 2, 2, 2, 1, 12 }, + { 125, { FORMAT_B4 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 1, 12 }, + { 126, { FORMAT_B4 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 2, 1, 1, 12 }, + { 127, { FORMAT_B4 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 1, 12 }, + { 128, { FORMAT_B4 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 0, 2, 1, 12 }, + { 129, { FORMAT_B4 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 1, 1, 12 }, + { 130, { FORMAT_B4 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 2, 1, 12 }, + { 131, { FORMAT_B4 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 1, 12 }, + { 132, { FORMAT_B4 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 2, 1, 12 }, + { 133, { FORMAT_B4 }, 1, { 0 }, { 9, 11, 13, 15, 17, 19 }, 6, 0, 1, 1, 12 }, + { 134, { FORMAT_B4 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 2, 1, 1, 12 }, + { 135, { FORMAT_B4 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 1, 12 }, + { 136, { FORMAT_B4 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 1, 12 }, + { 137, { FORMAT_B4 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 2, 2, 1, 12 }, + { 138, { FORMAT_B4 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 1, 12 }, + { 139, { FORMAT_B4 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 1, 12 }, + { 140, { FORMAT_B4 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25 }, 12, 2, 1, 1, 12 }, + { 141, { FORMAT_B4 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25 }, 12, 0, 2, 1, 12 }, + { 142, { FORMAT_B4 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 1, 12 }, + { 143, { FORMAT_B4 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 2, 1, 1, 12 }, + { 144, { FORMAT_C0 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 7, 2 }, + { 145, { FORMAT_C0 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 7, 2 }, + { 146, { FORMAT_C0 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 7, 2 }, + { 147, { FORMAT_C0 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 7, 2 }, + { 148, { FORMAT_C0 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 7, 2 }, + { 149, { FORMAT_C0 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 7, 2 }, + { 150, { FORMAT_C0 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 7, 2 }, + { 151, { FORMAT_C0 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 7, 2 }, + { 152, { FORMAT_C0 }, 2, { 1 }, { 7, 15, 23, 31, 39 }, 5, 0, 2, 7, 2 }, + { 153, { FORMAT_C0 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 7, 2 }, + { 154, { FORMAT_C0 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 7, 2 }, + { 155, { FORMAT_C0 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 7, 2 }, + { 156, { FORMAT_C0 }, 1, { 0 }, { 19, 39 }, 2, 8, 1, 3, 2 }, + { 157, { FORMAT_C0 }, 1, { 0 }, { 3, 5, 7 }, 3, 0, 1, 7, 2 }, + { 158, { FORMAT_C0 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 8, 1, 3, 2 }, + { 159, { FORMAT_C0 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 8, 2, 3, 2 }, + { 160, { FORMAT_C0 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 7, 2 }, + { 161, { FORMAT_C0 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 0, 2, 7, 2 }, + { 162, { FORMAT_C0 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 8, 1, 3, 2 }, + { 163, { FORMAT_C0 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 0, 1, 7, 2 }, + { 164, { FORMAT_C0 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 7, 2 }, + { 165, { FORMAT_C0 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 8, 1, 3, 2 }, + { 166, { FORMAT_C0 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 8, 1, 3, 2 }, + { 167, { FORMAT_C0 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 7, 2 }, + { 168, { FORMAT_C0 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 8, 2, 3, 2 }, + { 169, { FORMAT_C0 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 8, 1, 3, 2 }, + { 170, { FORMAT_C0 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 7, 2 }, + { 171, { FORMAT_C0 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 7, 2 }, + { 172, { FORMAT_C0 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39 }, 40, 8, 1, 3, 2 }, + { 173, { FORMAT_C2 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 174, { FORMAT_C2 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 175, { FORMAT_C2 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 176, { FORMAT_C2 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 177, { FORMAT_C2 }, 8, { 1, 2 }, { 9, 19, 29, 39 }, 4, 0, 2, 2, 6 }, + { 178, { FORMAT_C2 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 2, 6 }, + { 179, { FORMAT_C2 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 180, { FORMAT_C2 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 181, { FORMAT_C2 }, 2, { 1 }, { 7, 15, 23, 31, 39 }, 5, 2, 2, 2, 6 }, + { 182, { FORMAT_C2 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 1, 2, 6 }, + { 183, { FORMAT_C2 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 0, 2, 2, 6 }, + { 184, { FORMAT_C2 }, 2, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 185, { FORMAT_C2 }, 1, { 0 }, { 19, 39 }, 2, 2, 1, 2, 6 }, + { 186, { FORMAT_C2 }, 1, { 0 }, { 3, 5, 7 }, 3, 0, 1, 2, 6 }, + { 187, { FORMAT_C2 }, 1, { 0 }, { 24, 29, 34, 39 }, 4, 7, 1, 1, 6 }, + { 188, { FORMAT_C2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 7, 2, 1, 6 }, + { 189, { FORMAT_C2 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 0, 1, 2, 6 }, + { 190, { FORMAT_C2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 2, 6 }, + { 191, { FORMAT_C2 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 2, 1, 2, 6 }, + { 192, { FORMAT_C2 }, 1, { 0 }, { 3, 5, 7, 9, 11, 13 }, 6, 7, 1, 1, 6 }, + { 193, { FORMAT_C2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 7, 2, 1, 6 }, + { 194, { FORMAT_C2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 0, 1, 2, 6 }, + { 195, { FORMAT_C2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 7, 2, 1, 6 }, + { 196, { FORMAT_C2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 197, { FORMAT_C2 }, 1, { 0 }, { 13, 14, 15, 29, 30, 31, 37, 38, 39 }, 10, 7, 2, 1, 6 }, + { 198, { FORMAT_C2 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 7, 1, 1, 6 }, + { 199, { FORMAT_C2 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 0, 1, 2, 6 }, + { 200, { FORMAT_C2 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 0, 1, 2, 6 }, + { 201, { FORMAT_C2 }, 1, { 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39 }, 40, 7, 1, 1, 6 }, + { 202, { FORMAT_A1, FORMAT_B1 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 203, { FORMAT_A1, FORMAT_B1 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 204, { FORMAT_A1, FORMAT_B1 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 205, { FORMAT_A1, FORMAT_B1 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 206, { FORMAT_A1, FORMAT_B1 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 207, { FORMAT_A1, FORMAT_B1 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 208, { FORMAT_A1, FORMAT_B1 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 209, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 19, 39 }, 2, 8, 1, 3, 2 }, + { 210, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 8, 1, 3, 2 }, + { 211, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 2, 1, 6, 2 }, + { 212, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 6, 2 }, + { 213, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 8, 1, 3, 2 }, + { 214, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 2, 1, 6, 2 }, + { 215, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 1, 6, 2 }, + { 216, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 8, 1, 3, 2 }, + { 217, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 6, 2 }, + { 218, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 6, 2 }, + { 219, { FORMAT_A1, FORMAT_B1 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 2, 1, 6, 2 }, + { 220, { FORMAT_A2, FORMAT_B2 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 3, 4 }, + { 221, { FORMAT_A2, FORMAT_B2 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 3, 4 }, + { 222, { FORMAT_A2, FORMAT_B2 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 3, 4 }, + { 223, { FORMAT_A2, FORMAT_B2 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 3, 4 }, + { 224, { FORMAT_A2, FORMAT_B2 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 3, 4 }, + { 225, { FORMAT_A2, FORMAT_B2 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 3, 4 }, + { 226, { FORMAT_A2, FORMAT_B2 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 3, 4 }, + { 227, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 19, 39 }, 2, 6, 1, 2, 4 }, + { 228, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 6, 1, 2, 4 }, + { 229, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 2, 1, 3, 4 }, + { 230, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 3, 4 }, + { 231, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 6, 1, 2, 4 }, + { 232, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 2, 1, 3, 4 }, + { 233, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 1, 3, 4 }, + { 234, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 6, 1, 2, 4 }, + { 235, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 3, 4 }, + { 236, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 3, 4 }, + { 237, { FORMAT_A2, FORMAT_B2 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 2, 1, 3, 4 }, + { 238, { FORMAT_A3, FORMAT_B3 }, 16, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 239, { FORMAT_A3, FORMAT_B3 }, 16, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 2, 6 }, + { 240, { FORMAT_A3, FORMAT_B3 }, 8, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 241, { FORMAT_A3, FORMAT_B3 }, 8, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 2, 6 }, + { 242, { FORMAT_A3, FORMAT_B3 }, 4, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 243, { FORMAT_A3, FORMAT_B3 }, 4, { 1 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 1, 2, 6 }, + { 244, { FORMAT_A3, FORMAT_B3 }, 2, { 1 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 245, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 19, 39 }, 2, 2, 1, 2, 6 }, + { 246, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 1, 2, 6 }, + { 247, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 17, 19, 37, 39 }, 4, 2, 1, 2, 6 }, + { 248, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 9, 19, 29, 39 }, 4, 2, 2, 2, 6 }, + { 249, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 1, 2, 6 }, + { 250, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 23, 27, 31, 35, 39 }, 5, 2, 1, 2, 6 }, + { 251, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 2, 2, 6 }, + { 252, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 4, 9, 14, 19, 24, 29, 34, 39 }, 8, 2, 1, 2, 6 }, + { 253, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 3, 7, 11, 15, 19, 23, 27, 31, 35, 39 }, 10, 2, 2, 2, 6 }, + { 254, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, + 23, 25, 27, 29, 31, 33, 35, 37, 39 }, 15, 2, 1, 2, 6 }, + { 255, { FORMAT_A3, FORMAT_B3 }, 1, { 0 }, { 7, 15, 23, 31, 39 }, 5, 2, 1, 2, 6 }, +}; + +const xRANPrachPreambleLRAStruct gxranPreambleforLRA[XRAN_PRACH_PREAMBLE_FORMAT_OF_ABC] = +{ + {FORMAT_A1, 139, 15, 2 , 288 }, + {FORMAT_A2, 139, 15, 4 , 576 }, + {FORMAT_A3, 139, 15, 6 , 864 }, + {FORMAT_B1, 139, 15, 2 , 216 }, + {FORMAT_B2, 139, 15, 4 , 360 }, + {FORMAT_B3, 139, 15, 6 , 504 }, + {FORMAT_B4, 139, 15, 12, 936 }, + {FORMAT_C0, 139, 15, 1 , 1240}, + {FORMAT_C2, 139, 15, 4 , 2048} +}; + diff --git a/fhi_lib/lib/src/xran_up_api.c b/fhi_lib/lib/src/xran_up_api.c new file mode 100644 index 0000000..a8c71f2 --- /dev/null +++ b/fhi_lib/lib/src/xran_up_api.c @@ -0,0 +1,481 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @brief This file provides the implementation of User Plane Messages APIs. + * + * @file xran_up_api.c + * @ingroup group_lte_source_xran + * @author Intel Corporation + * + **/ + +#include +#include +#include "xran_fh_lls_cu.h" +#include "xran_transport.h" +#include "xran_up_api.h" +#ifndef MLOG_ENABLED +#include "mlog_lnx_xRAN.h" +#else +#include "mlog_lnx.h" +#endif + +extern uint32_t xran_lib_ota_tti; + + +/** + * @brief Builds eCPRI header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param iq_data_num_bytes Number of bytes in IQ data buffer + * @param iq_data_offset Number of elements already sent + * @return int int 0 on success, non zero on failure + */ +static int build_ecpri_hdr(struct rte_mbuf *mbuf, + const uint32_t iq_data_num_bytes, + const uint32_t iq_data_offset, + uint8_t alignment) +{ + struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *) + rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr)); + + uint16_t iq_samples_bytes_in_mbuf = rte_pktmbuf_tailroom(mbuf) - + sizeof(struct radio_app_common_hdr) - sizeof(struct data_section_hdr); + + iq_samples_bytes_in_mbuf -= (iq_samples_bytes_in_mbuf % alignment); + + if (NULL == ecpri_hdr) + return 1; + + ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER; + ecpri_hdr->ecpri_resv = 0; + ecpri_hdr->ecpri_concat = 0; + ecpri_hdr->ecpri_mesg_type = ECPRI_IQ_DATA; + + if (iq_data_offset + iq_samples_bytes_in_mbuf > iq_data_num_bytes) { + ecpri_hdr->ecpri_payl_size = + rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) + + sizeof(struct data_section_hdr) + + (iq_data_num_bytes - iq_data_offset)); + ecpri_hdr->ecpri_seq_id.e_bit = 1; /* last segment */ + } else { + ecpri_hdr->ecpri_payl_size = + rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) + + sizeof(struct data_section_hdr) + + iq_samples_bytes_in_mbuf); + ecpri_hdr->ecpri_seq_id.e_bit = 0; + } + +// ecpri_hdr->ecpri_xtc_id = 0; /* currently not used */ + ecpri_hdr->ecpri_seq_id.seq_id = 0; + ecpri_hdr->ecpri_seq_id.sub_seq_id = iq_data_offset / + iq_samples_bytes_in_mbuf; + + return 0; +} + +/** + * @brief Builds eCPRI header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param ecpri_mesg_type eCPRI message type + * @param payl_size the size in bytes of the payload part of eCPRI message + * @param CC_ID Component Carrier ID for ecpriRtcid/ecpriPcid + * @param Ant_ID Antenna ID for ecpriRtcid/ecpriPcid + * @param seq_id Message identifier for eCPRI message + * @return int int 0 on success, non zero on failure + */ +static int xran_build_ecpri_hdr_ex(struct rte_mbuf *mbuf, + uint8_t ecpri_mesg_type, + int payl_size, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t seq_id) +{ + struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *) + rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr)); + + if (NULL == ecpri_hdr) + return 1; + + ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER; + ecpri_hdr->ecpri_resv = 0; // should be zero + ecpri_hdr->ecpri_concat = 0; + ecpri_hdr->ecpri_mesg_type = ecpri_mesg_type; + ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(payl_size + + sizeof(struct data_section_hdr)+sizeof(struct radio_app_common_hdr)); + + /* one to one lls-CU to RU only and band sector is the same */ + ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID); + + ecpri_hdr->ecpri_seq_id.seq_id = seq_id; + + /* no transport layer fragmentation supported */ + ecpri_hdr->ecpri_seq_id.sub_seq_id = 0; + ecpri_hdr->ecpri_seq_id.e_bit = 1; + + return 0; +} + + +/** + * @brief Builds application layer of xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param app_hdr_input Radio App common header structure to be set in mbuf + * packet. + * @return int 0 on success, non zero on failure + */ +static int build_application_layer( + struct rte_mbuf *mbuf, + const struct radio_app_common_hdr *app_hdr_input) +{ + struct radio_app_common_hdr *app_hdr = (struct radio_app_common_hdr *) + rte_pktmbuf_append(mbuf, sizeof(struct radio_app_common_hdr)); + + if (NULL == app_hdr) + return 1; + + rte_memcpy(app_hdr, app_hdr_input, sizeof(struct radio_app_common_hdr)); + + return 0; +} + +/** + * @brief Builds section header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param sec_hdr Section header structure to be set in mbuf packet + * @return int 0 on success, non zero on failure + */ +static int build_section_hdr( + struct rte_mbuf *mbuf, + const struct data_section_hdr *sec_hdr) +{ + struct data_section_hdr *section_hdr = (struct data_section_hdr *) + rte_pktmbuf_append(mbuf, sizeof(struct data_section_hdr)); + + if (NULL == section_hdr) + return 1; + + rte_memcpy(section_hdr, sec_hdr, sizeof(struct data_section_hdr)); + + return 0; +} +/** + * @brief Function for appending IQ samples data to the mbuf. + * + * @param mbuf Initialized rte_mbuf packet. + * @param iq_data_start Address of the first element in IQ data array. + * @param iq_data_num_bytes Size of the IQ data array. + * @param iq_data_offset IQ data btyes already sent. + * @return uint16_t Bytes that have been appended to the packet. + */ +static uint16_t append_iq_samples_ex( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes) +{ + uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf); + + if(free_space_in_pkt >= iq_data_num_bytes){ + + void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_data_num_bytes); + if (iq_sam_buf == NULL) + return 0; +#ifdef XRAN_BYTE_ORDER_SWAP + int idx = 0; + uint16_t *restrict psrc = (uint16_t *)iq_data_start; + uint16_t *restrict pdst = (uint16_t *)iq_sam_buf; + /* CPU byte order (le) of IQ to network byte order (be) */ + for (idx = 0; idx < iq_data_num_bytes/sizeof(int16_t); idx++){ + pdst[idx] = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_cpu_to_be_16(psrc[idx]); + } +#else +#error xran spec is network byte order + /* for debug */ + rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start, iq_data_num_bytes); + +#endif + + return iq_data_num_bytes; + } + + return 0; +} + + +/** + * @brief Function for appending IQ samples data to the mbuf. + * + * @param mbuf Initialized rte_mbuf packet. + * @param iq_data_start Address of the first element in IQ data array. + * @param iq_data_num_bytes Size of the IQ data array. + * @param iq_data_offset IQ data btyes already sent. + * @return uint16_t Bytes that have been appended to the packet. + */ +static uint16_t append_iq_samples( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes, + const uint32_t iq_data_offset, + const uint8_t alignment) +{ + uint16_t iq_bytes_to_send = 0; + uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf); + + if (free_space_in_pkt > iq_data_num_bytes - iq_data_offset) + iq_bytes_to_send = iq_data_num_bytes - iq_data_offset; + else + iq_bytes_to_send = free_space_in_pkt; + + /* don't cut off an iq in half */ + iq_bytes_to_send -= iq_bytes_to_send % alignment; + + void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_bytes_to_send); + + rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start + iq_data_offset, + iq_bytes_to_send); + + return iq_bytes_to_send; +} + +/** + * @brief Builds compression header in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param compression_hdr Section compression header structure + * to be set in mbuf packet + * @return int 0 on success, non zero on failure + */ +static int build_compression_hdr( + struct rte_mbuf *mbuf, + const struct data_section_compression_hdr *compr_hdr) +{ + struct data_section_compression_hdr *compression_hdr = + (struct data_section_compression_hdr *) + rte_pktmbuf_append(mbuf, sizeof(*compression_hdr)); + + if (NULL == compression_hdr) + return 1; + + rte_memcpy(compression_hdr, compr_hdr, sizeof(*compression_hdr)); + + return 0; +} + +/** + * @brief Appends compression parameter in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet + * @param ud_comp_paramr Compression param to be set in mbuf packet + * @return int 0 on success, non zero on failure + */ +static int append_comp_param(struct rte_mbuf *mbuf, union compression_params *ud_comp_param) +{ + union compression_params *compr_param = + (union compression_params *)rte_pktmbuf_append(mbuf, sizeof(union compression_params)); + + if (NULL == compr_param) + return 1; + + rte_memcpy(compr_param, ud_comp_param, sizeof(union compression_params)); + + return 0; +} + +/** + * @brief Function for starting preparion of IQ samples portions + * to be sent in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet. + * @param iq_data_start Address of the first element in IQ data array. + * @param iq_data_num_bytes Size of the IQ data array. + * @param iq_data_offset IQ data bytes already sent. + * @param alignment Size of IQ data alignment. + * @param pkt_gen_params Struct with parameters used for building packet + * @return int Number of bytes that have been appended + to the packet within a single data section appended. + */ +int xran_prepare_iq_symbol_portion( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes, + uint32_t *iq_data_offset, + uint8_t alignment, + struct xran_up_pkt_gen_params *params, + int sub_seq_id) +{ + uint8_t i = 0; + uint16_t iq_sam_bytes_sent = 0; + + if (build_ecpri_hdr(mbuf, iq_data_num_bytes, *iq_data_offset, alignment)) + return 0; + + if (build_application_layer(mbuf, &(params->app_params)) != 0) + return 0; + + if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0) + return 0; + + if(params->compr_hdr_param.ud_comp_hdr.ud_comp_meth != XRAN_COMPMETHOD_NONE) { + if (build_compression_hdr(mbuf, &(params->compr_hdr_param)) !=0) + return 0; + + if(append_comp_param(mbuf, &(params->compr_param)) !=0) + return 0; + } + + return append_iq_samples(mbuf, iq_data_start, iq_data_num_bytes, + (*iq_data_offset), alignment); +} + +/** + * @brief Function for extracting all IQ samples from xRAN packet + * holding a single data section + * @param iq_data_start Address of the first element in IQ data array. + * @param symb_id Symbol ID to be extracted from ecpri header + * @param seq_id Sequence ID to be extracted from radio header + * @return int Size of remaining mbuf filled with IQ samples + zero on failure + */ +int xran_extract_iq_samples(struct rte_mbuf *mbuf, + void **iq_data_start, + uint8_t *CC_ID, + uint8_t *Ant_ID, + uint8_t *frame_id, + uint8_t *subframe_id, + uint8_t *slot_id, + uint8_t *symb_id, + struct ecpri_seq_id *seq_id) +{ + uint32_t mlogVar[10]; + uint32_t mlogVarCnt = 0; + struct xran_eaxc_info result; + + if (NULL == mbuf) + return 0; + if (NULL == iq_data_start) + return 0; + + /* Process eCPRI header. */ + const struct xran_ecpri_hdr *ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *); + if (ecpri_hdr == NULL) + return 0; + + if (seq_id) + *seq_id = ecpri_hdr->ecpri_seq_id; + + xran_decompose_cid((uint16_t)ecpri_hdr->ecpri_xtc_id, &result); + + *CC_ID = result.ccId; + *Ant_ID = result.ruPortId; + + /* Process radio header. */ + struct radio_app_common_hdr *radio_hdr = + (void *)rte_pktmbuf_adj(mbuf, sizeof(*ecpri_hdr)); + if (radio_hdr == NULL) + return 0; /* packet too short */ + + radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value); + + if (frame_id) + *frame_id = radio_hdr->frame_id; + + if (subframe_id) + *subframe_id = radio_hdr->sf_slot_sym.subframe_id; + + if (slot_id) + *slot_id = radio_hdr->sf_slot_sym.slot_id; + + if (symb_id) + *symb_id = radio_hdr->sf_slot_sym.symb_id; + + /* Process data section hdr */ + const struct data_section_hdr *data_hdr = + (void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr)); + if (data_hdr == NULL) + return 0; /* packet too short */ + +#ifdef COMPRESSION + const struct data_section_compression_hdr *data_compr_hdr = + (void *) rte_pktmbuf_adj(mbuf, sizeof(*data_hdr)); + + const uint8_t *compr_param = + (void *)rte_pktmbuf_adj(mbuf, sizeof(*data_compr_hdr)); + + *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*compr_param)); + +#else + *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*data_hdr)); +#endif + if (*iq_data_start == NULL) + return 0; + + mlogVar[mlogVarCnt++] = 0xBBBBBBB; + mlogVar[mlogVarCnt++] = xran_lib_ota_tti; + mlogVar[mlogVarCnt++] = radio_hdr->frame_id; + mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.subframe_id; + mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.slot_id; + mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.symb_id; + mlogVar[mlogVarCnt++] = rte_pktmbuf_pkt_len(mbuf); + MLogAddVariables(mlogVarCnt, mlogVar, MLogTick()); + + return rte_pktmbuf_pkt_len(mbuf); +} + +/** + * @brief Function for starting preparion of IQ samples portions + * to be sent in xRAN packet + * + * @param mbuf Initialized rte_mbuf packet. + * @param iq_data_start Address of the first element in IQ data array. + * @param iq_data_num_bytes Size of the IQ data array. + * @param iq_data_offset IQ data bytes already sent. + * @param alignment Size of IQ data alignment. + * @param pkt_gen_params Struct with parameters used for building packet + * @return int Number of bytes that have been appended + to the packet within all appended sections. + */ +int xran_prepare_iq_symbol_portion_no_comp( + struct rte_mbuf *mbuf, + const void *iq_data_start, + const uint32_t iq_data_num_bytes, + struct xran_up_pkt_gen_no_compression_params *params, + uint8_t CC_ID, + uint8_t Ant_ID, + uint8_t seq_id) +{ + if(xran_build_ecpri_hdr_ex(mbuf, + ECPRI_IQ_DATA, + iq_data_num_bytes, + CC_ID, + Ant_ID, + seq_id)) + return 0; + + if (build_application_layer(mbuf, &(params->app_params)) != 0) + return 0; + + if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0) + return 0; + + return append_iq_samples_ex(mbuf, iq_data_start, iq_data_num_bytes); +} + diff --git a/fhi_lib/readme.txt b/fhi_lib/readme.txt new file mode 100644 index 0000000..5394371 --- /dev/null +++ b/fhi_lib/readme.txt @@ -0,0 +1,163 @@ +#/****************************************************************************** +#* +#* Copyright (c) 2019 Intel. +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#* +#*******************************************************************************/ +1. Introduction +xRAN Lib performs communication between the low-layer split central unit (lls-CU) and RU, it is highly-optimized software implementation based on Intel Architecture to provide the standard interface implementation based on O-RAN front haul interface specification. + +2. Supported features +please refer PRD in the table <>, only ICC compiler was supported for this version. + +3. Fixed Issues +It's first version of seed code for feature development, future fixed issues will be tracked here. + +4. Known Issues +From current unit testing coverage, no Know issues was founded yet. + +5. Prerequisites for install + +5.1 Intel Compiler version +icc -v +icc version 18.0.1 (gcc version 4.8.5 compatibility) + +5.2 DPDK version +dpdk_18.08 + +5.3 compile DPDK with command +[dpdk]# ./usertools/dpdk-setup.sh + +select [16] x86_64-native-linuxapp-icc +select [18] Insert IGB UIO module +exit [35] Exit Script + +5.4 Find PCIe device of Fortville port + +lspci |grep Eth +19:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) +19:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) +41:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T (rev 04) +41:00.1 Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T (rev 04) +d8:00.0 << Ethernet controller: Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+ (rev 02) <<<< this one +d8:00.1 Ethernet controller: Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+ (rev 02) + +5.5 Corresponding Eth device via + +ifconfig -a + +find port Eth with correct PCIe Bus address as per list above + +ethtool -i enp216s0f0 +driver: i40e +version: 2.4.10 << i40e driver +firmware-version: 6.01 0x800034a4 1.1747.0 +expansion-rom-version: +bus-info: 0000:d8:00.0 <<< this one +supports-statistics: yes +supports-test: yes +supports-eeprom-access: yes +supports-register-dump: yes +supports-priv-flags: yes + +5.6 install correct 2.4.10 i40e version if different (https://downloadcenter.intel.com/download/28306/Intel-Network-Adapter-Driver-for-PCIe-40-Gigabit-Ethernet-Network-Connections-Under-Linux-) + +make sure firmare version is + +firmware-version: 6.01 + +5.7 make sure that linux boot arguments are correct + +cat /proc/cmdline +BOOT_IMAGE=/vmlinuz-3.10.0-rt56 root=/dev/mapper/centos_5gnr--skx--sp-root ro crashkernel=auto rd.lvm.lv=centos_5gnr-skx-sp/root rd.lvm.lv=centos_5gnr-skx-sp/swap intel_iommu=off usbcore.autosuspend=-1 selinux=0 enforcing=0 nmi_watchdog=0 softlockup_panic=0 audit=0 intel_pstate=disable cgroup_disable=memory mce=off idle=poll hugepagesz=1G hugepages=20 hugepagesz=2M hugepages=0 default_hugepagesz=1G isolcpus=1-35 rcu_nocbs=1-35 kthread_cpus=0 irqaffinity=0 nohz_full=1-35 + +5.8 enable SRIOV VF port for XRAN + +echo 2 > /sys/class/net/enp216s0f0/device/sriov_numvfs + +see https://doc.dpdk.org/guides/nics/intel_vf.html + +5.9 Check Virtual Function was created + +lspci |grep Eth +19:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) +19:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01) +41:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T (rev 04) +41:00.1 Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T (rev 04) +d8:00.0 Ethernet controller: Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+ (rev 02) +d8:00.1 Ethernet controller: Intel Corporation Ethernet Controller XL710 for 40GbE QSFP+ (rev 02) +d8:02.0 Ethernet controller: Intel Corporation XL710/X710 Virtual Function (rev 02) <<<< this is XRAN port (u-plane) +d8:02.1 Ethernet controller: Intel Corporation XL710/X710 Virtual Function (rev 02) <<<< this is XRAN port (c-plane) + +5.10 Configure VFs +- set mac to 00:11:22:33:44:66 +- set Vlan tag to 2 (U-plane) for VF0 +- set Vlan tag to 1 (C-plane) for VF1 + +[root@5gnr-sc12-xran app]# ip link set enp216s0f0 vf 0 mac 00:11:22:33:44:66 vlan 2 +[root@5gnr-sc12-xran app]# ip link set enp216s0f0 vf 1 mac 00:11:22:33:44:66 vlan 1 +[root@5gnr-sc12-xran app]# ip link show +1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 +2: enp65s0f0: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether a4:bf:01:3e:6b:79 brd ff:ff:ff:ff:ff:ff +3: eno2: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether a4:bf:01:3e:6b:7a brd ff:ff:ff:ff:ff:ff +4: enp25s0f0: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether 90:e2:ba:d3:b2:ec brd ff:ff:ff:ff:ff:ff +5: enp129s0f0: mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000 + link/ether 3c:fd:fe:a8:e0:70 brd ff:ff:ff:ff:ff:ff +6: enp129s0f1: mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000 + link/ether 3c:fd:fe:a8:e0:71 brd ff:ff:ff:ff:ff:ff +7: enp216s0f0: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether 3c:fd:fe:9e:93:68 brd ff:ff:ff:ff:ff:ff + vf 0 MAC 00:11:22:33:44:66, vlan 2, spoof checking on, link-state auto, trust off + vf 1 MAC 00:11:22:33:44:66, vlan 1, spoof checking on, link-state auto, trust off +8: enp25s0f1: mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000 + link/ether 90:e2:ba:d3:b2:ed brd ff:ff:ff:ff:ff:ff +9: enp216s0f1: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether 3c:fd:fe:9e:93:69 brd ff:ff:ff:ff:ff:ff +12: enp216s2: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether 96:fa:4d:04:4d:87 brd ff:ff:ff:ff:ff:ff +13: enp216s2f1: mtu 1500 qdisc mq state UP mode DEFAULT qlen 1000 + link/ether a6:67:49:bb:bd:5e brd ff:ff:ff:ff:ff:ff + +6. Install xRAN Lib + +6.1 start matlab and run gen_test.m +copy ant_*.bin to /xran/app + +6.2 build xran sample application +export XRAN_DIR=xRAN folder +export RTE_SDK=dpdk folder +[xRAN root folder]$ ./build.sh + +6.3 update Eth port used for XRAN +in ./app/run_lls-cu.sh +ports have to match VF function from step 1.11 (0000:d8:02.0 - U-plane 0000:d8:02.1 C-plane) + +6.4 Run dpdk.sh to assign port to PMD + +[xran root folder]# ./app/dpdk.sh + +Network devices using DPDK-compatible driver +============================================ +0000:d8:02.0 'XL710/X710 Virtual Function 154c' drv=igb_uio unused=i40evf +0000:d8:02.1 'XL710/X710 Virtual Function 154c' drv=igb_uio unused=i40evf + + +6.5 Run XRAN lls-CU sample app +setup RU mac address in config_file_lls_cu.dat +[xran root folder]# ./app/run_lls-cu.sh +