Front Haul Interface Library first seed code contribution 66/566/1 ORAN-seedcode_v1.1
authorLuis Farias <luis.farias@intel.com>
Thu, 25 Jul 2019 21:51:42 +0000 (14:51 -0700)
committerLuis Farias <luis.farias@intel.com>
Thu, 25 Jul 2019 21:51:42 +0000 (14:51 -0700)
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 <luis.farias@intel.com>
49 files changed:
fhi_lib/Licenses.txt [new file with mode: 0644]
fhi_lib/app/Makefile [new file with mode: 0644]
fhi_lib/app/ant_0.bin [new file with mode: 0644]
fhi_lib/app/ant_1.bin [new file with mode: 0644]
fhi_lib/app/ant_2.bin [new file with mode: 0644]
fhi_lib/app/ant_3.bin [new file with mode: 0644]
fhi_lib/app/common/common.c [new file with mode: 0644]
fhi_lib/app/common/common.h [new file with mode: 0644]
fhi_lib/app/config_file_lls_cu.dat [new file with mode: 0644]
fhi_lib/app/config_file_ru.dat [new file with mode: 0644]
fhi_lib/app/dpdk.sh [new file with mode: 0644]
fhi_lib/app/gen_test.m [new file with mode: 0644]
fhi_lib/app/lls-cu/Makefile [new file with mode: 0644]
fhi_lib/app/lls-cu/sample-lls-cu.c [new file with mode: 0644]
fhi_lib/app/ru/Makefile [new file with mode: 0644]
fhi_lib/app/run_lls-cu.sh [new file with mode: 0644]
fhi_lib/app/run_ru.sh [new file with mode: 0644]
fhi_lib/app/src/config.c [new file with mode: 0644]
fhi_lib/app/src/config.h [new file with mode: 0644]
fhi_lib/app/src/xran_mlog_task_id.h [new file with mode: 0644]
fhi_lib/build.sh [new file with mode: 0644]
fhi_lib/lib/Makefile [new file with mode: 0644]
fhi_lib/lib/api/xran_cp_api.h [new file with mode: 0644]
fhi_lib/lib/api/xran_fh_lls_cu.h [new file with mode: 0644]
fhi_lib/lib/api/xran_pkt.h [new file with mode: 0644]
fhi_lib/lib/api/xran_pkt_cp.h [new file with mode: 0644]
fhi_lib/lib/api/xran_pkt_up.h [new file with mode: 0644]
fhi_lib/lib/api/xran_sync_api.h [new file with mode: 0644]
fhi_lib/lib/api/xran_timer.h [new file with mode: 0644]
fhi_lib/lib/api/xran_transport.h [new file with mode: 0644]
fhi_lib/lib/api/xran_up_api.h [new file with mode: 0644]
fhi_lib/lib/ethernet/ethdi.c [new file with mode: 0644]
fhi_lib/lib/ethernet/ethdi.h [new file with mode: 0644]
fhi_lib/lib/ethernet/ethernet.c [new file with mode: 0644]
fhi_lib/lib/ethernet/ethernet.h [new file with mode: 0644]
fhi_lib/lib/src/mlog_lnx_xRAN.h [new file with mode: 0644]
fhi_lib/lib/src/xran_common.c [new file with mode: 0644]
fhi_lib/lib/src/xran_common.h [new file with mode: 0644]
fhi_lib/lib/src/xran_cp_api.c [new file with mode: 0644]
fhi_lib/lib/src/xran_hash.h [new file with mode: 0644]
fhi_lib/lib/src/xran_lib_mlog_tasks_id.h [new file with mode: 0644]
fhi_lib/lib/src/xran_main.c [new file with mode: 0644]
fhi_lib/lib/src/xran_printf.h [new file with mode: 0644]
fhi_lib/lib/src/xran_sync_api.c [new file with mode: 0644]
fhi_lib/lib/src/xran_timer.c [new file with mode: 0644]
fhi_lib/lib/src/xran_transport.c [new file with mode: 0644]
fhi_lib/lib/src/xran_ul_tables.c [new file with mode: 0644]
fhi_lib/lib/src/xran_up_api.c [new file with mode: 0644]
fhi_lib/readme.txt [new file with mode: 0644]

diff --git a/fhi_lib/Licenses.txt b/fhi_lib/Licenses.txt
new file mode 100644 (file)
index 0000000..6aee987
--- /dev/null
@@ -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 (file)
index 0000000..ebad9b9
--- /dev/null
@@ -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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index 0000000..818914e
--- /dev/null
@@ -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 <assert.h>
+#include <err.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+
+#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 (file)
index 0000000..fb4400d
--- /dev/null
@@ -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 <stdio.h>
+#include <unistd.h>
+
+#include "xran_pkt_up.h"
+
+#include <rte_common.h>
+#include <rte_mbuf.h>
+
+#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 (file)
index 0000000..7a17943
--- /dev/null
@@ -0,0 +1,92 @@
+#######################################################################
+#
+# <COPYRIGHT_TAG>
+#
+#######################################################################
+
+# 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 (file)
index 0000000..d1edf90
--- /dev/null
@@ -0,0 +1,92 @@
+#######################################################################
+#
+# <COPYRIGHT_TAG>
+#
+#######################################################################
+
+# 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 (file)
index 0000000..96bb84f
--- /dev/null
@@ -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 (file)
index 0000000..b93736c
--- /dev/null
@@ -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 (file)
index 0000000..86aa9cc
--- /dev/null
@@ -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 (file)
index 0000000..31ffb4b
--- /dev/null
@@ -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 <unistd.h>
+#include <sys/syscall.h>
+#include <sched.h>
+#include <assert.h>
+#include <err.h>
+#include <libgen.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#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; i<nSectorNum; i++)
+    {
+        eInterfaceType = XRANFTHTX_OUT;
+        status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[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; i<nSectorNum; i++)
+    {
+        eInterfaceType = XRANFTHRX_IN;
+        status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[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; i<nSectorNum; i++)
+    {
+        eInterfaceType = XRANFTHRACH_IN;
+        status =xran_bm_init(xranHandle,&psBbuIo->nBufPoolIndex[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; i<nSectorNum; i++)
+    {
+        for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
+        {
+            for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+                pFthTxBuffer[i][z][j]     = &(psBbuIo->sFrontHaulTxBbuIoBufCtrl[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; i<nSectorNum; i++)
+        {
+            xran_5g_fronthault_config (psBbuIo->nInstanceHandle[0][i],
+                pFthTxBuffer[i],
+                pFthRxBuffer[i],
+                xran_fh_rx_callback,  &pFthRxBuffer[i][0]);
+        }
+
+        // add prach callback here
+        for (i = 0; i<nSectorNum; i++)
+        {
+            xran_5g_prach_req(psBbuIo->nInstanceHandle[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; i<nSectorNum; i++)
+    {
+        pPhaseCompDl = (FPGAPhaseCompCfg *)(&nPhaseCompDl);
+        pPhaseCompDl->NRARFCN = 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 <nSectorNum; cc_id++)
+    {
+        for(tti  = 0; tti  < XRAN_N_FE_BUF_LEN; tti ++) {
+            for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
+                for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
+                    flowId = nSectorNum * ant_id + cc_id;
+
+                    if(p_tx_play_buffer[flowId]){
+                        /* (0-79 slots) 10ms of IQs */
+                        pos =  ((char*)p_tx_play_buffer[flowId]) + tx_play_buffer_position[flowId];
+
+                        ptr = psBbuIo->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 <nSectorNum; cc_id++)
+    {
+        for(tti  = 0; tti  < XRAN_N_FE_BUF_LEN; tti++) {
+            for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
+                for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
+                    flowId = nSectorNum * ant_id + cc_id;
+                    if(p_rx_log_buffer[flowId]){
+                        /* (0-79 slots) 10ms of IQs */
+                        pos =  ((char*)p_rx_log_buffer[flowId]) + rx_log_buffer_position[flowId];
+                        ptr = psBbuIo->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 (file)
index 0000000..29ac054
--- /dev/null
@@ -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 (file)
index 0000000..cec7e5b
--- /dev/null
@@ -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 (file)
index 0000000..e84bc0a
--- /dev/null
@@ -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 (file)
index 0000000..1564c8d
--- /dev/null
@@ -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 <rte_ethdev.h>
+
+#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; i<strlen(input); i++)
+        if (input[i] == ' ' || input[i] == '\n' || input[i] == '\t')
+            input[i] = '\0';
+}
+
+static int fillConfigStruct(RuntimeConfig *config, const char *key, const char *value)
+{
+    int32_t parse_res = 0;
+
+    if (strcmp(key, KEY_APP_MODE) == 0){
+        config->appMode = 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; i++)
+            if (inputLine[i] == '#') {
+                inputLine[i] = '\0';
+                inputLen = i + 1;
+                break;
+            }
+
+        for (i=0; i<inputLen; i++)
+            if (inputLine[i] == '=') {
+                strncpy(key, inputLine, i);
+                key[i] = '\0';
+                trim(key);
+                if ((i + 1 > 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 (file)
index 0000000..b2953ee
--- /dev/null
@@ -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 <stdint.h>
+#include <rte_ether.h>
+
+/** 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 (file)
index 0000000..23a673c
--- /dev/null
@@ -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 (file)
index 0000000..149ad8a
--- /dev/null
@@ -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 (file)
index 0000000..d65eef1
--- /dev/null
@@ -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 (file)
index 0000000..9d08e42
--- /dev/null
@@ -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 (file)
index 0000000..24bacba
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#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 (file)
index 0000000..112ea41
--- /dev/null
@@ -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 <rte_common.h>
+#include <rte_ether.h>
+#include <rte_byteorder.h>
+
+
+/**
+ *****************************************************************************
+ * @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 (file)
index 0000000..0f0e1ba
--- /dev/null
@@ -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 (file)
index 0000000..a2399f0
--- /dev/null
@@ -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 (file)
index 0000000..2e98311
--- /dev/null
@@ -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 (file)
index 0000000..d44b5e0
--- /dev/null
@@ -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 <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#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 (file)
index 0000000..6d69c3e
--- /dev/null
@@ -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 <rte_common.h>
+#include <rte_mbuf.h>
+
+#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 (file)
index 0000000..4665762
--- /dev/null
@@ -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 <rte_common.h>
+#include <rte_mbuf.h>
+
+#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 (file)
index 0000000..3664ecc
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/queue.h>
+#include <err.h>
+#include <assert.h>
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <rte_config.h>
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mbuf.h>
+#include <rte_timer.h>
+
+#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), &eth_hdr->d_addr);
+        ether_format_addr(src, sizeof(src), &eth_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 (file)
index 0000000..3b00e15
--- /dev/null
@@ -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 <rte_config.h>
+#include <rte_mbuf.h>
+#include <rte_timer.h>
+
+#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 (file)
index 0000000..ebf997c
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/queue.h>
+#include <err.h>
+#include <assert.h>
+
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rte_config.h>
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_errno.h>
+
+#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, &eth_addr);
+    ether_format_addr(buf, sizeof(buf), &eth_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 (file)
index 0000000..b22aed8
--- /dev/null
@@ -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 <rte_config.h>
+#include <rte_ether.h>
+#include <rte_mbuf.h>
+
+#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 (file)
index 0000000..5494045
--- /dev/null
@@ -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 (file)
index 0000000..67079e2
--- /dev/null
@@ -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 <assert.h>
+#include <err.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+
+#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, &params, 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; i<nsection; i++)
+            xran_cp_add_section_info(pHandle,
+                    dir, cc_id, ru_port_id, subframe_id, slot_id,
+                    &sect_geninfo[i].info);
+        }
+
+    return (ret);
+}
+
+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)
+{
+    struct xran_cp_gen_params params;
+    struct xran_section_gen_info sect_geninfo[8];
+    struct rte_mbuf *mbuf;
+    int i, nsection, ret;
+    struct xran_lib_ctx *pxran_lib_ctx = xran_lib_get_ctx();
+    xRANPrachCPConfigStruct *pPrachCPConfig = &(pxran_lib_ctx->PrachCPConfig);
+
+#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, &params, 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,
+                    &sect_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 (file)
index 0000000..ad17c1e
--- /dev/null
@@ -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 <stdio.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_timer.h>
+
+#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 (file)
index 0000000..d42b22b
--- /dev/null
@@ -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 <rte_branch_prediction.h>
+
+#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; i<num_sections; i++) {
+        rte_memcpy(&list[i], &gen_info[i].info, sizeof(struct xran_section_info));
+#if defined(XRAN_CP_USES_HASHTABLE)
+        xran_section_add_hash(ptr->hash, 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; index<ptr->cur_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<<uval))) / (CPLEN_TS));
+}
+
+// Frequency offset 5.4.5.11
+// frequency_offset = freqOffset * SCS * 0.5
+inline int32_t xran_get_freqoffset(int freqOffset, int scs)
+{
+    return ((freqOffset * scs)>>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; i<params->numSections; 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 *)&params->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; i<result->numSections; 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; i<result->numSections; 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; i<result->numSections; 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; i<result->numSections; 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 (file)
index 0000000..b06c694
--- /dev/null
@@ -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 <rte_common.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+
+#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 (file)
index 0000000..2c99c19
--- /dev/null
@@ -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 (file)
index 0000000..94751f6
--- /dev/null
@@ -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 <sched.h>
+#include <assert.h>
+#include <err.h>
+#include <libgen.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_ring.h>
+
+#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; j<XRAN_N_FE_BUF_LEN; j++)
+    {
+        for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+           p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[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; j<XRAN_N_FE_BUF_LEN; j++)
+        for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+            printf("TTI:TX 0x%02x Sec %d Ant%d\n",j,i,z);
+            for(k = 0; k <XRAN_NUM_OF_SYMBOL_PER_SLOT; k++){
+                uint8_t *ptr = p_xran_lib_ctx->sFrontHaulTxBbuIoBufCtrl[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; j<XRAN_N_FE_BUF_LEN; j++)
+        for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+            printf("TTI:RX 0x%02x Sec %d Ant%d\n",j,i,z);
+            for(k = 0; k <XRAN_NUM_OF_SYMBOL_PER_SLOT; k++){
+                uint8_t *ptr = p_xran_lib_ctx->sFrontHaulRxBbuIoBufCtrl[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; j<XRAN_N_FE_BUF_LEN; j++)
+    {
+        for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+           p_xran_lib_ctx->sFHPrachRxBbuIoBufCtrl[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 (file)
index 0000000..6caee87
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..e030a86
--- /dev/null
@@ -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 <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <math.h>
+
+#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 (file)
index 0000000..875b0b6
--- /dev/null
@@ -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 <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#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 (file)
index 0000000..9e1d192
--- /dev/null
@@ -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 <stdint.h>
+#include <endian.h>
+#include <rte_common.h>
+#include <rte_config.h>
+
+#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 (file)
index 0000000..99feefb
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..a8c71f2
--- /dev/null
@@ -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 <rte_memcpy.h>
+#include <inttypes.h>
+#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 (file)
index 0000000..5394371
--- /dev/null
@@ -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 <<xRAN release track table.xlsx>>, 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: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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
+