From 922b5b595a0492eea7edca41b25d656774cc1380 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Mon, 15 Jan 2018 15:24:50 +0100
Subject: [PATCH] Fix NFAPI integration

This commit fixes issues introduced by the previous commit.

Summary of work:
- cleanup:
  - fix LOG_XX to be less verbose
  - fix cmake_targets/CMakeLists.txt
  - fix oaienv
  - remove dead code
- bug fixes:
  - in openair1/SCHED/fapi_l1.c we had:
      eNB->pdcch_vars[subframe&1].num_dci           = number_dci;
    should be:
      eNB->pdcch_vars[subframe&1].num_dci           = 0;
    This bug let the PHY send more DCIs than what should have been
    sent because num_dci is incremented later on in the code.
    This fix may be a problem for fapi mode, to be checked.
  - add new T VCD traces
  - revert openair1/PHY/TOOLS/file_output.c to 'develop' version
  - remove thread_id in logRecord/logRecord_mt
  - revert (and adapt) configuration files
  - be careful when doing frame++, we need to % 1024
  - revert target_rx_power in openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
- NFAPI:
  - the open-nFAPI code has been included in the repository. See nfapi/README.
    Maybe we should "git clone" the Cisco repository instead. We have to be
    careful of availability though.

What has been tested:
- monolithic eNB FDD 5/10MHz with one UE, iperf UDP/TCP uplink/downlink

Anything else may fail to work, especially the FAPI mode, which has not
been tested at all.
---
 cmake_targets/CMakeLists.txt                  |   57 +-
 common/utils/T/T_defs.h                       |    2 +-
 common/utils/T/T_messages.txt                 |   36 +
 nfapi/README                                  |   15 +
 nfapi/open-nFAPI/.travis.yml                  |   36 +
 nfapi/open-nFAPI/CHANGELOG.md                 |    0
 nfapi/open-nFAPI/LICENSE.md                   |  201 +
 nfapi/open-nFAPI/Makefile.am                  |   15 +
 nfapi/open-nFAPI/README.md                    |  138 +
 nfapi/open-nFAPI/common/Makefile.am           |   31 +
 nfapi/open-nFAPI/common/public_inc/debug.h    |   51 +
 nfapi/open-nFAPI/common/src/debug.c           |   76 +
 nfapi/open-nFAPI/configure.ac                 |   45 +
 nfapi/open-nFAPI/docs/Doxyfile                | 1720 +++++
 nfapi/open-nFAPI/docs/Doxyfile.in             | 1720 +++++
 nfapi/open-nFAPI/docs/Makefile.am             |   35 +
 nfapi/open-nFAPI/docs/doxygen.h               |  327 +
 .../open-nFAPI/integration_tests/Makefile.am  |   29 +
 nfapi/open-nFAPI/integration_tests/main.cpp   |  269 +
 nfapi/open-nFAPI/nfapi/Makefile.am            |   30 +
 nfapi/open-nFAPI/nfapi/inc/nfapi.h            |   91 +
 .../nfapi/public_inc/nfapi_interface.h        | 3855 ++++++++++
 nfapi/open-nFAPI/nfapi/src/nfapi.c            |  860 +++
 nfapi/open-nFAPI/nfapi/src/nfapi_p4.c         | 2084 ++++++
 nfapi/open-nFAPI/nfapi/src/nfapi_p5.c         | 1799 +++++
 nfapi/open-nFAPI/nfapi/src/nfapi_p7.c         | 6184 +++++++++++++++++
 nfapi/open-nFAPI/nfapi/tests/Makefile.am      |   36 +
 .../open-nFAPI/nfapi/tests/nfapi_cunit_main.c | 5511 +++++++++++++++
 nfapi/open-nFAPI/pnf/Makefile.am              |   32 +
 nfapi/open-nFAPI/pnf/inc/pnf.h                |   49 +
 nfapi/open-nFAPI/pnf/inc/pnf_p7.h             |  126 +
 .../pnf/public_inc/nfapi_pnf_interface.h      |  803 +++
 nfapi/open-nFAPI/pnf/src/pnf.c                | 1598 +++++
 nfapi/open-nFAPI/pnf/src/pnf_interface.c      |  432 ++
 nfapi/open-nFAPI/pnf/src/pnf_p7.c             | 1769 +++++
 nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c   |  225 +
 nfapi/open-nFAPI/pnf/tests/Makefile.am        |   28 +
 nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c   | 2365 +++++++
 nfapi/open-nFAPI/pnf_sim/Makefile.am          |   22 +
 nfapi/open-nFAPI/pnf_sim/inc/fapi_interface.h | 1800 +++++
 nfapi/open-nFAPI/pnf_sim/inc/fapi_stub.h      |   76 +
 nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp    |  642 ++
 nfapi/open-nFAPI/pnf_sim/src/main.cpp         | 2285 ++++++
 nfapi/open-nFAPI/sim_common/Makefile.am       |   31 +
 nfapi/open-nFAPI/sim_common/inc/pool.h        |  186 +
 nfapi/open-nFAPI/sim_common/inc/vendor_ext.h  |   71 +
 nfapi/open-nFAPI/sim_common/src/pool.cpp      |   15 +
 nfapi/open-nFAPI/vnf/Makefile.am              |   43 +
 nfapi/open-nFAPI/vnf/inc/vnf.h                |   46 +
 nfapi/open-nFAPI/vnf/inc/vnf_p7.h             |  136 +
 .../vnf/public_inc/nfapi_vnf_interface.h      |  995 +++
 nfapi/open-nFAPI/vnf/src/vnf.c                | 1123 +++
 nfapi/open-nFAPI/vnf/src/vnf_interface.c      |  676 ++
 nfapi/open-nFAPI/vnf/src/vnf_p7.c             | 1599 +++++
 nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c   |  562 ++
 nfapi/open-nFAPI/vnf/tests/Makefile.am        |   30 +
 nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c   | 1497 ++++
 nfapi/open-nFAPI/vnf_sim/Makefile.am          |   22 +
 nfapi/open-nFAPI/vnf_sim/inc/mac.h            |   60 +
 nfapi/open-nFAPI/vnf_sim/src/mac.cpp          | 1327 ++++
 nfapi/open-nFAPI/vnf_sim/src/main.cpp         | 1525 ++++
 nfapi/open-nFAPI/xml/pnf_phy_1_A.xml          |   88 +
 nfapi/open-nFAPI/xml/pnf_phy_1_A_ws.xml       |   90 +
 nfapi/open-nFAPI/xml/pnf_phy_1_B.xml          |   88 +
 nfapi/open-nFAPI/xml/pnf_phy_2_A.xml          |   90 +
 nfapi/open-nFAPI/xml/vnf_A.xml                |   21 +
 nfapi/open-nFAPI/xml/vnf_A_ws.xml             |   23 +
 oaienv                                        |   11 -
 openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c |    2 +-
 openair1/PHY/LTE_TRANSPORT/dci.c              |    5 -
 openair1/PHY/LTE_TRANSPORT/dci_tools.c        |   29 +-
 openair1/PHY/LTE_TRANSPORT/pucch.c            |    4 +-
 openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c   |    2 +-
 .../PHY/LTE_TRANSPORT/ulsch_demodulation.c    |    7 -
 openair1/PHY/TOOLS/file_output.c              |    6 +-
 openair1/PHY/defs.h                           |    2 -
 openair1/SCHED/fapi_l1.c                      |    9 +-
 openair1/SCHED/fapi_l1.h                      |    2 +-
 openair1/SCHED/phy_procedures_lte_eNb.c       |   55 +-
 openair1/SCHED/ru_procedures.c                |   10 -
 openair2/ENB_APP/enb_config.c                 |   10 +-
 openair2/LAYER2/MAC/eNB_scheduler.c           |   13 -
 openair2/LAYER2/MAC/eNB_scheduler_RA.c        |   18 +-
 openair2/LAYER2/MAC/eNB_scheduler_bch.c       |   12 +-
 openair2/LAYER2/MAC/eNB_scheduler_dlsch.c     |   12 +-
 .../LAYER2/MAC/eNB_scheduler_primitives.c     |   27 +-
 openair2/LAYER2/MAC/eNB_scheduler_ulsch.c     |   10 +-
 openair2/LAYER2/MAC/pre_processor.c           |   16 +-
 openair2/PHY_INTERFACE/IF_Module.c            |   27 +-
 openair2/RRC/LITE/L2_interface.c              |    5 +-
 openair2/RRC/LITE/rrc_eNB.c                   |    4 +-
 openair2/UTIL/LOG/log.c                       |   22 +-
 openair2/UTIL/LOG/log.h                       |   27 +-
 targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp  |    4 +
 targets/COMMON/create_tasks.c                 |    2 +-
 .../CONF/enb.band7.tm1.50PRB.usrpb210.conf    |   47 +-
 .../CONF/oaiL1.nfapi.usrpb210.conf            |   21 +-
 .../CONF/rcc.band7.tm1.50PRB.nfapi.conf       |   66 +-
 targets/RT/USER/lte-enb.c                     |   58 +-
 targets/RT/USER/lte-ran.c                     |    7 -
 targets/RT/USER/lte-ru.c                      |   76 +-
 targets/RT/USER/lte-softmodem.c               |    6 +-
 102 files changed, 48002 insertions(+), 481 deletions(-)
 create mode 100644 nfapi/README
 create mode 100644 nfapi/open-nFAPI/.travis.yml
 create mode 100644 nfapi/open-nFAPI/CHANGELOG.md
 create mode 100644 nfapi/open-nFAPI/LICENSE.md
 create mode 100644 nfapi/open-nFAPI/Makefile.am
 create mode 100644 nfapi/open-nFAPI/README.md
 create mode 100644 nfapi/open-nFAPI/common/Makefile.am
 create mode 100644 nfapi/open-nFAPI/common/public_inc/debug.h
 create mode 100644 nfapi/open-nFAPI/common/src/debug.c
 create mode 100644 nfapi/open-nFAPI/configure.ac
 create mode 100644 nfapi/open-nFAPI/docs/Doxyfile
 create mode 100644 nfapi/open-nFAPI/docs/Doxyfile.in
 create mode 100644 nfapi/open-nFAPI/docs/Makefile.am
 create mode 100644 nfapi/open-nFAPI/docs/doxygen.h
 create mode 100644 nfapi/open-nFAPI/integration_tests/Makefile.am
 create mode 100644 nfapi/open-nFAPI/integration_tests/main.cpp
 create mode 100644 nfapi/open-nFAPI/nfapi/Makefile.am
 create mode 100644 nfapi/open-nFAPI/nfapi/inc/nfapi.h
 create mode 100644 nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
 create mode 100644 nfapi/open-nFAPI/nfapi/src/nfapi.c
 create mode 100644 nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
 create mode 100644 nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
 create mode 100644 nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
 create mode 100644 nfapi/open-nFAPI/nfapi/tests/Makefile.am
 create mode 100644 nfapi/open-nFAPI/nfapi/tests/nfapi_cunit_main.c
 create mode 100644 nfapi/open-nFAPI/pnf/Makefile.am
 create mode 100644 nfapi/open-nFAPI/pnf/inc/pnf.h
 create mode 100644 nfapi/open-nFAPI/pnf/inc/pnf_p7.h
 create mode 100644 nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
 create mode 100644 nfapi/open-nFAPI/pnf/src/pnf.c
 create mode 100644 nfapi/open-nFAPI/pnf/src/pnf_interface.c
 create mode 100644 nfapi/open-nFAPI/pnf/src/pnf_p7.c
 create mode 100644 nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
 create mode 100644 nfapi/open-nFAPI/pnf/tests/Makefile.am
 create mode 100644 nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c
 create mode 100644 nfapi/open-nFAPI/pnf_sim/Makefile.am
 create mode 100644 nfapi/open-nFAPI/pnf_sim/inc/fapi_interface.h
 create mode 100644 nfapi/open-nFAPI/pnf_sim/inc/fapi_stub.h
 create mode 100644 nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp
 create mode 100644 nfapi/open-nFAPI/pnf_sim/src/main.cpp
 create mode 100644 nfapi/open-nFAPI/sim_common/Makefile.am
 create mode 100644 nfapi/open-nFAPI/sim_common/inc/pool.h
 create mode 100644 nfapi/open-nFAPI/sim_common/inc/vendor_ext.h
 create mode 100644 nfapi/open-nFAPI/sim_common/src/pool.cpp
 create mode 100644 nfapi/open-nFAPI/vnf/Makefile.am
 create mode 100644 nfapi/open-nFAPI/vnf/inc/vnf.h
 create mode 100644 nfapi/open-nFAPI/vnf/inc/vnf_p7.h
 create mode 100644 nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
 create mode 100644 nfapi/open-nFAPI/vnf/src/vnf.c
 create mode 100644 nfapi/open-nFAPI/vnf/src/vnf_interface.c
 create mode 100644 nfapi/open-nFAPI/vnf/src/vnf_p7.c
 create mode 100644 nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
 create mode 100644 nfapi/open-nFAPI/vnf/tests/Makefile.am
 create mode 100644 nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c
 create mode 100644 nfapi/open-nFAPI/vnf_sim/Makefile.am
 create mode 100644 nfapi/open-nFAPI/vnf_sim/inc/mac.h
 create mode 100644 nfapi/open-nFAPI/vnf_sim/src/mac.cpp
 create mode 100644 nfapi/open-nFAPI/vnf_sim/src/main.cpp
 create mode 100644 nfapi/open-nFAPI/xml/pnf_phy_1_A.xml
 create mode 100644 nfapi/open-nFAPI/xml/pnf_phy_1_A_ws.xml
 create mode 100644 nfapi/open-nFAPI/xml/pnf_phy_1_B.xml
 create mode 100644 nfapi/open-nFAPI/xml/pnf_phy_2_A.xml
 create mode 100644 nfapi/open-nFAPI/xml/vnf_A.xml
 create mode 100644 nfapi/open-nFAPI/xml/vnf_A_ws.xml

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 7b4e30b030..32f06de025 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -27,8 +27,8 @@ cmake_minimum_required (VERSION 2.8)
 # Base directories, compatible with legacy OAI building
 ################################################
 set (OPENAIR_DIR     $ENV{OPENAIR_DIR})
-set (NFAPI_DIR       $ENV{NFAPI_DIR})
-set (NFAPI_USER_DIR  ${OPENAIR_DIR}/nfapi)
+set (NFAPI_DIR       ${OPENAIR_DIR}/nfapi/open-nFAPI)
+set (NFAPI_USER_DIR  ${OPENAIR_DIR}/nfapi/oai_integration)
 set (OPENAIR1_DIR    ${OPENAIR_DIR}/openair1)
 set (OPENAIR2_DIR    ${OPENAIR_DIR}/openair2)
 set (OPENAIR3_DIR    ${OPENAIR_DIR}/openair3)
@@ -1061,9 +1061,9 @@ include_directories(${NFAPI_DIR}/vnf/inc)
 # nFAPI user defined code
 #############################
 set(NFAPI_USER_SRC
-${NFAPI_USER_DIR}/nfapi.c
-${NFAPI_USER_DIR}/nfapi_pnf.c
-${NFAPI_USER_DIR}/nfapi_vnf.c
+  ${NFAPI_USER_DIR}/nfapi.c
+  ${NFAPI_USER_DIR}/nfapi_pnf.c
+  ${NFAPI_USER_DIR}/nfapi_vnf.c
 )
 add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC})
 include_directories(${NFAPI_USER_DIR})
@@ -1740,26 +1740,6 @@ endif()
 add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}")
 add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}")
 
-#pkg_search_module(NFAPI nfapi)
-#if(NOT ${NFAPI_FOUND})
-  #message( FATAL_ERROR "PACKAGE nfapi not found: some targets will fail. Run build_oai -I again!")
-#else()
-  #include_directories(${NFAPI_INCLUDE_DIRS})
-  #message( "PACKAGE nfapi!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
-  #message( "${NFAPI_INCLUDE_DIR}")
-  #message( "${NFAPI_COMMON_INCLUDE_DIR}")
-  #message( "${NFAPI_VNF_INCLUDE_DIR}")
-  #message( "${NFAPI_PNF_INCLUDE_DIR}")
-  #message( "XXX")
-  #message( "${NFAPI_LIBRARY}")
-  #message( "${NFAPI_COMMON_LIBRARY}")
-  #message( "${NFAPI_PNF_LIBRARY}")
-  #message( "XXX")
-  #message( "${NFAPI_LIBRARIES}")
-  #message( "XXX")
-#endif()
-
-
 pkg_search_module(XPM xpm)
 if(NOT ${XPM_FOUND})
   message("PACKAGE xpm not found: some targets will fail")
@@ -1815,12 +1795,6 @@ if (${T_TRACER})
   set (T_LIB "rt")
 endif (${T_TRACER})
 
-#if (${NFAPI_DIR})
-#set (NFAPI_PNF_LIB "nfapi_pnf")
-#set (NFAPI_LIB "nfapi")
-#set (NFAPI_COMMON_LIB "nfapi_common")
-#endif (${NFAPI_DIR})
-#
 #Some files in the T directory are generated.
 #This rule and the following deal with it.
 add_custom_command (
@@ -2005,27 +1979,6 @@ add_executable(oaisim
   ${SHLIB_LOADER_SOURCES}
 )
 
-#add_library( imp_nfapi STATIC IMPORTED)
-#set_property(TARGET imp_nfapi PROPERTY IMPORTED_LOCATION ${NFAPI_DIR}/libnfapi.a)
-#set_property(TARGET imp_nfapi PROPERTY IMPORTED_IMPLIB ${NFAPI_DIR}/libnfapi.a)
-#target_link_libraries(oaisim imp_nfapi)
-
-#add_library( imp_nfapi_common STATIC IMPORTED)
-#set_property(TARGET imp_nfapi_common PROPERTY IMPORTED_LOCATION ${NFAPI_DIR}/common/libnfapi_common.a)
-#set_property(TARGET imp_nfapi_common PROPERTY IMPORTED_IMPLIB ${NFAPI_DIR}/common/libnfapi_common.a)
-#target_link_libraries(oaisim imp_nfapi_common)
-
-#add_library( imp_nfapi_pnf STATIC IMPORTED)
-#set_property(TARGET imp_nfapi_pnf PROPERTY IMPORTED_LOCATION ${NFAPI_DIR}/pnf/libnfapi_pnf.a)
-#set_property(TARGET imp_nfapi_pnf PROPERTY IMPORTED_IMPLIB ${NFAPI_DIR}/pnf/libnfapi_pnf.a)
-#target_link_libraries(oaisim imp_nfapi_pnf)
-
-#
-#add_library (imp_nfapi_common STATIC IMPORTED)
-#set_target_properties(imp_nfapi_common PROPERTIES IMPORTED_LOCATION ${NFAPI_DIR}/common/libnfapi_common.a
-#set_target_properties(oaisim PROPERTIES LINK_FLAGS ${NFAPI_DIR}/nfapi/libnfapi.a ${NFAPI_DIR}/pnf/libnfapi_pnf.a ${NFAPI_DIR}/common/libnfapi_common.a)
-
-
 
 target_include_directories(oaisim PUBLIC  ${OPENAIR_TARGETS}/SIMU/USER)
 target_link_libraries (oaisim
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index 24845b6b9e..6bdda0edac 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -29,7 +29,7 @@ typedef struct {
 #define T_SHM_FILENAME "/T_shm_segment"
 
 /* number of VCD functions (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_FUNCTIONS 178
+#define VCD_NUM_FUNCTIONS 187
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
 #define VCD_NUM_VARIABLES 128
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 3e37b5ea15..3009cc3305 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -2157,3 +2157,39 @@ ID = VCD_FUNCTION_TRX_DECOMPR_IF
     DESC = VCD function TRX_DECOMPR_IF
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_NFAPI
+    DESC = VCD function NFAPI
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_GENERATE_PCFICH
+    DESC = VCD function GENERATE_PCFICH
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_GENERATE_DCI0
+    DESC = VCD function GENERATE_DCI0
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_GENERATE_DLSCH
+    DESC = VCD function GENERATE_DLSCH
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_GENERATE_PHICH
+    DESC = VCD function GENERATE_PHICH
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDCCH_SCRAMBLING
+    DESC = VCD function PDCCH_SCRAMBLING
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDCCH_MODULATION
+    DESC = VCD function PDCCH_MODULATION
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDCCH_INTERLEAVING
+    DESC = VCD function PDCCH_INTERLEAVING
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDCCH_TX
+    DESC = VCD function PDCCH_TX
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
diff --git a/nfapi/README b/nfapi/README
new file mode 100644
index 0000000000..b2e1321532
--- /dev/null
+++ b/nfapi/README
@@ -0,0 +1,15 @@
+This directory contains the NFAPI code.
+
+It comes in two parts:
+
+1 - open-nFAPI
+
+    This is a clone of the github repository
+    (https://github.com/cisco/open-nFAPI,
+     commit b3bc579b1697eab829d5d8a2de59c93a61b88fa4).
+    The patch open-nfapi.oai.patch has then been applied.
+
+2 - oai_integration
+
+    This is code written by David Price from Cisco to integrate
+    open-nFAPI into OpenAirInterface.
diff --git a/nfapi/open-nFAPI/.travis.yml b/nfapi/open-nFAPI/.travis.yml
new file mode 100644
index 0000000000..ce2faea923
--- /dev/null
+++ b/nfapi/open-nFAPI/.travis.yml
@@ -0,0 +1,36 @@
+
+env:
+  global:
+    # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created 
+    #   via the "travis encrypt" command using the project repo's public key
+    - secure: "oNj8JhGBN/zjzrAU7y2Nn/wxSxA/MDp2Y8fVLLp6fhx+y2mWdlMZhgCjeKSpdbGtroUnxErX1P8t+8EPz2+mMoq+G809Q9t7eJjd1+6nkVhEEfDXN83BmJkvIylC0/IKJiT2wCa8LzbdhpQUFyZ1Gk1WKZozAW5HotfFjm6/NFi/GX4uA7S0tU5E4yC3r4yqH9cLZ+arWMOEY/X0lrx0n6tLjDe921kFwkZQGFzAzrbXN2fZXKQ3xFcpREWEgEWsY7H2n4T7oJI3nEPY4P/4kvCjeQMjnlATEwtcciBiUbHRew4WWSTndF54crRlqFlzFcEf/Ouz27U/d2xYHJWcWNi88l+/qsb+V0uobwhiGUJGbVhf9IkgEO3tr/zbwkPDFrXpa/1xuSoc6jDm8i61gKQkcBhQsRFXlciPvwLhiL07gzeAfZD1Yke3tE+0geHPbEA0czzwtHe35jorAKYWsFXOXmcoK9t9SpnvBRFz6JuEsHPooafze43sTJg3qkgBszkU+U38CneeAVwo/uTA3Zw1ZrtOQv56v0UvAHze/VAF5z3rFJPl1oJl60OI8V5UBg4yIa2bySKhO//zwd4MGmsBpcWwDuu2BHUVasfk0vaetVxVVtdXG/2BuBP+IXinpJtI48NSFs6PT82dHz4cDF/iLDs0hPC6sbV258PY8F0="
+
+language: cpp
+
+dist: trusty
+sudo: required
+
+compiler:
+  - g++
+
+before_install:
+  - sudo apt-get install doxygen 
+  - sudo apt-get install libcunit1-dev 
+  - sudo apt-get install libz-dev
+  - sudo apt-get install libsctp-dev
+  - sudo apt-get install libboost-all-dev
+  - autoreconf -i
+
+addons:
+  coverity_scan:
+    project:
+      name: cisco-open-nFAPI
+      version: 1.0
+      description: Build submitted via Travis CI
+    notification_email: xxx@cisco.com
+    build_command_prepend: ./configure
+    build_command: make
+    branch_pattern: coverity_scan
+
+script:
+  - ./configure && make && make check
diff --git a/nfapi/open-nFAPI/CHANGELOG.md b/nfapi/open-nFAPI/CHANGELOG.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/nfapi/open-nFAPI/LICENSE.md b/nfapi/open-nFAPI/LICENSE.md
new file mode 100644
index 0000000000..5e0fd33cbb
--- /dev/null
+++ b/nfapi/open-nFAPI/LICENSE.md
@@ -0,0 +1,201 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction,
+and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by
+the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all
+other entities that control, are controlled by, or are under common
+control with that entity. For the purposes of this definition,
+"control" means (i) the power, direct or indirect, to cause the
+direction or management of such entity, whether by contract or
+otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity
+exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications,
+including but not limited to software source code, documentation
+source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical
+transformation or translation of a Source form, including but
+not limited to compiled object code, generated documentation,
+and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or
+Object form, made available under the License, as indicated by a
+copyright notice that is included in or attached to the work
+(an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object
+form, that is based on (or derived from) the Work and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship. For the purposes
+of this License, Derivative Works shall not include works that remain
+separable from, or merely link (or bind by name) to the interfaces of,
+the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including
+the original version of the Work and any modifications or additions
+to that Work or Derivative Works thereof, that is intentionally
+submitted to Licensor for inclusion in the Work by the copyright owner
+or by an individual or Legal Entity authorized to submit on behalf of
+the copyright owner. For the purposes of this definition, "submitted"
+means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems,
+and issue tracking systems that are managed by, or on behalf of, the
+Licensor for the purpose of discussing and improving the Work, but
+excluding communication that is conspicuously marked or otherwise
+designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity
+on behalf of whom a Contribution has been received by Licensor and
+subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the
+Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except as stated in this section) patent license to make, have made,
+use, offer to sell, sell, import, and otherwise transfer the Work,
+where such license applies only to those patent claims licensable
+by such Contributor that are necessarily infringed by their
+Contribution(s) alone or by combination of their Contribution(s)
+with the Work to which such Contribution(s) was submitted. If You
+institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work
+or a Contribution incorporated within the Work constitutes direct
+or contributory patent infringement, then any patent licenses
+granted to You under this License for that Work shall terminate
+as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+Work or Derivative Works thereof in any medium, with or without
+modifications, and in Source or Object form, provided that You
+meet the following conditions:
+
+(a) You must give any other recipients of the Work or
+Derivative Works a copy of this License; and
+
+(b) You must cause any modified files to carry prominent notices
+stating that You changed the files; and
+
+(c) You must retain, in the Source form of any Derivative Works
+that You distribute, all copyright, patent, trademark, and
+attribution notices from the Source form of the Work,
+excluding those notices that do not pertain to any part of
+the Derivative Works; and
+
+(d) If the Work includes a "NOTICE" text file as part of its
+distribution, then any Derivative Works that You distribute must
+include a readable copy of the attribution notices contained
+within such NOTICE file, excluding those notices that do not
+pertain to any part of the Derivative Works, in at least one
+of the following places: within a NOTICE text file distributed
+as part of the Derivative Works; within the Source form or
+documentation, if provided along with the Derivative Works; or,
+within a display generated by the Derivative Works, if and
+wherever such third-party notices normally appear. The contents
+of the NOTICE file are for informational purposes only and
+do not modify the License. You may add Your own attribution
+notices within Derivative Works that You distribute, alongside
+or as an addendum to the NOTICE text from the Work, provided
+that such additional attribution notices cannot be construed
+as modifying the License.
+
+You may add Your own copyright statement to Your modifications and
+may provide additional or different license terms and conditions
+for use, reproduction, or distribution of Your modifications, or
+for any such Derivative Works as a whole, provided Your use,
+reproduction, and distribution of the Work otherwise complies with
+the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+any Contribution intentionally submitted for inclusion in the Work
+by You to the Licensor shall be under the terms and conditions of
+this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify
+the terms of any separate license agreement you may have executed
+with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+names, trademarks, service marks, or product names of the Licensor,
+except as required for reasonable and customary use in describing the
+origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+agreed to in writing, Licensor provides the Work (and each
+Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied, including, without limitation, any warranties or conditions
+of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any
+risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+whether in tort (including negligence), contract, or otherwise,
+unless required by applicable law (such as deliberate and grossly
+negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special,
+incidental, or consequential damages of any character arising as a
+result of this License or out of the use or inability to use the
+Work (including but not limited to damages for loss of goodwill,
+work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses), even if such Contributor
+has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+the Work or Derivative Works thereof, You may choose to offer,
+and charge a fee for, acceptance of support, warranty, indemnity,
+or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only
+on Your own behalf and on Your sole responsibility, not on behalf
+of any other Contributor, and only if You agree to indemnify,
+defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following
+boilerplate notice, with the fields enclosed by brackets "{}"
+replaced with your own identifying information. (Don't include
+the brackets!)  The text should be enclosed in the appropriate
+comment syntax for the file format. We also recommend that a
+file or class name and description of purpose be included on the
+same "printed page" as the copyright notice for easier
+identification within third-party archives.
+
+Copyright {yyyy} {name of copyright owner}
+
+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.
diff --git a/nfapi/open-nFAPI/Makefile.am b/nfapi/open-nFAPI/Makefile.am
new file mode 100644
index 0000000000..900cf2bbcf
--- /dev/null
+++ b/nfapi/open-nFAPI/Makefile.am
@@ -0,0 +1,15 @@
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS =common/ \
+	 sim_common/ \
+	 nfapi/ \
+	 pnf/ \
+	 vnf/ \
+	 nfapi/tests \
+	 pnf/tests \
+	 vnf/tests \
+	 pnf_sim/ \
+	 vnf_sim/ \
+	 integration_tests/ \
+	 docs/ \
+	 $(NULL)
diff --git a/nfapi/open-nFAPI/README.md b/nfapi/open-nFAPI/README.md
new file mode 100644
index 0000000000..f3132c78d6
--- /dev/null
+++ b/nfapi/open-nFAPI/README.md
@@ -0,0 +1,138 @@
+[![Build Status](https://travis-ci.org/cisco/open-nFAPI.svg?branch=master)](https://travis-ci.org/cisco/open-nFAPI)
+[![Coverity Status](https://scan.coverity.com/projects/11791/badge.svg)](https://scan.coverity.com/projects/cisco-open-nfapi)
+
+# open-nFAPI
+ 
+Open-nFAPI is implementation of the Small Cell Forum's network functional API or nFAPI for short. 
+nFAPI defines a network protocol that is used to connect a Physical Network Function (PNF) 
+running LTE Layer 1 to a Virtual Network Function (VNF) running LTE layer 2 and above. The specification
+can be found at http://scf.io/documents/082.
+ 
+The aim of open-nFAPI is to provide an open interface between LTE layer 1 and layer 2 to allow for
+interoperability between the PNF and VNF & also to facilitate the sharing of PNF's between
+different VNF's
+
+Open-nFAPI implements the P4, P5 and P7 interfaces as defined by the nFAPI specification. 
+* The P5 interface allows the VNF to query and configure the 'resources' of the PNF; i.e slice it into
+ 1 or more PHY instances.
+* The P7 interface is used to send the subframe information between the PNF and VNF for a PHY instance
+* The P4 interface allows the VNF to request the PNF PHY instance to perform measurements of the surrounding network
+
+The remaining interfaces are currently outside of the scope of this project.
+
+Supports release 082.09.05 of the nFAPI specification
+
+**The Small Cell Forum cordially requests that any derivative work that looks to 
+extend the nFAPI libraries use the specified vendor extension techniques, 
+so ensuring the widest interoperability of the baseline nFAPI specification 
+in those derivative works.**
+
+## Awards
+
+The Open-nFAPI project has won the Small Cell Forum Judges Choice award 2017. (http://www.smallcellforum.org/awards-2/winners-2017/)
+
+## Licensing
+
+The open-nFAPI libraries are release by CISCO under an Apache 2 license. See `LICENSE.md` file for details
+
+## Downloading
+
+The open-nFAPI project can be pulled from git hub
+
+```
+git clone https://github.com/cisco/open-nFAPI.git nfapi
+```
+
+The following dependencies are required. These are based on a fresh ubuntu installation.
+
+```
+sudo apt-get install autoconf
+sudo apt-get install gcc
+sudo apt-get install g++
+sudo apt-get install libtool
+sudo apt-get install make
+sudo apt-get install doxygen
+sudo apt-get install libcunit1-dev
+sudo apt-get install libz-dev
+sudo apt-get install libsctp-dev
+sudo apt-get install libboost-all-dev
+```
+
+
+
+## Building
+
+To build the open-nFAPI project
+
+```
+autoreconf -i
+./configure
+make
+```
+
+To run the unit and integration tests
+
+```
+make check
+```
+
+You may notice in the console output of the final integration tests the following
+
+```
+*** Missing subframe 123 125
+```
+
+Out of the box the machine on which you are running has not be configured for real time operation as a result
+the vnf may not be scheduled at the correct times and hence it may risk 'missing' subframe opportunities. This
+warning indicates this has happened. 
+
+## Running the simulator
+
+The vnf and pnf simulator can be run using the following commands. The pnf and vnf simulator support sourcing and sinking
+data over udp. Review the xml configuration files for the details of the port and address to configure. Console logging will show
+which address:port is being used
+
+Note : Pinning the simulators to unused cores will produce more consistent behaviour.
+
+Note : You may have to run the processes with sudo to be able to set the real time scheduling and priority
+
+### vnf simulator
+
+To run the vnf simulator you need to specify the port the vnf will listen for p5 connection request upon and also the xml configuration file
+
+```
+vnfsim <port> <xml config file>
+```
+
+### pnf simulator
+
+To run the vnf simulator you need to specify the addrss & port the pnf will connect to the vnf on and also the xml configuration file
+
+```
+pnfsim <address> <port> <xml config file>
+```
+
+
+## Directory structure
+
+```
+docs                    doxgen documentation
+common                  common code used by the nfapi libraries
+nfapi                   the nfapi library including message definitions & encode/decode functions
+pnf                     the pnf library for p4, p5, & p7 interfaces
+vnf                     the vnf library for p4, p5, & p7 interfaces
+sim_common              common simulation for used by the vnf and pnf sim
+vnf_sim                 a vnf simulator including a stub mac implementation
+pnf_sim                 a pnf simualtor including a fapi interface defintion and stub implementation
+xml                     xml configuration files for the vnf and pnf simulator
+wireshark               code for a wireshark dissector for the nFAPI protocol
+```
+
+## Coverity
+
+Coverity runs on the coverity-scan branch. Changes must be merged to the coverity-scan branch to be checked.
+
+
+## eNB Integration - Open Air Interface
+
+The open-nFAPI implementation has been integrated with the Open Air Interface solution here (https://gitlab.eurecom.fr/oai/openairinterface5g) and is (at the time of writing) here (https://gitlab.eurecom.fr/daveprice/openairinterface5g/tree/nfapi-ru-rau-split). The open-nFAPI implementation is integrated with the source eNB implementation with any changes required applied as a patch on top of the baseline open-nFAPI library. Any extensions required must be implemented through the vendor extensions as specified by the Small Cell Forum documentation. Any integration wrapping of functionality must be done within the target environment as shown in the Open Air Interface implementation nfapi directory which is defined by the $NFAPI_DIR location at the top level.
diff --git a/nfapi/open-nFAPI/common/Makefile.am b/nfapi/open-nFAPI/common/Makefile.am
new file mode 100644
index 0000000000..3e3326ea2c
--- /dev/null
+++ b/nfapi/open-nFAPI/common/Makefile.am
@@ -0,0 +1,31 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AM_CPPFLAGS = -I$(top_srcdir)/common/public_inc -g -Wall -Werror
+
+noinst_LIBRARIES =libnfapi_common.a
+
+libnfapi_common_a_SOURCES = src/debug.c 
+
+libnfapi_common_a_CFLAGS =$(AM_CFLAGS)
+
+lib_LTLIBRARIES =libnfapi_common.la
+
+libnfapi_common_la_SOURCES = src/debug.c
+
+
+
+
diff --git a/nfapi/open-nFAPI/common/public_inc/debug.h b/nfapi/open-nFAPI/common/public_inc/debug.h
new file mode 100644
index 0000000000..14f97a17f6
--- /dev/null
+++ b/nfapi/open-nFAPI/common/public_inc/debug.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _DEBUG_H_
+#define _DEBUG_H_
+
+/*! The trace levels used by the nfapi libraries */
+typedef enum nfapi_trace_level
+{
+	NFAPI_TRACE_ERROR = 1,
+	NFAPI_TRACE_WARN,
+	NFAPI_TRACE_NOTE,
+	NFAPI_TRACE_INFO,
+
+	NFAPI_TRACE_LEVEL_MAX
+} nfapi_trace_level_t;
+
+/*! The trace function pointer */
+typedef void (*nfapi_trace_fn_t)(nfapi_trace_level_t level, const char* format, ...);
+
+/*! Global trace function */
+extern nfapi_trace_fn_t nfapi_trace_g;
+
+/*! Global trace level */
+extern nfapi_trace_level_t nfapi_trace_level_g;
+
+/*! NFAPI trace macro */
+//#define NFAPI_TRACE(level, format, ...) { if(nfapi_trace_g && ((nfapi_trace_level_t)level <= nfapi_trace_level_g)) (*nfapi_trace_g)(level, format, ##__VA_ARGS__); }
+#define NFAPI_TRACE(level, format, ...) { if (nfapi_trace_g) (*nfapi_trace_g)(level, format, ##__VA_ARGS__); }
+
+/*! Function to change the trace level 
+ * \param new_level The modified trace level
+ */
+
+void nfapi_set_trace_level(nfapi_trace_level_t new_level);
+
+#endif /* _DEBUG_H_ */
diff --git a/nfapi/open-nFAPI/common/src/debug.c b/nfapi/open-nFAPI/common/src/debug.c
new file mode 100644
index 0000000000..a45d41d7d7
--- /dev/null
+++ b/nfapi/open-nFAPI/common/src/debug.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <syslog.h>
+
+#include <debug.h>
+
+#define MAX_MSG_LENGTH 			2096
+#define TRACE_HEADER_LENGTH		44
+
+void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...);
+
+// initialize the trace function to 0
+void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg;
+
+nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO;
+//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN;
+
+void nfapi_set_trace_level(nfapi_trace_level_t new_level)
+{
+	nfapi_trace_level_g = new_level;
+}
+
+void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...)
+{
+	char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH];
+	uint32_t num_chars;
+	va_list p_args;
+	struct timeval tv;
+	pthread_t tid = pthread_self();
+
+	(void)gettimeofday(&tv, NULL);
+
+	num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid);
+
+	if (num_chars > TRACE_HEADER_LENGTH)
+	{
+		printf("trace_dbg: Error, num_chars is too large: %d", num_chars);
+		return;
+	}
+
+	va_start(p_args, format);
+	if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args)))
+	{
+		if (level <= NFAPI_TRACE_WARN)
+		{
+			printf("%s", trace_buff);
+		}
+		printf("%s", trace_buff);
+	}
+	va_end(p_args);
+}
diff --git a/nfapi/open-nFAPI/configure.ac b/nfapi/open-nFAPI/configure.ac
new file mode 100644
index 0000000000..fd3b387ee5
--- /dev/null
+++ b/nfapi/open-nFAPI/configure.ac
@@ -0,0 +1,45 @@
+AC_INIT([open-nFAPI], [1.0])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign serial-tests])
+AM_PROG_AR
+
+LT_INIT([shared static])
+
+# Dependencies
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_AWK
+AC_CONFIG_HEADERS([config.h])
+
+AC_PROG_LIBTOOL
+
+AC_CHECK_FILE([/usr/include/CUnit/CUnit.h],
+	[CFLAGS_CUNIT=-I/usr/include/CUnit AC_SUBST(CFLAGS_CUNIT)],
+	[AC_MSG_NOTICE([Have cunit *************])])
+
+# Need doxygen
+AC_CHECK_PROGS([DOXYGEN], [doxygen])
+if test -z "$DOXYGEN";
+	then AC_MSG_WARN([Doxygen not found - continuing without Doxygen support])
+fi
+AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([docs/Doxyfile])])
+
+AC_REQUIRE_AUX_FILE([tap-driver.sh])
+
+AC_CONFIG_FILES([Makefile
+                 sim_common/Makefile
+                 common/Makefile
+                 nfapi/Makefile
+                 pnf/Makefile
+                 vnf/Makefile
+                 nfapi/tests/Makefile
+                 pnf/tests/Makefile
+                 vnf/tests/Makefile
+                 pnf_sim/Makefile
+                 vnf_sim/Makefile
+                 integration_tests/Makefile
+                 docs/Makefile
+])
+AC_OUTPUT
diff --git a/nfapi/open-nFAPI/docs/Doxyfile b/nfapi/open-nFAPI/docs/Doxyfile
new file mode 100644
index 0000000000..9491727d2b
--- /dev/null
+++ b/nfapi/open-nFAPI/docs/Doxyfile
@@ -0,0 +1,1720 @@
+# Doxyfile 1.7.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = open-nFAPI
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = ../nfapi/public_inc ../pnf/public_inc ../vnf/public_inc ../docs/doxygen.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is adviced to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# If the HTML_TIMESTAMP tag is set to YES then the generated HTML documentation will contain the timesstamp.
+
+HTML_TIMESTAMP         = NO
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will write a font called Helvetica to the output
+# directory and reference it in all dot files that doxygen generates.
+# When you want a differently looking font you can specify the font name
+# using DOT_FONTNAME. You need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/nfapi/open-nFAPI/docs/Doxyfile.in b/nfapi/open-nFAPI/docs/Doxyfile.in
new file mode 100644
index 0000000000..74d405ad00
--- /dev/null
+++ b/nfapi/open-nFAPI/docs/Doxyfile.in
@@ -0,0 +1,1720 @@
+# Doxyfile 1.7.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = @PACKAGE_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = @top_srcdir@/nfapi/public_inc @top_srcdir@/pnf/public_inc @top_srcdir@/vnf/public_inc @top_srcdir@/docs/doxygen.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is adviced to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# If the HTML_TIMESTAMP tag is set to YES then the generated HTML documentation will contain the timesstamp.
+
+HTML_TIMESTAMP         = NO
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will write a font called Helvetica to the output
+# directory and reference it in all dot files that doxygen generates.
+# When you want a differently looking font you can specify the font name
+# using DOT_FONTNAME. You need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/nfapi/open-nFAPI/docs/Makefile.am b/nfapi/open-nFAPI/docs/Makefile.am
new file mode 100644
index 0000000000..9530fa844d
--- /dev/null
+++ b/nfapi/open-nFAPI/docs/Makefile.am
@@ -0,0 +1,35 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+if HAVE_DOXYGEN
+directory = $(top_srcdir)/docs/man/man3/
+
+dist_man_MANS = $(directory)/man_page_1.3 $(directory)/man_page_2.3
+$(directory)/man_page_1.3: doxyfile.stamp
+$(directory)/man_page_2.3: doxyfile.stamp
+
+doxyfile.stamp:
+	$(DOXYGEN) Doxyfile
+	echo Timestamp > doxyfile.stamp
+
+CLEANFILES = doxyfile.stamp
+
+all-local: doxyfile.stamp
+clean-local:
+	rm -rf $(top_srcdir)/docs/man
+	rm -rf $(top_srcdir)/docs/html
+	rm -rf $(top_srcdir)/docs/latex
+endif
diff --git a/nfapi/open-nFAPI/docs/doxygen.h b/nfapi/open-nFAPI/docs/doxygen.h
new file mode 100644
index 0000000000..ae815e68d6
--- /dev/null
+++ b/nfapi/open-nFAPI/docs/doxygen.h
@@ -0,0 +1,327 @@
+/*! \mainpage Open Network Function Application Platform Interface (Open-nFAPI)
+ *
+ * \section intro_sec Introduction
+ *
+ * Open-nFAPI is implementation of the Small Cell Forum's network femto API or nFAPI for short. 
+ * nFAPI defines a network protocol that is used to connect a Physical Network Function (PNF) 
+ * running LTE Layer 1 to a Virtual Network Function (VNF) running LTE Layer 2 and above. The specification
+ * can be found at http://scf.io/documents/082.
+ *
+ * The aim of Open-nFAPI is to provide an open interface between LTE Layer 1 and Layer 2 to allow for
+ * interoperability between the PNF and VNF & also to facilitate the sharing of PNF's between
+ * different VNF's
+ *
+ * Open-nFAPI implements the P4, P5 and P7 interfaces as defined by the nFAPI specification. 
+ * - The P5 interface allows the VNF to query and configure the 'resources' of the PNF; slicing it into
+ * 1 or more phy instances.  
+ * - The P7 interface is used to send the subframe information between the PNF and VNF for 1 or more phy instances
+ * - The P4 interface allows the VNF to request the PNF phy instances to perform measurements of the surrounding network
+ *
+ * The remaining interfaces are currently outside of the scope of this project.
+ *
+ * The best place to start is by reviewing the detailed nFAPI call flow which can be \ref nfapi_call_flow "here"
+ * 
+ * \section contrib Contibuting
+ *
+ * The Small Cell Forum cordially requests that any derivative work that looks to extend 
+ * the nFAPI libraries use the specified vendor extension techniques, so ensuring 
+ *the widest interoperability of the baseline nFAPI specification in those derivative works.
+ * 
+ * \section install_sec Installation
+ *
+ * \subsection step1 Step 1: Opening the box
+ *
+ * etc...
+ *
+ * \section dir_struct Directory Structure
+ * \code
+ 
+ *     nfapi
+ *     |- common                    Common functions for the nfapi project
+ *     |  |- src
+ *     |  |- public-inc
+ *     |- nfapi                     The NFAPI lib
+ *     |  |- inc
+ *     |  |- src
+ *     |  |- public-inc             Public interface for the nfapi library
+ *     |  |- tests                  Unit test for the nfapi lib
+ *     |- pnf                       The PNF lib
+ *     |  |- inc
+ *     |  |- src
+ *     |  |- public-inc             Public interface for the pnf library
+ *     |  |- tests                  Unit test for the pnf lib
+ *     |- vnf                       The VNF lib
+ *     |  |- inc
+ *     |  |- src
+ *     |  |- public-inc             Public interface for the vnf library
+ *     |  |- tests                  Unit test for the vnf lib
+ *     |- sim_common                Common functions for the nfapi simulators
+ *     |  |- inc
+ *     |  |- src
+ *     |- pnf_sim                   The PNF simulator
+ *     |  |- inc
+ *     |  |- src
+ *     |- vnf_sim                   The VNF simulator
+ *     |  |- inc
+ *     |  |- src
+ *     |- integration_tests         Integration tests that run both VNF & PNF simulators
+ *     |  |- inc
+ *     |  |- src
+ *     |- docs                      Documentation
+ *     |- xml                       Xml configuration for the simulator
+ 
+ * \endcode
+ * \section building Building
+ * To build the nfapi project and run the unit test you will need to 
+ * \code
+ *     autoreconf -i
+ *     ./configure
+ *     make
+ *     make check
+ * \endcode
+ * The following dependencies will be required
+ * - Boost. Need to build the simulators
+ * - STCP. Need to run the simulators
+ * - 
+ * \section simulators  Running the simulators
+ * Once you have build the nfapi project you can run the PNF/VNF simulators on either the same
+ * of seperate linux machines. 
+ * 
+ * To run the VNF from the vnf_sim directory.
+ * \code
+ *     ./vnfsim 4242 ../xml/vnf_A.xml
+ * [MAC] Rx Data from 8891
+ * [MAC] Tx Data to 10.231.16.80.8892
+ * Calling nfapi_vnf_start
+ * 2035.854438: 0x04:  773068608: nfapi_vnf_start()
+ * 2035.854450: 0x04:  773068608: Starting P5 VNF connection on port 4242
+ * 2035.854472: 0x04:  773068608: P5 socket created... 3
+ * 2035.854478: 0x03:  773068608: VNF Setting the SCTP_INITMSG
+ * 2035.854481: 0x04:  773068608: IPV4 binding to port 4242
+ * 2035.854485: 0x04:  773068608: bind succeeded..3.
+ * 2035.854497: 0x04:  773068608: listen succeeded...
+ * \endcode
+ *
+ * 
+ * To run the PNF from the pnf_sim directory
+ * \code
+ *     ./pnfsim 127.0.01 4242 ../xml/pnf_phy_1_A.xml
+ * nfapi_pnf_start
+ * Starting P5 PNF connection to VNF at 127.0.0.1:4242
+ * Host address info  0 Family:IPV4 Address:127.0.0.1
+ * PNF Setting the SCTP_INITMSG
+ * P5 socket created...
+ * Socket CONNECTED
+ * PNF_PARAM.request received
+ * [PNF_SIM] pnf param request
+ * PNF_CONFIG.request received
+ * [PNF_SIM] pnf config request
+ * .... and so on
+ * \endcode
+ * 
+ * You can Ctrl-C to exit the simulators. 
+ * 
+
+ */
+
+/*! \page nfapi_call_flow NFAPI Call Flow
+ *
+ * \section seq_diag Sequence diagram
+ *
+ * The follow sequence digram show how the nFAPI api will be used to bring up 
+ * the PNF and then the PNF PHY and initiate subframe message exchange
+ * The names of the CLIENT callbacks are placeholders for the functions that 
+ * the CLIENT will provide.
+ *
+ * \msc
+ *
+ *   width="1750";
+ *   FAPI, PNF_P7_CLIENT, PNF_P7_LIB, PNF_P5_CLIENT, PNF_P5_LIB, VNF_P5_LIB, VNF_P5_CLIENT, VNF_P7_LIB, VNF_P7_CLIENT, MAC;
+ *   VNF_P5_CLIENT=>VNF_P5_LIB		[label="nfapi_vnf_config_create", URL="\ref nfapi_vnf_config_create"];
+ *   VNF_P5_CLIENT=>VNF_P5_LIB		[label="nfapi_vnf_start", URL="\ref nfapi_vnf_start"];
+ *   VNF_P5_LIB note VNF_P5_LIB		[label="Listening for PNF connection"];
+ *   PNF_P5_CLIENT note PNF_P5_CLIENT		[label="P9 has provided the address of the VNF"];
+ *	 PNF_P5_CLIENT=>PNF_P5_LIB		[label="nfapi_pnf_config_create", URL="\ref nfapi_pnf_config_create"];
+ *	 PNF_P5_CLIENT=>PNF_P5_LIB		[label="nfapi_pnf_start", URL="\ref nfapi_pnf_start"];
+ *   PNF_P5_LIB note PNF_P5_LIB		[label="PNF STATE : PNF IDLE"];
+ *   PNF_P5_LIB->VNF_P5_LIB			[label="<connect>"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="pnf_connection_indication", URL="\ref nfapi_vnf_config::pnf_connection_indication"];
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_pnf_param_req", URL="\ref nfapi_vnf_pnf_param_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="PNF_PARAM.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="pnf_param_request", URL="\ref nfapi_pnf_config::pnf_param_req"];
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_pnf_param_response", URL="\ref nfapi_pnf_pnf_param_resp"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="PNF_PARAM.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="pnf_param_response", URL="\ref nfapi_vnf_config::pnf_param_resp"];
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_pnf_config_req", URL="\ref nfapi_vnf_pnf_config_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="PNF_CONFIG.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="pnf_config_request", URL="\ref nfapi_pnf_config::pnf_config_req"];
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_pnf_config_response", URL="\ref nfapi_pnf_pnf_config_resp"];
+ *   PNF_P5_LIB note PNF_P5_LIB		[label="PNF STATE : PNF CONFIGURED"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="PNF_CONFIG.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="pnf_config_response", URL="\ref nfapi_vnf_config::pnf_config_resp"];
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_pnf_start_req", URL="\ref nfapi_vnf_pnf_start_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="PNF_START.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="pnf_start_request", URL="\ref nfapi_pnf_config::pnf_start_req"];
+ *   PNF_P5_CLIENT=>FAPI			[label="<create>"];
+ *   FAPI note FAPI					[label="FAPI STATE : IDLE"];
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_pnf_start_response", URL="\ref nfapi_pnf_pnf_start_resp"];
+ *   PNF_P5_LIB note PNF_P5_LIB		[label="PNF STATE : PNF RUNNING"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="PNF_START.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="pnf_start_response", URL="\ref nfapi_vnf_config::pnf_param_resp"];
+ *
+ *   --- [ label="If vnf p7 instance not already running"];
+ *   VNF_P5_CLIENT=>VNF_P5_LIB	    [label="nfapi_vnf_allocate_phy", URL="\ref nfapi_vnf_allocate_phy"];
+ *   VNF_P5_CLIENT=>VNF_P7_CLIENT	[label="<create>"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_config_create", URL="\ref nfapi_vnf_p7_config_create"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_start", URL="\ref nfapi_vnf_p7_start"];
+ *   ---;
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_param_request", URL="\ref nfapi_vnf_param_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="PARAM.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="param_request", URL="\ref nfapi_pnf_config::param_req"];
+ *   PNF_P5_CLIENT=>FAPI			[label="fapi_param_request"];
+ *   PNF_P5_CLIENT<=FAPI			[label="fapi_param_response"];
+ *   PNF_P5_CLIENT=>PNF_P7_CLIENT	[label="<create>"];
+ *   PNF_P7_CLIENT=>PNF_P7_LIB		[label="nfapi_pnf_p7_create", URL="\ref nfapi_pnf_p7_config_create"];
+ *   PNF_P7_CLIENT=>PNF_P7_LIB		[label="nfapi_pnf_p7_start", URL="\ref nfapi_pnf_p7_start"];
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_param_response", URL="\ref nfapi_pnf_param_resp"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="PARAM.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="param_response", URL="\ref nfapi_vnf_config::param_resp"];
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_config_request", URL="\ref nfapi_vnf_config_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="CONFIG.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="config_request", URL="\ref nfapi_pnf_config::config_req"];
+ *   PNF_P5_CLIENT=>FAPI			[label="fapi_config_request"];
+ *   FAPI note FAPI					[label="FAPI STATE : CONFIGURED"];
+ *   PNF_P5_CLIENT<=FAPI			[label="fapi_config_response"];
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_config_response", URL="\ref nfapi_pnf_param_resp"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="CONFIG.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="config_response", URL="\ref nfapi_vnf_config::config_resp"];
+ *
+ *   VNF_P5_LIB<=VNF_P5_CLIENT		[label="nfapi_vnf_start_request", URL="\ref nfapi_vnf_start_req"];
+ *   VNF_P5_LIB->PNF_P5_LIB			[label="START.request"];
+ *   PNF_P5_LIB=>PNF_P5_CLIENT		[label="start_request", URL="\ref nfapi_pnf_config::start_req"];
+ *   PNF_P5_CLIENT=>FAPI			[label="fapi_start_request"];
+ *   FAPI note FAPI					[label="FAPI STATE : RUNNING"];
+ *   FAPI note FAPI					[label="FAPI will start sending subframe indications"];
+ *
+ *   --- [ label="For each 'phy' subframe"];
+ *   FAPI=>PNF_P7_CLIENT			[label="fapi_subframe_indication"];
+ *   PNF_P7_CLIENT=>PNF_P7_LIB		[label="nfapi_pnf_p7_subframe_ind", URL="\ref nfapi_pnf_p7_subframe_ind"];
+ *   ---;
+ *   PNF_P7_CLIENT=>PNF_P5_CLIENT	[label="<start_response>"];
+ *
+ *   PNF_P5_LIB<=PNF_P5_CLIENT		[label="nfapi_pnf_start_response", URL="\ref nfapi_pnf_start_resp"];
+ *   VNF_P5_LIB<-PNF_P5_LIB			[label="START.response"];
+ *   VNF_P5_LIB=>VNF_P5_CLIENT		[label="start_response", URL="\ref nfapi_vnf_config::start_resp"];
+ *   VNF_P5_CLIENT=>VNF_P7_CLIENT	[label="<p7_add_pnf>"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_add_pnf", URL="\ref nfapi_vnf_p7_add_pnf"];
+ *
+ *   VNF_P7_LIB->PNF_P7_LIB			[label="DL_NODE_SYNC"];
+ *   VNF_P7_LIB<-PNF_P7_LIB			[label="UL_NODE_SYNC"];
+ *   VNF_P7_LIB<-PNF_P7_LIB			[label="TIMING_INFO"];
+ *   VNF_P7_LIB note VNF_P7_LIB		[label="When sync is achieved"];
+ *
+ *   VNF_P7_LIB=>VNF_P7_CLIENT		[label="sync_indication", URL="\ref nfapi_vnf_p7_config::sync_indication"];
+ *
+ *   --- [ label="For each 'vnf phy' subframe"];
+ *   VNF_P7_LIB=>VNF_P7_CLIENT		[label="subframe_indication(tti=x)", URL="\ref nfapi_vnf_p7_config::subframe_indication"];
+ *   VNF_P7_CLIENT=>MAC				[label="subframe_indication"];
+ *   VNF_P7_CLIENT<=MAC				[label="dl_config_req"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_dl_config_req", URL="\ref nfapi_vnf_p7_dl_config_req"];
+ *   VNF_P7_LIB->PNF_P7_LIB			[label="DL_CONFIG.request"];
+ *   PNF_P7_LIB note PNF_P7_LIB		[label="Store in subframe buffer for tti x"];
+ *   VNF_P7_CLIENT<=MAC				[label="ul_config_req"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_ul_config_req", URL="\ref nfapi_vnf_p7_ul_config_req"];
+ *   VNF_P7_LIB->PNF_P7_LIB			[label="UL_CONFIG.request"];
+ *   PNF_P7_LIB note PNF_P7_LIB		[label="Store in subframe buffer for tti x"];
+ *   VNF_P7_CLIENT<=MAC				[label="hi_dci0_req"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_hi_dci0_req", URL="\ref nfapi_vnf_p7_hi_dci0_req"];
+ *   VNF_P7_LIB->PNF_P7_LIB			[label="HI_DCI0.request"];
+ *   PNF_P7_LIB note PNF_P7_LIB		[label="Store in subframe buffer for tti x"];
+ *   VNF_P7_CLIENT<=MAC				[label="tx_req"];
+ *   VNF_P7_CLIENT=>VNF_P7_LIB		[label="nfapi_vnf_p7_tx_req", URL="\ref nfapi_vnf_p7_tx_req"];
+ *   VNF_P7_LIB->PNF_P7_LIB			[label="TX.request"];
+ *   PNF_P7_LIB note PNF_P7_LIB		[label="Store in subframe buffer for tti x"];
+ *   ---;
+ *
+ *
+ *   --- [ label="For each 'phy' subframe"];
+ *
+ *   FAPI=>PNF_P7_CLIENT			[label="harq_indication"];
+ *   PNF_P7_CLIENT=>PNF_P7_LIB		[label="nfapi_pnf_p7_harq_ind", URL="\ref nfapi_pnf_p7_harq_ind"];
+ *   PNF_P7_LIB->VNF_P7_LIB			[label="HARQ.ind"];
+ *   VNF_P7_LIB=>VNF_P7_CLIENT		[label="harq_ind", URL="\ref nfapi_vnf_p7_config::harq_indication"];
+ *   VNF_P7_CLIENT=>MAC				[label="harq_ind"];
+ *
+ *   FAPI=>PNF_P7_CLIENT			[label="subframe_indication(tti=x)"];
+ *   PNF_P7_CLIENT=>PNF_P7_LIB		[label="nfapi_pnf_p7_subframe_ind", URL="\ref nfapi_pnf_p7_subframe_ind"];
+ *   PNF_P7_LIB note PNF_P7_LIB		[label="Send data from subframe buffer for tti x"];
+ *   PNF_P7_LIB=>PNF_P7_CLIENT		[label="dl_config_req", URL="\ref nfapi_pnf_p7_config::dl_config_req"];
+ *   PNF_P7_CLIENT=>FAPI			[label="dl_config_req"];
+ *   PNF_P7_LIB=>PNF_P7_CLIENT		[label="ul_config_req", URL="\ref nfapi_pnf_p7_config::ul_config_req"];
+ *   PNF_P7_CLIENT=>FAPI			[label="ul_config_req"];
+ *   PNF_P7_LIB=>PNF_P7_CLIENT		[label="hi_dci0_req", URL="\ref nfapi_pnf_p7_config::hi_dci0_req"];
+ *   PNF_P7_CLIENT=>FAPI			[label="hi_dci0_req"];
+ *   PNF_P7_LIB=>PNF_P7_CLIENT		[label="tx_req", URL="\ref nfapi_pnf_p7_config::tx_req"];
+ *   PNF_P7_CLIENT=>FAPI			[label="tx_req"];
+ *   ---;
+ *
+ * \endmsc
+ *
+ * \section seq_diag_bca BCA
+ *
+ * -#	The VNF_P5_CLIENT is created. If it left to the VRAN partner to define how that is done. The client is responsiable to creation of the thread with the correct priorities within the wider system.
+ * -#	The VNF_P5_CLIENT creates and initializes the VNF_P5_LIB (nfapi_vnf_config_create & nfapi_vnf_start) providing the address that it should listen on for incoming SCTP connections. It is expected that this would be provided by some VNF management system. The VNF_P5_CLIENT also provides information on the callbacks that the VNF_P5_LIB will use to inform the VNF_P5_CLIENT of the received messages
+ * \code
+ * nfapi_vnf_config_t* vnf_config = nfapi_vnf_config_create();
+ * vnf_config->pnf_connection_indication = &pnf_connection_indication;
+ * vnf_config->pnf_param_resp = &pnf_param_resp;
+ * nfapi_vnf_start(vnf_config);
+ * \endcode
+ * -#	It is FFS how the address information of the VNF P5 is passed to the PNF over P9, but assuming that has been done
+ * -#	The PNF_P5_CLIENT is created and then creates the PNF_P5_LIB (nfapi_pnf_init & nfapi_pnf_start) passing the address of the VNF to connect to. The PNF_P5_CLIENT also provides information on the callbacks that the PNF_P5_LIB will use to inform the PNF_P5_CLIENT of the received messages
+ * \code
+ * nfapi_pnf_config_t* pnf_config = nfapi_pnf_config_create();
+ * pnf_config->pnf_param_req = &pnf_param_req;
+ * nfapi_pnf_start(pnf_config);
+ * \endcode
+ * -#	The PNF_P5_LIB attempts to establish connection to the VNF_P5 endpoint
+ * -#	The VNF_P5_LIB receives the STCP connection request and indicates this to the VNF_P5_CLIENT (pnf_connection_indication). The VNF_P5_CLIENT can decide to accept or reject the connection.
+  * \code
+ * int pnf_connection_indication(nfapi_vnf_config_t* config, int p5_idx) {
+ *   // send the PNF_PARAM.request
+ *   nfapi_pnf_param_request_t req;
+ *   memset(&req, 0, sizeof(req));
+ *   req.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+ *   nfapi_vnf_pnf_param_req(config, p5_idx, req);
+ *   return 0;
+ * }
+ * \endcode
+
+ * -#	The VNF and PNF then proceed to exchange the NFAPI PNF messages (PNF_PARAM, PNF_CONFIG and PNF_START). At each stage the LIB’s invoke callbacks on the CLIENT’s for them to handle message the return the appropriate response. 
+ * -#	Finally the VNF will send the PNF_START.req which will invoke the PNF_P5_CLIENT nfapi_pnf_start_request callback. This is the point at which it is expect that the PNF_CLIENT will create the FAPI module. The PNF_P5_CLIENT will need to perform the translation between NFAPI structures and vendor specific FAPI structures for messages sent between the PNF_P5_LIB and the FAPI interface.
+ * -#	The PNF_START.response will sent back to the VNF and at this point the VNF_P5_CLIENT will need to decide which VNF_P7 instance will handle the P7 connection. i.e. it needs to determine the IP address and port number of the P7 VNF instance. 
+ * -#	A new VNF_P7_CLIENT & VNF_P7_LIB should be configured and started if necessary.
+ * -#	The VNF_P5 will then send the PARAM.request to the PNF_P5 which will forward it onto the FAPI interface. This PARAM.request includes the VNF_P7 address. The PNF_P7_CLIENT must decide on the PNF P7 address. This information is used to create and initialize the PNF_P7_LIB. The PNF_P7 address is then returned by the PNF_P5 to the VNF_P5 in the PARAM.response.
+ * -#	The VNF_P5 will then exchange with the PNF_P5 the CONFIG.request/response which will be used to configure the PNF FAPI instance.
+ * -#	The VNF_P5 will then decide to start the PNF_P7 by sending the START.request.
+ * -#	The PNF_P5_CLIENT need to send the start request to the FAPI instance. The response which is the start of subframe indications from the FAPI. In receipt of the first subframe indication the PNF_P5_CLIENT will send the START.response to the VNF_P5 via the PNF_P5_LIB
+ * -#	The FAPI subframe indications should be forwarded to the PNF_P7_LIB by the PNF_P7_CLIENT. Until the VNF_P7 instance has sent the subframe configuration messages (dl_config, ul_config, etc) the PNF_P7_LIB will send ‘dummy’ subframe configuration messages. The contents of which are configurable by the PNF_P7_CLIENT.
+ * -#	When the VNF_P5_CLIENT receives the START.response it will need to ‘communicate’ with the VNF_P7_CLIENT to inform it that the PNF_P7 instance has started. The VNF_P7_CLIENT will call the nfapi_vnf_P7_add_pnf function passing the address details of the PNF_P7 instance.
+ * -#	The VNF_P7_LIB will then start the sync procedure to establish sub frame synchronization between the PNF_P7 and VNF_P7 instances. This involves sending the DL_NODE_SYNC and UL_NODE_SYNC to determine network latency and PNF processing latency to be able to request MAC generate sub frames in advance on when they are required by the FAPI interface.
+ * -#	When sync is achieved the VNF_P7_LIB will send the nfapi_sync_indication to the VNF_P7_CLIENT. 
+ * -#	The VNF_P7_LIB will then start issuing sub frame indications to the VNF_P7_CLIENT. The logical intent is that they indications are sent every millisecond. However due to the scheduling jitter that may be seen by the VNF these subframe indications may be less than or more than 1ms apart. How this is handled is one of the critical functions of the VNF_P7_LIB and may require specialization or requirements on the VNF environment i.e. CPU pinning.
+ * -#	The VNF_P7_LIB will send the subframe_indication to the VNF_P7_CLIENT for ‘x’ subframe’s inadvance of the current TTI at the PNF. The delta ‘x’ will be determined by the sync procedure and how far in advance the FAPI needs to receive messages before RF transmission. 
+ * -#	The VNF_P7_CLIENT is then responsible for communicating to the MAC layer to prepare the dl_config_request, ul_config_request, hi_dci0_request, tx_req in a timely manner and sending them to the VNF_P7_LIB
+ * -#	The VNF_P7_LIB will send them to the VNF_P7_LIB. 
+ * -#	The PNF_P7_LIB will store these messages in a subframe buffer or playout buffer in advance of when they are required by FAPI.
+ *  -#	The PNF_P7_LIB will monitor to see if these messages arrive too late and if they do trigger a TIMING_INFO response to the VNF_P7_LIB to reassess if the sync is still valid.
+ * -#	As some time in the future the FAPI will send a subframe indication for the TTI that the VNF_P7_LIB had previously requested.
+ * -#	The PNF_P7_LIB will then use the messages in the subframe buffer and send them too the FAPI interface for transmission. The PNF_P7_CLIENT will need to perform the translation between NFAPI structure and vendor specific FAPI structures
+ * -#	This subframe exchange will continue and allow high layer MAC and RRC function to bringup the cell and connect UE’s
+
+ */
diff --git a/nfapi/open-nFAPI/integration_tests/Makefile.am b/nfapi/open-nFAPI/integration_tests/Makefile.am
new file mode 100644
index 0000000000..2413590182
--- /dev/null
+++ b/nfapi/open-nFAPI/integration_tests/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+#vnf unit test
+AM_CPPFLAGS = -I../nfapi/inc -I../nfapi/public_inc  -I../common/public_inc -I../vnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
+
+export LD_LIBRARY_PATH=/opt/gcc-4.7.3/lib
+check_PROGRAMS= nfapi_integration_tests
+nfapi_integration_tests_SOURCES = main.cpp ../common/src/debug.c   
+nfapi_integration_tests_LDADD= -L$(libdir) -lpthread -lrt  -lcunit
+
+
+
+LOG_DRIVER = $(top_srcdir)/tap-driver.sh
+TESTS=nfapi_integration_tests
+EXTRA_DIST=$(TESTS)
diff --git a/nfapi/open-nFAPI/integration_tests/main.cpp b/nfapi/open-nFAPI/integration_tests/main.cpp
new file mode 100644
index 0000000000..83c48afec3
--- /dev/null
+++ b/nfapi/open-nFAPI/integration_tests/main.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "CUnit.h"
+#include "Basic.h"
+#include "Automated.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int start_vnf_proc(int port)
+{
+	char port_str[10];
+	sprintf(port_str, "%d", port);
+
+	const char *argv[]  = {"vnfsim", port_str, "../xml/vnf_A.xml", NULL};
+	int pid = fork();
+
+	if(pid == 0)
+	{
+		int result = execv("../vnf_sim/vnfsim", (char* const*)argv); //, env_args);
+		if(result == -1)
+		{
+			printf("Failed to exec vnf process %d\n", errno);
+		}
+		exit(0);
+	}
+	else
+	{
+		return pid;
+	}
+}
+
+int start_pnf_proc(const char* addr, int port, const char* file)
+{
+	char port_str[10];
+	sprintf(port_str, "%d", port);
+
+	char filename[256];
+	sprintf(filename, "../xml/%s", file);
+
+	const char * argv[] = {"pnfsim", addr, port_str, filename, NULL};
+	int pid = fork();
+
+	if(pid == 0)
+	{
+		int result = execv("../pnf_sim/pnfsim", (char* const*)argv); //, env_args);
+		if(result == -1)
+		{
+			printf("Failed to exec pnf process %d\n", errno);
+		}
+		exit(0);
+	}
+	else
+	{
+		return pid;
+	}
+}
+
+int kill_proc(int pid)
+{
+	kill(pid, SIGKILL);
+
+	int status;
+	int waitpid_result = waitpid(pid, &status, 0);
+
+	return waitpid_result;
+}
+
+
+void test_1()
+{
+
+	int pnf_port = 5655;
+	const char* pnf_addr = "localhost";
+
+	printf("**** starting vnf *****\n");
+	int vnf_pid = start_vnf_proc(pnf_port);
+
+	printf("**** starting pnf *****\n");
+	int pnf1_pid = start_pnf_proc(pnf_addr, pnf_port, "pnf_phy_1_A.xml");
+
+
+	sleep(10);
+
+	printf ("*** Terminating ****\n");
+	kill_proc(vnf_pid);
+	kill_proc(pnf1_pid);
+}
+void test_1a()
+{
+
+	int pnf_port = 5655;
+	const char* pnf_addr = "localhost";
+
+	printf("**** starting vnf *****\n");
+	int vnf_pid = start_vnf_proc(pnf_port);
+
+	printf("**** starting pnf *****\n");
+	int pnf1_pid = start_pnf_proc(pnf_addr, pnf_port, "pnf_phy_2_A.xml");
+
+
+	sleep(10);
+
+	printf ("*** Terminating ****\n");
+	kill_proc(vnf_pid);
+	kill_proc(pnf1_pid);
+}
+
+
+void test_2()
+{
+	int pnf_port = 5655;
+	const char* pnf_addr = "127.0.0.1";
+
+	int vnf_pid = start_vnf_proc(pnf_port);
+	sleep(2);
+
+	int pnf1_pid = start_pnf_proc(pnf_addr, pnf_port, "pnf_phy_1_A.xml");	
+	int pnf2_pid = start_pnf_proc(pnf_addr, pnf_port, "pnf_phy_1_A.xml");	
+
+	sleep(2);
+
+	kill_proc(pnf2_pid);
+	kill_proc(pnf1_pid);
+	kill_proc(vnf_pid);
+}
+
+void test_32()
+{
+	int pnf_count = 32;
+	int pnf_pid[pnf_count];
+
+	int pnf_port = 5655;
+	const char* pnf_addr = "127.0.0.1";
+
+	int vnf_pid = start_vnf_proc(pnf_port);
+	sleep(2);
+
+	for(int i = 0; i < pnf_count; ++i)
+	{
+		pnf_pid[i] = start_pnf_proc(pnf_addr, pnf_port, "pnf_phy_1_A.xml");
+	}
+
+	sleep(5);
+
+	printf ("*** Terminating pnfs\n");
+
+	for(int i = 0; i < pnf_count; ++i)
+	{
+		kill_proc(pnf_pid[i]);
+	}
+	printf ("*** Terminating vnf\n");
+	kill_proc(vnf_pid);
+}
+
+
+int init_suite()
+{
+	return 0;
+}
+
+int clean_suite()
+{
+	return 0;
+}
+
+int main ( void )
+{
+   CU_pSuite pSuite = NULL;
+
+   /* initialize the CUnit test registry */
+   if ( CUE_SUCCESS != CU_initialize_registry() )
+      return CU_get_error();
+
+   /* add a suite to the registry */
+   pSuite = CU_add_suite( "integration_test_suite", init_suite, clean_suite );
+   if ( NULL == pSuite ) 
+   {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+        //(NULL == CU_add_test(pSuite, "vnf_test_start_connect_2", vnf_test_start_connect_2)) 
+   /* add the tests to the suite */
+   if ( (NULL == CU_add_test(pSuite, "test_1a", test_1a))
+//        (NULL == CU_add_test(pSuite, "test_2", test_2)) ||
+//        (NULL == CU_add_test(pSuite, "test_32", test_32))
+      )
+   {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+   // Run all tests using the basic interface
+   CU_basic_set_mode(CU_BRM_VERBOSE);
+   CU_set_output_filename("vnf_unit_test_results.xml");
+   CU_basic_run_tests();
+
+	CU_pSuite s = CU_get_registry()->pSuite;
+	int count = 0;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+	printf("%d..%d\n", 1, count);
+
+
+
+	s = CU_get_registry()->pSuite;
+	count = 1;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			int pass = 1;
+			CU_FailureRecord* failures = CU_get_failure_list();
+			while(failures)
+			{
+				if(strcmp(failures->pSuite->pName, s->pName) == 0 &&
+				   strcmp(failures->pTest->pName, t->pName) == 0)
+				{
+					pass = 0;
+					failures = 0;
+				}
+				else
+				{
+					failures = failures->pNext;
+				}
+			}
+
+			if(pass)
+				printf("ok %d - %s:%s\n", count, s->pName, t->pName);
+			else 
+				printf("not ok %d - %s:%s\n", count, s->pName, t->pName);
+
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+   CU_cleanup_registry();
+   return CU_get_error();
+
+}
diff --git a/nfapi/open-nFAPI/nfapi/Makefile.am b/nfapi/open-nFAPI/nfapi/Makefile.am
new file mode 100644
index 0000000000..853ee9ff80
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/Makefile.am
@@ -0,0 +1,30 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AUTOMAKE_OPTIONS=subdir-objects
+AM_CPPFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc  -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/pnf/public_inc  $(BOOST_CPPFLAGS) -Wall -Werror -g
+
+noinst_LIBRARIES = libnfapi.a
+
+libnfapi_a_SOURCES = src/nfapi.c  src/nfapi_p5.c  src/nfapi_p7.c src/nfapi_p4.c
+libnfapi_a_CFLAGS =$(AM_CFLAGS)
+
+lib_LTLIBRARIES = libnfapi.la
+libnfapi_la_SOURCES =  src/nfapi.c  src/nfapi_p5.c  src/nfapi_p7.c src/nfapi_p4.c
+
+
+LDADD= ../pnf/src/libnfapi_pnf.a ../vnf/src/libnfapi_vnf.a ../common/bin/libnfapi_common.a 
+
diff --git a/nfapi/open-nFAPI/nfapi/inc/nfapi.h b/nfapi/open-nFAPI/nfapi/inc/nfapi.h
new file mode 100644
index 0000000000..65ad4dd160
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/inc/nfapi.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _NFAPI_H_
+#define _NFAPI_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// todo : move to public_inc so can be used by vendor extensions
+
+#define MAX_BAD_TAG 3
+
+uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end);
+uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end);
+uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end);
+uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end);
+uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end);
+uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end);
+
+uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end);
+uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end);
+uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end);
+uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end);
+uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end);
+uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end);
+
+
+uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
+uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
+uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end);
+
+uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
+uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
+uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end);
+
+typedef uint8_t (*pack_array_elem_fn)(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t packarray(void* array, uint16_t elem_size, uint16_t max_count, uint16_t count, uint8_t **ppWritePackedMsg, uint8_t *end, pack_array_elem_fn fn);
+
+typedef uint8_t (*unpack_array_elem_fn)(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end);
+uint8_t unpackarray(uint8_t **ppReadPackedMsg, void* array, uint16_t elem_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn);
+
+uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end);
+
+typedef uint8_t (*pack_tlv_fn)(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn);
+
+uint32_t pack_vendor_extension_tlv(nfapi_tl_t* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config);
+int unpack_vendor_extension(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve_tlv);
+
+typedef uint8_t (*unpack_tlv_fn)(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+typedef struct
+{
+	uint16_t tag;
+	void* tlv;
+	unpack_tlv_fn unpack_func;
+} unpack_tlv_t;
+
+int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* packedMsgEnd, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve);
+
+uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config);
+typedef uint8_t (*unpack_p7_tlv_fn)(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t*);
+typedef struct
+{
+	uint16_t tag;
+	void* tlv;
+	unpack_p7_tlv_fn unpack_func;
+} unpack_p7_tlv_t;
+int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* packedMsgEnd, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _NFAPI_H_ */
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
new file mode 100644
index 0000000000..f665d11c89
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
@@ -0,0 +1,3855 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _NFAPI_INTERFACE_H_
+#define _NFAPI_INTERFACE_H_
+
+#include "stddef.h"
+
+// Constants - update based on implementation
+#define NFAPI_MAX_PHY_RF_INSTANCES 2
+#define NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH 16
+#define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3
+#define NFAPI_MAX_NUM_RF_BANDS 16
+
+// The following definition control the size of arrays used in the interface.
+// These may be changed if desired. They are used in the encoder to make sure 
+// that the user has not specified a 'count' larger than the max array, and also
+// used by the decoder when decode an array. If the 'count' received is larger
+// than the array it is to be stored in the decode fails. 
+#define NFAPI_MAX_NUM_ANTENNAS 8
+#define NFAPI_MAX_NUM_SUBBANDS 13
+#define NFAPI_MAX_BF_VECTORS 8
+#define NFAPI_MAX_CC 1
+#define NFAPI_MAX_NUM_PHYSICAL_ANTENNAS 8
+#define NFAPI_MAX_RSSI 8
+#define NFAPI_MAX_PSC_LIST 32
+#define NFAPI_MAX_PCI_LIST 32
+#define NFAPI_MAX_CARRIER_LIST 32
+#define NFAPI_MAX_ARFCN_LIST 128
+#define NFAPI_MAX_LTE_CELLS_FOUND 8
+#define NFAPI_MAX_UTRAN_CELLS_FOUND 8
+#define NFAPI_MAX_GSM_CELLS_FOUND 8
+#define NFAPI_MAX_NB_IOT_CELLS_FOUND 8
+#define NFAPI_MAX_SI_PERIODICITY 8
+#define NFAPI_MAX_SI_INDEX 8
+#define NFAPI_MAX_MIB_LENGTH 32
+#define NFAPI_MAX_SIB_LENGTH 256
+#define NFAPI_MAX_SI_LENGTH 256
+#define NFAPI_MAX_OPAQUE_DATA 64
+#define NFAPI_MAX_NUM_SCHEDULED_UES 8 // Used in the TPM structure
+#define NFAPI_MAX_PNF_PHY 5
+#define NFAPI_MAX_PNF_PHY_RF_CONFIG 5
+#define NFAPI_MAX_PNF_RF  5
+#define NFAPI_MAX_NMM_FREQUENCY_BANDS 32
+#define NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS 100
+#define NFAPI_MAX_UL_DL_CONFIGURATIONS 5
+#define NFAPI_MAX_CSI_RS_RESOURCE_CONFIG 4
+#define NFAPI_MAX_ANTENNA_PORT_COUNT 8
+#define NFAPI_MAX_EPDCCH_PRB 8
+#define NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS 8
+#define NFAPI_MAX_NUMBER_ACK_NACK_TDD 8
+#define NFAPI_MAX_RO_DL 8
+
+#define NFAPI_HEADER_LENGTH 8
+#define NFAPI_P7_HEADER_LENGTH 16
+
+#define NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE 0xF000
+#define NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE 0xFFFF
+
+#define NFAPI_VERSION_3_0_11	0x000
+#define NFAPI_VERSION_3_0_12    0x001
+
+// The IANA agreed port definition of the P5 SCTP VNF enpoint 
+// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=7701
+#define NFAPI_P5_SCTP_PORT		7701
+
+typedef unsigned int	uint32_t;
+typedef unsigned short	uint16_t;
+typedef unsigned char	uint8_t;
+typedef signed int		int32_t;
+typedef signed short	int16_t;
+typedef signed char		int8_t;
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t message_id;
+	uint16_t message_length;
+	uint16_t spare;
+} nfapi_p4_p5_message_header_t;
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t message_id;
+	uint16_t message_length;
+	uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/
+	uint32_t checksum;
+	uint32_t transmit_timestamp;
+} nfapi_p7_message_header_t;
+
+#define NFAPI_PHY_ID_NA 0
+
+//#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x80) >> 7 )
+//#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x70) >> 4 )
+#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x8000) >> 15 )
+#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x7F00) >> 8 )
+#define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF )
+#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) )
+
+typedef struct {
+	uint16_t tag;
+	uint16_t length;
+} nfapi_tl_t;
+#define NFAPI_TAG_LENGTH_PACKED_LEN 4
+
+// Convenience methods to convert between SFN/SFN formats
+#define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF))
+#define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF))
+
+#define NFAPI_SFNSF2SFN(_sfnsf) ((_sfnsf) >> 4)
+#define NFAPI_SFNSF2SF(_sfnsf) ((_sfnsf) & 0xF)
+
+#define NFAPI_MAX_SFNSFDEC 10240
+
+typedef nfapi_tl_t* nfapi_vendor_extension_tlv_t;
+
+
+// nFAPI Message IDs
+typedef enum {
+	NFAPI_DL_CONFIG_REQUEST = 0x0080,
+	NFAPI_UL_CONFIG_REQUEST,
+	NFAPI_SUBFRAME_INDICATION,
+	NFAPI_HI_DCI0_REQUEST,
+	NFAPI_TX_REQUEST,
+	NFAPI_HARQ_INDICATION,
+	NFAPI_CRC_INDICATION,
+	NFAPI_RX_ULSCH_INDICATION,
+	NFAPI_RACH_INDICATION,
+	NFAPI_SRS_INDICATION,
+	NFAPI_RX_SR_INDICATION,
+	NFAPI_RX_CQI_INDICATION,
+	NFAPI_LBT_DL_CONFIG_REQUEST,
+	NFAPI_LBT_DL_INDICATION,
+	NFAPI_NB_HARQ_INDICATION,
+	NFAPI_NRACH_INDICATION,
+
+	NFAPI_PNF_PARAM_REQUEST = 0x0100,
+	NFAPI_PNF_PARAM_RESPONSE,
+	NFAPI_PNF_CONFIG_REQUEST,
+	NFAPI_PNF_CONFIG_RESPONSE,
+	NFAPI_PNF_START_REQUEST,
+	NFAPI_PNF_START_RESPONSE,
+	NFAPI_PNF_STOP_REQUEST,
+	NFAPI_PNF_STOP_RESPONSE,
+	NFAPI_PARAM_REQUEST,
+	NFAPI_PARAM_RESPONSE,
+	NFAPI_CONFIG_REQUEST,
+	NFAPI_CONFIG_RESPONSE,
+	NFAPI_START_REQUEST,
+	NFAPI_START_RESPONSE,
+	NFAPI_STOP_REQUEST,
+	NFAPI_STOP_RESPONSE,
+	NFAPI_MEASUREMENT_REQUEST,
+	NFAPI_MEASUREMENT_RESPONSE,
+
+	NFAPI_UL_NODE_SYNC = 0x0180,
+	NFAPI_DL_NODE_SYNC,
+	NFAPI_TIMING_INFO,
+
+
+	NFAPI_RSSI_REQUEST = 0x0200,
+	NFAPI_RSSI_RESPONSE,
+	NFAPI_RSSI_INDICATION,
+	NFAPI_CELL_SEARCH_REQUEST,
+	NFAPI_CELL_SEARCH_RESPONSE,
+	NFAPI_CELL_SEARCH_INDICATION,
+	NFAPI_BROADCAST_DETECT_REQUEST,
+	NFAPI_BROADCAST_DETECT_RESPONSE,
+	NFAPI_BROADCAST_DETECT_INDICATION,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION,
+	NFAPI_SYSTEM_INFORMATION_REQUEST,
+	NFAPI_SYSTEM_INFORMATION_RESPONSE,
+	NFAPI_SYSTEM_INFORMATION_INDICATION,
+	NFAPI_NMM_STOP_REQUEST,
+	NFAPI_NMM_STOP_RESPONSE,
+
+	NFAPI_VENDOR_EXT_MSG_MIN = 0x0300,
+	NFAPI_VENDOR_EXT_MSG_MAX = 0x03FF,
+
+
+	NFAPI_MAX_MESSAGE_ID,
+} nfapi_message_id_e;
+
+// nFAPI Error Codes
+typedef enum {
+	NFAPI_MSG_OK = 0,
+	NFAPI_MSG_INVALID_STATE,
+	NFAPI_MSG_INVALID_CONFIG,
+	NFAPI_SFN_OUT_OF_SYNC,
+	NFAPI_MSG_SUBFRAME_ERR,
+	NFAPI_MSG_BCH_MISSING,
+	NFAPI_MSG_INVALID_SFN,
+	NFAPI_MSG_HI_ERR,
+	NFAPI_MSG_TX_ERR,
+	
+	NFAPI_LBT_NO_PDU_IN_DL_REQ,
+	NFAPI_LBT_NO_VALID_CONFIG_REQ_RECEIVED,
+	NFAPI_FAPI_E_LBT_SF_SFN_PASSED_END_SF_SFN,
+	NFAPI_FAPI_E_LBT_OVERLAP,
+	NFAPI_MSG_BCH_PRESENT,
+	
+	NFAPI_NBIOT_UNEXPECTED_REQ,
+
+	// This is special return code that indicates that a response has
+	// been send via P9
+	NFAPI_MSG_P9_RESPONSE = 0xAA
+} nfapi_error_code_e;
+
+
+typedef enum {
+	NFAPI_P4_MSG_OK = 100,
+	NFAPI_P4_MSG_INVALID_STATE = 101,
+	NFAPI_P4_MSG_INVALID_CONFIG = 102,
+	NFAPI_P4_MSG_RAT_NOT_SUPPORTED = 103,
+	NFAPI_P4_MSG_NMM_STOP_OK = 200,
+	NFAPI_P4_MSG_NMM_STOP_IGNOREDED = 201,
+	NFAPI_P4_MSG_NMM_STOP_INVALID_STATE = 202,
+	NFAPI_P4_MSG_PROCEDURE_COMPLETE = 300,
+	NFAPI_P4_MSG_PROCEDURE_STOPPED = 301,
+	NFAPI_P4_MSG_PARTIAL_RESULTS = 302,
+	NFAPI_P4_MSG_TIMEOUT = 303
+} nfapi_p4_error_code_e;
+
+// nFAPI enums
+typedef enum {
+	NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE = 0,
+	NFAPI_DL_CONFIG_BCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_MCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_DLSCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_PCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_PRS_PDU_TYPE,
+	NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE,
+	NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE,
+	NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NBCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE
+} nfapi_dl_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_DL_DCI_FORMAT_1 = 0,
+	NFAPI_DL_DCI_FORMAT_1A,
+	NFAPI_DL_DCI_FORMAT_1B,
+	NFAPI_DL_DCI_FORMAT_1C,
+	NFAPI_DL_DCI_FORMAT_1D,
+	NFAPI_DL_DCI_FORMAT_2,
+	NFAPI_DL_DCI_FORMAT_2A,
+	NFAPI_DL_DCI_FORMAT_2B,
+	NFAPI_DL_DCI_FORMAT_2C
+} nfapi_dl_dci_format_e;
+
+typedef enum {
+	NFAPI_UL_DCI_FORMAT_0 = 0,
+	NFAPI_UL_DCI_FORMAT_3,
+	NFAPI_UL_DCI_FORMAT_3A,
+	NFAPI_UL_DCI_FORMAT_4
+} nfapi_ul_dci_format_e;
+
+typedef enum {
+	NFAPI_UL_CONFIG_ULSCH_PDU_TYPE = 0,
+	NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_SRS_PDU_TYPE,
+	NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_NULSCH_PDU_TYPE,
+	NFAPI_UL_CONFIG_NRACH_PDU_TYPE,
+} nfapi_ul_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_HI_DCI0_HI_PDU_TYPE = 0,
+	NFAPI_HI_DCI0_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE,
+} nfapi_hi_dci0_pdu_type_e;
+
+typedef enum {
+	NFAPI_HARQ_ACK = 1,
+	NFAPI_HARQ_NACK,
+	NFAPI_HARQ_ACK_OR_NACK,
+	NFAPI_HARQ_DTX,
+	NFAPI_HARQ_ACK_OR_DTX,
+	NFAPI_HARQ_NACK_OR_DTX,
+	NFAPI_HARQ_ACK_OR_NACK_OR_DTX
+} nfapi_harq_type_e;
+
+typedef enum {
+	NFAPI_CSI_REPORT_TYPE_PERIODIC = 0,
+	NFAPI_CSI_REPORT_TYPE_APERIODIC
+} nfapi_csi_report_type_e;
+
+typedef enum {
+	NFAPI_DL_BW_SUPPORTED_6 = 1,
+	NFAPI_DL_BW_SUPPORTED_15 = 2,
+	NFAPI_DL_BW_SUPPORTED_25 = 4,
+	NFAPI_DL_BW_SUPPORTED_50 = 8,
+	NFAPI_DL_BW_SUPPORTED_75 = 16,
+	NFAPI_DL_BW_SUPPORTED_100 = 32
+} nfapi_dl_bandwith_supported_e;
+
+typedef enum {
+	NFAPI_UL_BW_SUPPORTED_6 = 1,
+	NFAPI_UL_BW_SUPPORTED_15 = 2,
+	NFAPI_UL_BW_SUPPORTED_25 = 4,
+	NFAPI_UL_BW_SUPPORTED_50 = 8,
+	NFAPI_UL_BW_SUPPORTED_75 = 16,
+	NFAPI_UL_BW_SUPPORTED_100 = 32
+} nfapi_ul_bandwith_supported_e;
+
+typedef enum {
+	NFAPI_3GPP_REL_SUPPORTED_8 = 0,
+	NFAPI_3GPP_REL_SUPPORTED_9 = 1,
+	NFAPI_3GPP_REL_SUPPORTED_10 = 2,
+	NFAPI_3GPP_REL_SUPPORTED_11 = 4,
+	NFAPI_3GPP_REL_SUPPORTED_12 = 8
+} nfapi_3gpp_release_supported_e;
+
+
+typedef enum {
+	NFAPI_DUPLEXING_MODE_TDD = 0,
+	NFAPI_DUPLEXING_MODE_FDD = 1,
+	NFAPI_DUPLEXING_MODE_HD_FDD = 2,
+} nfapi_duplexing_mode_e;
+
+typedef enum {
+	NFAPI_CP_NORMAL = 0,
+	NFAPI_CP_EXTENDED = 1
+} nfapi_cyclic_prefix_type_e;
+
+typedef enum {
+	NFAPI_RAT_TYPE_LTE = 0,
+	NFAPI_RAT_TYPE_UTRAN = 1,
+	NFAPI_RAT_TYPE_GERAN = 2,
+	NFAPI_RAT_TYPE_NB_IOT = 3
+} nfapi_rat_type_e;
+
+typedef enum {
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5
+} nfapi_harq_indication_tdd_ack_nackformat_e;
+
+
+typedef enum {
+	NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE = 0,
+	NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE
+} nfapi_lbt_dl_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE = 0,
+	NFAPI_LBT_DL_RSP_DRS_PDU_TYPE
+} nfapi_lbt_dl_rsp_pdu_type_e;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t length;
+	uint8_t value[NFAPI_MAX_OPAQUE_DATA];
+} nfapi_opaqaue_data_t;
+
+// Utility functions to turn enums into char*
+const char* nfapi_error_code_to_str(nfapi_error_code_e value);
+
+
+// P5 Sub Structures
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nfapi_sync_mode;
+	uint8_t location_mode;
+	uint16_t location_coordinates_length;
+	uint8_t location_coordinates[NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH];
+	uint32_t dl_config_timing;
+	uint32_t tx_timing;
+	uint32_t ul_config_timing;
+	uint32_t hi_dci0_timing;
+	uint16_t maximum_number_phys;
+	uint16_t maximum_total_bandwidth;
+	uint8_t maximum_total_number_dl_layers;
+	uint8_t maximum_total_number_ul_layers;
+	uint8_t shared_bands;
+	uint8_t shared_pa;
+	int16_t maximum_total_power;
+	uint8_t oui[NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH];
+} nfapi_pnf_param_general_t;
+#define NFAPI_PNF_PARAM_GENERAL_TAG 0x1000
+
+
+
+
+
+typedef struct {
+	uint16_t rf_config_index;
+} nfapi_rf_config_info_t;
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t number_of_rfs;
+	nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t number_of_rf_exclusions;
+	nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t downlink_channel_bandwidth_supported;
+	uint16_t uplink_channel_bandwidth_supported;
+	uint8_t number_of_dl_layers_supported;
+	uint8_t number_of_ul_layers_supported;
+	uint16_t maximum_3gpp_release_supported;
+	uint8_t nmm_modes_supported;
+} nfapi_pnf_phy_info_t;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_t;
+#define NFAPI_PNF_PHY_TAG 0x1001
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t transmission_mode_7_supported;
+	uint16_t transmission_mode_8_supported;
+	uint16_t two_antenna_ports_for_pucch;
+	uint16_t transmission_mode_9_supported;
+	uint16_t simultaneous_pucch_pusch;
+	uint16_t four_layer_tx_with_tm3_and_tm4;
+} nfapi_pnf_phy_rel10_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel10_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel10_t;
+#define NFAPI_PNF_PHY_REL10_TAG 0x100A
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t edpcch_supported;
+	uint16_t multi_ack_csi_reporting;
+	uint16_t pucch_tx_diversity;
+	uint16_t ul_comp_supported;
+	uint16_t transmission_mode_5_supported;
+} nfapi_pnf_phy_rel11_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel11_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel11_t;
+#define NFAPI_PNF_PHY_REL11_TAG 0x100B
+
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t csi_subframe_set;
+	uint16_t enhanced_4tx_codebook;
+	uint16_t drs_supported;
+	uint16_t ul_64qam_supported;
+	uint16_t transmission_mode_10_supported;
+	uint16_t alternative_bts_indices;
+} nfapi_pnf_phy_rel12_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel12_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel12_t;
+#define NFAPI_PNF_PHY_REL12_TAG 0x100C
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t pucch_format4_supported;
+	uint16_t pucch_format5_supported;
+	uint16_t more_than_5_ca_support;
+	uint16_t laa_supported;
+	uint16_t laa_ending_in_dwpts_supported;
+	uint16_t laa_starting_in_second_slot_supported;
+	uint16_t beamforming_supported;
+	uint16_t csi_rs_enhancement_supported;
+	uint16_t drms_enhancement_supported;
+	uint16_t srs_enhancement_supported;
+} nfapi_pnf_phy_rel13_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel13_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel13_t;
+#define NFAPI_PNF_PHY_REL13_TAG 0x100D
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t number_of_rfs;
+	nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t number_of_rf_exclusions;
+	nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint8_t number_of_dl_layers_supported;
+	uint8_t number_of_ul_layers_supported;
+	uint16_t maximum_3gpp_release_supported;
+	uint8_t nmm_modes_supported;
+} nfapi_pnf_phy_rel13_nb_iot_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel13_nb_iot_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel13_nb_iot_t;
+#define NFAPI_PNF_PHY_REL13_NB_IOT_TAG 0x100E
+
+
+
+typedef struct {
+	uint16_t rf_config_index;
+	uint16_t band;
+	int16_t maximum_transmit_power; 
+	int16_t minimum_transmit_power;
+	uint8_t number_of_antennas_suppported;
+	uint32_t minimum_downlink_frequency;
+	uint32_t maximum_downlink_frequency;
+	uint32_t minimum_uplink_frequency;
+	uint32_t maximum_uplink_frequency;
+} nfapi_pnf_rf_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rfs;
+	nfapi_pnf_rf_info_t rf[NFAPI_MAX_PNF_RF];
+} nfapi_pnf_rf_t;
+#define NFAPI_PNF_RF_TAG 0x1002
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t phy_config_index;
+	uint16_t rf_config_index;
+} nfapi_phy_rf_config_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_phy_rf_config_info;
+	nfapi_phy_rf_config_info_t phy_rf_config[NFAPI_MAX_PHY_RF_INSTANCES];
+} nfapi_pnf_phy_rf_config_t;
+#define NFAPI_PNF_PHY_RF_TAG 0x1003
+
+// Generic strucutre for single tlv value.
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t value;
+} nfapi_uint16_tlv_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	int16_t value;
+} nfapi_int16_tlv_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t value;
+} nfapi_uint8_tlv_t;
+
+typedef struct {
+	nfapi_uint16_tlv_t phy_state;
+} nfapi_l1_status;
+
+#define NFAPI_L1_STATUS_PHY_STATE_TAG 0x00FA
+
+typedef struct {
+	nfapi_uint16_tlv_t dl_bandwidth_support;
+	nfapi_uint16_tlv_t ul_bandwidth_support;
+	nfapi_uint16_tlv_t dl_modulation_support;
+	nfapi_uint16_tlv_t ul_modulation_support;
+	nfapi_uint16_tlv_t phy_antenna_capability;
+	nfapi_uint16_tlv_t release_capability;
+	nfapi_uint16_tlv_t mbsfn_capability;
+} nfapi_phy_capabilities_t;
+
+#define NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG 0x00C8
+#define NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG 0x00C9
+#define NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG 0x00CA
+#define NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG 0x00CB
+#define NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG 0x00CC
+#define NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG 0x00CD
+#define NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG 0x00CE
+
+
+typedef struct {
+	nfapi_uint16_tlv_t data_report_mode;
+	nfapi_uint16_tlv_t sfnsf;
+} nfapi_l23_config_t;
+
+
+#define NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG 0x00F0
+#define NFAPI_L23_CONFIG_SFNSF_TAG 0x00F1
+
+typedef struct {
+	nfapi_uint16_tlv_t duplex_mode;
+	nfapi_uint16_tlv_t pcfich_power_offset;
+	nfapi_uint16_tlv_t pb;
+	nfapi_uint16_tlv_t dl_cyclic_prefix_type;
+	nfapi_uint16_tlv_t ul_cyclic_prefix_type;
+} nfapi_subframe_config_t;
+
+#define NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG 0x0001
+#define NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG 0x0002
+#define NFAPI_SUBFRAME_CONFIG_PB_TAG 0x0003
+#define NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG 0x0004
+#define NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG 0x0005
+
+typedef struct {
+	nfapi_uint16_tlv_t dl_channel_bandwidth;
+	nfapi_uint16_tlv_t ul_channel_bandwidth;
+	nfapi_uint16_tlv_t reference_signal_power;
+	nfapi_uint16_tlv_t tx_antenna_ports;
+	nfapi_uint16_tlv_t rx_antenna_ports;
+} nfapi_rf_config_t;
+
+#define NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG 0x000A
+#define NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG 0x000B
+#define NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG 0x000C
+#define NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG 0x000D
+#define NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG 0x000E
+
+typedef struct {
+	nfapi_uint16_tlv_t phich_resource;
+	nfapi_uint16_tlv_t phich_duration;
+	nfapi_uint16_tlv_t phich_power_offset;
+} nfapi_phich_config_t;
+
+#define NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG 0x0014
+#define NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG 0x0015
+#define NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG 0x0016
+
+typedef struct {
+	nfapi_uint16_tlv_t primary_synchronization_signal_epre_eprers;
+	nfapi_uint16_tlv_t secondary_synchronization_signal_epre_eprers;
+	nfapi_uint16_tlv_t physical_cell_id;
+} nfapi_sch_config_t;
+
+#define NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001E
+#define NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001F
+#define NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG 0x0020
+
+typedef struct {
+	nfapi_uint16_tlv_t configuration_index;
+	nfapi_uint16_tlv_t root_sequence_index;
+	nfapi_uint16_tlv_t zero_correlation_zone_configuration;
+	nfapi_uint16_tlv_t high_speed_flag;
+	nfapi_uint16_tlv_t frequency_offset;
+} nfapi_prach_config_t;
+
+#define NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG 0x0028
+#define NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG 0x0029
+#define NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x002A
+#define NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG 0x002B
+#define NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG 0x002C
+
+typedef struct {
+	nfapi_uint16_tlv_t hopping_mode;
+	nfapi_uint16_tlv_t hopping_offset;
+	nfapi_uint16_tlv_t number_of_subbands;
+} nfapi_pusch_config_t;
+
+#define NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG 0x0032
+#define NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG 0x0033
+#define NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG 0x0034
+
+typedef struct {
+	nfapi_uint16_tlv_t delta_pucch_shift;
+	nfapi_uint16_tlv_t n_cqi_rb;
+	nfapi_uint16_tlv_t n_an_cs;
+	nfapi_uint16_tlv_t n1_pucch_an;
+} nfapi_pucch_config_t;
+
+#define NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG 0x003C
+#define NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG 0x003D
+#define NFAPI_PUCCH_CONFIG_N_AN_CS_TAG 0x003E
+#define NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG 0x003F
+
+typedef struct {
+	nfapi_uint16_tlv_t bandwidth_configuration;
+	nfapi_uint16_tlv_t max_up_pts;
+	nfapi_uint16_tlv_t srs_subframe_configuration;
+	nfapi_uint16_tlv_t srs_acknack_srs_simultaneous_transmission;
+} nfapi_srs_config_t;
+
+#define NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG 0x0046
+#define NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG 0x0047
+#define NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG 0x0048
+#define NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG 0x0049
+
+typedef struct {
+	nfapi_uint16_tlv_t uplink_rs_hopping;
+	nfapi_uint16_tlv_t group_assignment;
+	nfapi_uint16_tlv_t cyclic_shift_1_for_drms;
+} nfapi_uplink_reference_signal_config_t;
+
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG 0x0050
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG 0x0051
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG 0x0052
+
+
+typedef struct {
+	nfapi_uint16_tlv_t ed_threshold_lbt_pdsch;
+	nfapi_uint16_tlv_t ed_threshold_lbt_drs;
+	nfapi_uint16_tlv_t pd_threshold;
+	nfapi_uint16_tlv_t multi_carrier_type;
+	nfapi_uint16_tlv_t multi_carrier_tx;
+	nfapi_uint16_tlv_t multi_carrier_freeze;
+	nfapi_uint16_tlv_t tx_antenna_ports_drs;
+	nfapi_uint16_tlv_t tx_power_drs;
+} nfapi_laa_config_t;
+
+#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG 0x0064
+#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG 0x0065
+#define NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG 0x0066
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG 0x0067
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG 0x0068
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG 0x0069
+#define NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG 0x006A
+#define NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG 0x006B
+
+typedef struct {
+
+	nfapi_uint16_tlv_t pbch_repetitions_enable_r13;
+	nfapi_uint16_tlv_t prach_catm_root_sequence_index;
+	nfapi_uint16_tlv_t prach_catm_zero_correlation_zone_configuration;
+	nfapi_uint16_tlv_t prach_catm_high_speed_flag;
+	nfapi_uint16_tlv_t prach_ce_level_0_enable;
+	nfapi_uint16_tlv_t prach_ce_level_0_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_0_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_0_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_0_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_0_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_0_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_1_enable;
+	nfapi_uint16_tlv_t prach_ce_level_1_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_1_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_1_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_1_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_1_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_1_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_2_enable;
+	nfapi_uint16_tlv_t prach_ce_level_2_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_2_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_2_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_2_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_2_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_2_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_3_enable;
+	nfapi_uint16_tlv_t prach_ce_level_3_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_3_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_3_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_3_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_3_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_3_hopping_offset;
+	nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodea;
+	nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodeb;
+} nfapi_emtc_config_t;
+
+#define NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG 0x0078
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG 0x0079
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x007A
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG 0x007B
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG 0x007C
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG 0x007D
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG 0x007E
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x007F
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG 0x0080
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG 0x0081
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG 0x0082
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG 0x0083
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG 0x0084
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG 0x0085
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0086
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG 0x0087
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG 0x0088
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG 0x0089
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG 0x008A
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG 0x008B
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG 0x008C
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x008D
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG 0x008E
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG 0x008F
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG 0x0090
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG 0x0091
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG 0x0092
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG 0x0093
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0094
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG 0x0095
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG 0x0096
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG 0x0097
+#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG 0x0098
+#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG 0x0099
+
+typedef struct {
+	nfapi_uint16_tlv_t operating_mode;
+	nfapi_uint16_tlv_t anchor;
+	nfapi_uint16_tlv_t prb_index;
+	nfapi_uint16_tlv_t control_region_size;
+	nfapi_uint16_tlv_t assumed_crs_aps;
+	nfapi_uint16_tlv_t nprach_config_0_enabled;
+	nfapi_uint16_tlv_t nprach_config_0_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_0_start_time;
+	nfapi_uint16_tlv_t nprach_config_0_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_0_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_0_cp_length;
+	nfapi_uint16_tlv_t nprach_config_0_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t nprach_config_1_enabled;
+	nfapi_uint16_tlv_t nprach_config_1_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_1_start_time;
+	nfapi_uint16_tlv_t nprach_config_1_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_1_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_1_cp_length;
+	nfapi_uint16_tlv_t nprach_config_1_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t nprach_config_2_enabled;
+	nfapi_uint16_tlv_t nprach_config_2_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_2_start_time;
+	nfapi_uint16_tlv_t nprach_config_2_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_2_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_2_cp_length;
+	nfapi_uint16_tlv_t nprach_config_2_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t three_tone_base_sequence;
+	nfapi_uint16_tlv_t six_tone_base_sequence;
+	nfapi_uint16_tlv_t twelve_tone_base_sequence;
+	nfapi_uint16_tlv_t three_tone_cyclic_shift;
+	nfapi_uint16_tlv_t six_tone_cyclic_shift;
+	nfapi_uint16_tlv_t dl_gap_config_enable;
+	nfapi_uint16_tlv_t dl_gap_threshold;
+	nfapi_uint16_tlv_t dl_gap_periodicity;
+	nfapi_uint16_tlv_t dl_gap_duration_coefficient;
+} nfapi_nb_iot_config_t;
+
+#define NFAPI_NB_IOT_CONFIG_OPERATING_MODE_TAG 0x00A5
+#define NFAPI_NB_IOT_CONFIG_ANCHOR_TAG 0x00A6
+#define NFAPI_NB_IOT_CONFIG_PRB_INDEX_TAG 0x00A7
+#define NFAPI_NB_IOT_CONFIG_CONTROL_REGION_SIZE_TAG 0x00A8
+#define NFAPI_NB_IOT_CONFIG_ASSUMED_CRS_APS_TAG 0x00A9
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_ENABLED_TAG 0x00AA
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SF_PERIODICITY_TAG 0x00AB
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_START_TIME_TAG 0x00AC
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SUBCARRIER_OFFSET_TAG 0x00AD
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_SUBCARRIERS_TAG 0x00AE
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_CP_LENGTH_TAG 0x00AF
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B0
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_ENABLED_TAG 0x00B1
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SF_PERIODICITY_TAG 0x00B2
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_START_TIME_TAG 0x00B3
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SUBCARRIER_OFFSET_TAG 0x00B4
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_SUBCARRIERS_TAG 0x00B5
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_CP_LENGTH_TAG 0x00B6
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B7
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_ENABLED_TAG 0x00B8
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SF_PERIODICITY_TAG 0x00B9
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_START_TIME_TAG 0x00BA
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SUBCARRIER_OFFSET_TAG 0x00BB
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_SUBCARRIERS_TAG 0x00BC
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_CP_LENGTH_TAG 0x00BD
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00BE
+#define NFAPI_NB_IOT_CONFIG_THREE_TONE_BASE_SEQUENCE_TAG 0x00BF
+#define NFAPI_NB_IOT_CONFIG_SIX_TONE_BASE_SEQUENCE_TAG 0x00C0
+#define NFAPI_NB_IOT_CONFIG_TWELVE_TONE_BASE_SEQUENCE_TAG 0x00C1
+#define NFAPI_NB_IOT_CONFIG_THREE_TONE_CYCLIC_SHIFT_TAG 0x00C2
+#define NFAPI_NB_IOT_CONFIG_SIX_TONE_CYCLIC_SHIFT_TAG 0x00C3
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_CONFIG_ENABLE_TAG 0x00C4
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_THRESHOLD_TAG 0x00C5
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_PERIODICITY_TAG 0x00C6
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_DURATION_COEFFICIENT_TAG 0x00C7
+
+typedef struct {
+	nfapi_uint16_tlv_t laa_support;
+	nfapi_uint16_tlv_t pd_sensing_lbt_support;
+	nfapi_uint16_tlv_t multi_carrier_lbt_support;
+	nfapi_uint16_tlv_t partial_sf_support;
+} nfapi_laa_capability_t;
+
+#define NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG 0x00D1
+#define NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG 0x00D2
+#define NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG 0x00D3
+#define NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG 0x00D4
+
+typedef struct {
+	nfapi_uint16_tlv_t nb_iot_support;
+	nfapi_uint16_tlv_t nb_iot_operating_mode_capability;
+} nfapi_nb_iot_capability_t;
+
+#define NFAPI_LAA_CAPABILITY_NB_IOT_SUPPORT_TAG 0x00D5
+#define NFAPI_LAA_CAPABILITY_NB_IOT_OPERATING_MODE_CAPABILITY_TAG 0x00D6
+
+typedef struct {
+	nfapi_uint16_tlv_t subframe_assignment;
+	nfapi_uint16_tlv_t special_subframe_patterns;
+} nfapi_tdd_frame_structure_t;
+
+#define NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG 0x005A
+#define NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG 0x005B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_rf_bands;
+	uint16_t rf_band[NFAPI_MAX_NUM_RF_BANDS];
+} nfapi_rf_bands_t;
+#define NFAPI_PHY_RF_BANDS_TAG 0x0114
+
+#define NFAPI_IPV4_ADDRESS_LENGTH 4
+#define NFAPI_IPV6_ADDRESS_LENGTH 16
+
+// Convience enum to allow the ip addres type to be distinguished
+typedef enum {
+	NFAPI_IP_ADDRESS_IPV4 = 0,
+	NFAPI_IP_ADDRESS_IPV6
+} nfapi_ip_address_type_e;
+
+// The type could be infered from the length, but it is clearer in 
+// code to have a type variable set
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t type;
+	union {
+		uint8_t ipv4_address[NFAPI_IPV4_ADDRESS_LENGTH];
+		uint8_t ipv6_address[NFAPI_IPV6_ADDRESS_LENGTH];
+	} u;
+} nfapi_ip_address_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t address[NFAPI_IPV4_ADDRESS_LENGTH];
+} nfapi_ipv4_address_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t address[NFAPI_IPV6_ADDRESS_LENGTH];
+} nfapi_ipv6_address_t;
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rf_bands;
+	uint16_t bands[NFAPI_MAX_NMM_FREQUENCY_BANDS];
+} nfapi_nmm_frequency_bands_t;
+
+//These TLVs are used exclusively by nFAPI
+typedef struct
+{
+	// These TLVs are used to setup the transport connection between VNF and PNF
+	nfapi_ipv4_address_t p7_vnf_address_ipv4;
+	nfapi_ipv6_address_t p7_vnf_address_ipv6;
+	nfapi_uint16_tlv_t p7_vnf_port;
+
+	nfapi_ipv4_address_t p7_pnf_address_ipv4;
+	nfapi_ipv6_address_t p7_pnf_address_ipv6;
+	nfapi_uint16_tlv_t p7_pnf_port;
+	
+	// These TLVs are used to setup the transport connection between VNF and PNF
+	nfapi_uint8_tlv_t dl_ue_per_sf;
+	nfapi_uint8_tlv_t ul_ue_per_sf;
+
+	// These TLVs are used by PNF to report its RF capabilities to the VNF software
+	nfapi_rf_bands_t rf_bands;
+
+	// These TLVs are used by the VNF to configure the synchronization with the PNF.
+	nfapi_uint8_tlv_t timing_window;
+	nfapi_uint8_tlv_t timing_info_mode;
+	nfapi_uint8_tlv_t timing_info_period;
+
+	// These TLVs are used by the VNF to configure the RF in the PNF
+	nfapi_uint16_tlv_t max_transmit_power;
+	nfapi_uint16_tlv_t earfcn;
+
+	nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands;
+	nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands;
+	nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands;
+	nfapi_uint8_tlv_t nmm_uplink_rssi_supported;
+
+} nfapi_nfapi_t;
+
+#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100
+#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101
+#define NFAPI_NFAPI_P7_VNF_PORT_TAG 0x0102
+#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103
+#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104
+#define NFAPI_NFAPI_P7_PNF_PORT_TAG 0x0105
+
+#define NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x010A
+#define NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x010B
+#define NFAPI_NFAPI_RF_BANDS_TAG 0x0114
+#define NFAPI_NFAPI_TIMING_WINDOW_TAG 0x011E
+#define NFAPI_NFAPI_TIMING_INFO_MODE_TAG 0x011F
+#define NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
+#define NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x0128
+#define NFAPI_NFAPI_EARFCN_TAG 0x0129
+#define NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x0130
+#define NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x0131
+#define NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x0132
+#define NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x0133
+
+
+// P5 Message Structures
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_param_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_pnf_param_general_t pnf_param_general;
+	nfapi_pnf_phy_t pnf_phy;
+	nfapi_pnf_rf_t pnf_rf;
+	nfapi_pnf_phy_rel10_t pnf_phy_rel10;
+	nfapi_pnf_phy_rel11_t pnf_phy_rel11;
+	nfapi_pnf_phy_rel12_t pnf_phy_rel12;
+	nfapi_pnf_phy_rel13_t pnf_phy_rel13;
+	nfapi_pnf_phy_rel13_nb_iot_t pnf_phy_rel13_nb_iot;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_param_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_pnf_phy_rf_config_t pnf_phy_rf_config;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_config_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_config_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_start_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_start_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_stop_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_param_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t error_code;
+	uint8_t num_tlv;
+	// fdd or tdd in idle or configured tlvs
+	nfapi_l1_status l1_status;
+	nfapi_phy_capabilities_t phy_capabilities;
+	nfapi_laa_capability_t laa_capability;
+	nfapi_nb_iot_capability_t nb_iot_capability;
+	
+	nfapi_subframe_config_t subframe_config;
+	nfapi_rf_config_t rf_config;
+	nfapi_phich_config_t phich_config;
+	nfapi_sch_config_t sch_config;
+	nfapi_prach_config_t prach_config;
+	nfapi_pusch_config_t pusch_config;
+	nfapi_pucch_config_t pucch_config;
+	nfapi_srs_config_t srs_config;
+	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
+	nfapi_tdd_frame_structure_t tdd_frame_structure_config;
+	nfapi_l23_config_t l23_config;
+	nfapi_nb_iot_config_t nb_iot_config;
+
+	// addition nfapi tlvs as per table 2-16 in idle or configure
+	nfapi_nfapi_t nfapi_config;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_param_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t num_tlv;
+	nfapi_subframe_config_t subframe_config;
+	nfapi_rf_config_t rf_config;
+	nfapi_phich_config_t phich_config;
+	nfapi_sch_config_t sch_config;
+	nfapi_prach_config_t prach_config;
+	nfapi_pusch_config_t pusch_config;
+	nfapi_pucch_config_t pucch_config;
+	nfapi_srs_config_t srs_config;
+	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
+	nfapi_laa_config_t laa_config;
+	nfapi_emtc_config_t emtc_config;
+	nfapi_tdd_frame_structure_t tdd_frame_structure_config;
+	nfapi_l23_config_t l23_config;
+	nfapi_nb_iot_config_t nb_iot_config;
+	
+	// addition nfapi tlvs as per table 2-16 in idle or configure
+	nfapi_nfapi_t nfapi_config;
+
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_config_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_config_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_start_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_start_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_stop_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_uint16_tlv_t dl_rs_tx_power;
+	nfapi_uint16_tlv_t received_interference_power;
+	nfapi_uint16_tlv_t thermal_noise_power;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_measurement_request_t;
+
+#define NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG 0x1004
+#define NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG 0x1005
+#define NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG 0x1006
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_resource_blocks;
+	int16_t received_interference_power[NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS];
+} nfapi_received_interference_power_measurement_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_int16_tlv_t dl_rs_tx_power_measurement;
+	nfapi_received_interference_power_measurement_t received_interference_power_measurement;
+	nfapi_int16_tlv_t thermal_noise_power_measurement;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_measurement_response_t;
+
+#define NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG 0x1007
+#define NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG 0x1008
+#define NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG 0x1009
+
+// P7 Sub Structures
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dci_format;
+	uint8_t cce_idx;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs_1;
+	uint8_t redundancy_version_1;
+	uint8_t new_data_indicator_1;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t mcs_2;
+	uint8_t redundancy_version_2;
+	uint8_t new_data_indicator_2;
+	uint8_t harq_process;
+	uint8_t tpmi;
+	uint8_t pmi;
+	uint8_t precoding_information;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index;
+	uint8_t ngap;
+	uint8_t transport_block_size_index;
+	uint8_t downlink_power_offset;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t rnti_type;
+	uint16_t transmission_power;
+} nfapi_dl_config_dci_dl_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG 0x2001
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mcch_flag;
+	uint8_t mcch_change_notification;
+	uint8_t scrambling_identity;
+} nfapi_dl_config_dci_dl_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG 0x2002
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t antenna_ports_scrambling_and_layers;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_dl_rb;
+} nfapi_dl_config_dci_dl_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG 0x2003
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_ack_resource_offset;
+	uint8_t pdsch_re_mapping_quasi_co_location_indicator;
+} nfapi_dl_config_dci_dl_pdu_rel11_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG 0x2039
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t primary_cell_type;
+	uint8_t ul_dl_configuration_flag;
+	uint8_t number_ul_dl_configurations;
+	uint8_t ul_dl_configuration_indication[NFAPI_MAX_UL_DL_CONFIGURATIONS];
+} nfapi_dl_config_dci_dl_pdu_rel12_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG 0x203a
+
+
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t scheduled_ues;
+	uint16_t precoding_value[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS][NFAPI_MAX_NUM_SCHEDULED_UES];
+} nfapi_dl_config_dci_dl_tpm_subband_info_t;
+
+typedef struct {
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_antennas;
+	nfapi_dl_config_dci_dl_tpm_subband_info_t subband_info[NFAPI_MAX_NUM_SUBBANDS];
+} nfapi_dl_config_dci_dl_tpm_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t laa_end_partial_sf_flag;
+	uint8_t laa_end_partial_sf_configuration;
+	uint8_t initial_lbt_sf;
+	uint8_t codebook_size_determination;
+	uint8_t drms_table_flag;
+	uint8_t tpm_struct_flag;
+	nfapi_dl_config_dci_dl_tpm_t tpm;
+} nfapi_dl_config_dci_dl_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG 0x203b
+
+typedef struct {
+	nfapi_dl_config_dci_dl_pdu_rel8_t dci_dl_pdu_rel8;
+	nfapi_dl_config_dci_dl_pdu_rel9_t dci_dl_pdu_rel9;
+	nfapi_dl_config_dci_dl_pdu_rel10_t dci_dl_pdu_rel10;
+	nfapi_dl_config_dci_dl_pdu_rel11_t dci_dl_pdu_rel11;
+	nfapi_dl_config_dci_dl_pdu_rel12_t dci_dl_pdu_rel12;
+	nfapi_dl_config_dci_dl_pdu_rel13_t dci_dl_pdu_rel13;
+} nfapi_dl_config_dci_dl_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+} nfapi_dl_config_bch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG 0x2004
+
+typedef struct {
+	nfapi_dl_config_bch_pdu_rel8_t bch_pdu_rel8;
+} nfapi_dl_config_bch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint16_t transmission_power;
+	uint16_t mbsfn_area_id;
+} nfapi_dl_config_mch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG 0x2005
+
+typedef struct {
+	nfapi_dl_config_mch_pdu_rel8_t mch_pdu_rel8;
+} nfapi_dl_config_mch_pdu;
+
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t num_antennas;
+	uint16_t bf_value[NFAPI_MAX_NUM_ANTENNAS];
+} nfapi_bf_vector_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint8_t redundancy_version;
+	uint8_t transport_blocks;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t number_of_subbands;
+	uint8_t codebook_index[NFAPI_MAX_NUM_SUBBANDS];
+	uint8_t ue_category_capacity;
+	uint8_t pa;
+	uint8_t delta_power_offset_index;
+	uint8_t ngap;
+	uint8_t nprb;
+	uint8_t transmission_mode;
+	uint8_t num_bf_prb_per_subband;
+	uint8_t num_bf_vector;
+	nfapi_bf_vector_t bf_vector[NFAPI_MAX_BF_VECTORS];
+} nfapi_dl_config_dlsch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG 0x2006
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nscid;
+} nfapi_dl_config_dlsch_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG 0x2007
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_flag;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_nzp_configuration;
+	uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG];
+	uint8_t pdsch_start;
+} nfapi_dl_config_dlsch_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG 0x2008
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t drms_config_flag;
+	uint16_t drms_scrambling;
+	uint8_t csi_config_flag;
+	uint16_t csi_scrambling;
+	uint8_t pdsch_re_mapping_flag;
+	uint8_t pdsch_re_mapping_atenna_ports;
+	uint8_t pdsch_re_mapping_freq_shift;
+} nfapi_dl_config_dlsch_pdu_rel11_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG 0x203C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t altcqi_table_r12;
+	uint8_t maxlayers;
+	uint8_t n_dl_harq;
+} nfapi_dl_config_dlsch_pdu_rel12_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG 0x203D
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+	uint8_t ue_type;
+	uint8_t pdsch_payload_type;
+	uint16_t initial_transmission_sf_io;
+	uint8_t drms_table_flag;
+} nfapi_dl_config_dlsch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG 0x203E
+
+typedef struct {
+	nfapi_dl_config_dlsch_pdu_rel8_t dlsch_pdu_rel8;
+	nfapi_dl_config_dlsch_pdu_rel9_t dlsch_pdu_rel9;
+	nfapi_dl_config_dlsch_pdu_rel10_t dlsch_pdu_rel10;
+	nfapi_dl_config_dlsch_pdu_rel11_t dlsch_pdu_rel11;
+	nfapi_dl_config_dlsch_pdu_rel12_t dlsch_pdu_rel12;
+	nfapi_dl_config_dlsch_pdu_rel13_t dlsch_pdu_rel13;
+} nfapi_dl_config_dlsch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t p_rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t redundancy_version;
+	uint8_t number_of_transport_blocks;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t ue_category_capacity;
+	uint8_t pa;
+	uint16_t transmission_power;
+	uint8_t nprb;
+	uint8_t ngap;
+} nfapi_dl_config_pch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG 0x2009
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ue_mode;
+	uint16_t initial_transmission_sf_io;
+} nfapi_dl_config_pch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG 0x203F
+
+typedef struct {
+	nfapi_dl_config_pch_pdu_rel8_t pch_pdu_rel8;
+	nfapi_dl_config_pch_pdu_rel13_t pch_pdu_rel13;
+} nfapi_dl_config_pch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t transmission_power;
+	uint8_t prs_bandwidth;
+	uint8_t prs_cyclic_prefix_type;
+	uint8_t prs_muting;
+} nfapi_dl_config_prs_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG 0x200A
+
+typedef struct {
+	nfapi_dl_config_prs_pdu_rel9_t prs_pdu_rel9;
+} nfapi_dl_config_prs_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_antenna_port_count_r10;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t transmission_power;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_of_nzp_configuration;
+	uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG];
+} nfapi_dl_config_csi_rs_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG 0x200B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_class;
+	uint8_t cdm_type;
+	uint8_t num_bf_vector;
+	struct {
+		uint8_t csi_rs_resource_index;
+		uint16_t bf_value[NFAPI_MAX_ANTENNA_PORT_COUNT];
+	} bf_vector[NFAPI_MAX_BF_VECTORS];
+
+}nfapi_dl_config_csi_rs_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG 0x2040
+
+typedef struct {
+	nfapi_dl_config_csi_rs_pdu_rel10_t csi_rs_pdu_rel10;
+	nfapi_dl_config_csi_rs_pdu_rel13_t csi_rs_pdu_rel13;
+} nfapi_dl_config_csi_rs_pdu;
+
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG 0x2001
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG 0x2002
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG 0x2003
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG 0x2039
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG 0x203a
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG 0x203b
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t epdcch_resource_assignment_flag;
+	uint16_t epdcch_id;
+	uint8_t epdcch_start_symbol;
+	uint8_t epdcch_num_prb;
+	uint8_t epdcch_prb_index[NFAPI_MAX_EPDCCH_PRB];
+	nfapi_bf_vector_t bf_vector;
+} nfapi_dl_config_epdcch_parameters_rel11_t;
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG 0x2041
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+} nfapi_dl_config_epdcch_parameters_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG 0x2042
+
+typedef struct {
+	nfapi_dl_config_dci_dl_pdu_rel8_t			epdcch_pdu_rel8;
+	nfapi_dl_config_dci_dl_pdu_rel9_t			epdcch_pdu_rel9;
+	nfapi_dl_config_dci_dl_pdu_rel10_t			epdcch_pdu_rel10;
+	nfapi_dl_config_dci_dl_pdu_rel11_t			epdcch_pdu_rel11;
+	nfapi_dl_config_dci_dl_pdu_rel12_t			epdcch_pdu_rel12;
+	nfapi_dl_config_dci_dl_pdu_rel13_t			epdcch_pdu_rel13;
+	nfapi_dl_config_epdcch_parameters_rel11_t	epdcch_params_rel11;
+	nfapi_dl_config_epdcch_parameters_rel13_t	epdcch_params_rel13;
+} nfapi_dl_config_epdcch_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mpdcch_narrow_band;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_tansmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggregation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint16_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t pdsch_reptition_levels;
+	uint8_t redundancy_version;
+	uint8_t new_data_indicator;
+	uint8_t harq_process;
+	uint8_t tpmi_length;
+	uint8_t tpmi;
+	uint8_t pmi_flag;
+	uint8_t pmi;
+	uint8_t harq_resource_offset;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index_length;
+	uint8_t downlink_assignment_index;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t starting_ce_level;
+	uint8_t srs_request;
+	uint8_t antenna_ports_and_scrambling_identity_flag;
+	uint8_t antenna_ports_and_scrambling_identity;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t paging_direct_indication_differentiation_flag;
+	uint8_t direct_indication;
+	uint8_t total_dci_length_including_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS];
+} nfapi_dl_config_mpdcch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG 0x205B
+
+
+typedef struct {
+	nfapi_dl_config_mpdcch_pdu_rel13_t mpdcch_pdu_rel13;
+} nfapi_dl_config_mpdcch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+	uint16_t hyper_sfn_2_lsbs;
+} nfapi_dl_config_nbch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG 0x205C
+
+typedef struct {
+	nfapi_dl_config_nbch_pdu_rel13_t nbch_pdu_rel13;
+} nfapi_dl_config_nbch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t dci_format;
+	uint8_t scheduling_delay;
+	uint8_t resource_assignment;
+	uint8_t repetition_number;
+	uint8_t mcs;
+	uint8_t new_data_indicator;
+	uint8_t harq_ack_resource;
+	uint8_t npdcch_order_indication;
+	uint8_t starting_number_of_nprach_repetitions;
+	uint8_t subcarrier_indication_of_nprach;
+	uint8_t paging_direct_indication_differentation_flag;
+	uint8_t direct_indication;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t total_dci_length_including_padding;
+} nfapi_dl_config_npdcch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG 0x205D
+
+typedef struct {
+	nfapi_dl_config_npdcch_pdu_rel13_t npdcch_pdu_rel13;
+} nfapi_dl_config_npdcch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint16_t resource_assignment;
+	uint16_t repetition_number;
+	uint8_t modulation;
+	uint8_t number_of_subframes_for_resource_assignment;
+	uint8_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+} nfapi_dl_config_ndlsch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG 0x205E
+
+typedef struct {
+	nfapi_dl_config_ndlsch_pdu_rel13_t ndlsch_pdu_rel13;
+} nfapi_dl_config_ndlsch_pdu;
+
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_dl_config_dci_dl_pdu	dci_dl_pdu;
+		nfapi_dl_config_bch_pdu		bch_pdu;
+		nfapi_dl_config_mch_pdu		mch_pdu;
+		nfapi_dl_config_dlsch_pdu	dlsch_pdu;
+		nfapi_dl_config_pch_pdu		pch_pdu;
+		nfapi_dl_config_prs_pdu		prs_pdu;
+		nfapi_dl_config_csi_rs_pdu	csi_rs_pdu;
+		nfapi_dl_config_epdcch_pdu	epdcch_pdu;
+		nfapi_dl_config_mpdcch_pdu	mpdcch_pdu;
+		nfapi_dl_config_nbch_pdu	nbch_pdu;
+		nfapi_dl_config_npdcch_pdu	npdcch_pdu;
+		nfapi_dl_config_ndlsch_pdu	ndlsch_pdu;
+	};
+} nfapi_dl_config_request_pdu_t;
+
+#define NFAPI_DL_CONFIG_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_pdcch_ofdm_symbols;
+	uint8_t number_dci;
+	uint16_t number_pdu;
+	uint8_t number_pdsch_rnti;
+	uint16_t transmission_power_pcfich;
+	nfapi_dl_config_request_pdu_t* dl_config_pdu_list;
+} nfapi_dl_config_request_body_t;
+#define NFAPI_DL_CONFIG_REQUEST_BODY_TAG 0x2000
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t modulation_type;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication;
+	uint8_t redundancy_version;
+	uint8_t harq_process_number;
+	uint8_t ul_tx_mode;
+	uint8_t current_tx_nb;
+	uint8_t n_srs;
+} nfapi_ul_config_ulsch_pdu_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG 0x200D
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t transport_blocks;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t disable_sequence_hopping_flag;
+} nfapi_ul_config_ulsch_pdu_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG 0x200E
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+	uint8_t dmrs_config_flag;
+	uint16_t ndmrs_csh_identity;
+} nfapi_ul_config_ulsch_pdu_rel11_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG 0x2043
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t  ue_type;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+	uint16_t initial_transmission_sf_io;
+	uint8_t  empty_symbols_due_to_re_tunning;
+} nfapi_ul_config_ulsch_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG 0x2044
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu_rel8_t ulsch_pdu_rel8;
+	nfapi_ul_config_ulsch_pdu_rel10_t ulsch_pdu_rel10;
+	nfapi_ul_config_ulsch_pdu_rel11_t ulsch_pdu_rel11;
+	nfapi_ul_config_ulsch_pdu_rel13_t ulsch_pdu_rel13;
+} nfapi_ul_config_ulsch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dl_cqi_pmi_size_rank_1;
+	uint8_t dl_cqi_pmi_size_rank_greater_1;
+	uint8_t ri_size;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+} nfapi_ul_config_cqi_ri_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG 0x2010
+
+typedef struct {
+	uint8_t dl_cqi_pmi_ri_size;
+	uint8_t control_type;
+} nfapi_ul_config_periodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	uint8_t number_of_cc;
+	struct {
+		uint8_t ri_size;
+		uint8_t dl_cqi_pmi_size[8];
+	} cc[NFAPI_MAX_CC];
+} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t report_type;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+	union {
+		nfapi_ul_config_periodic_cqi_pmi_ri_report_t periodic_cqi_pmi_ri_report;
+		nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t aperiodic_cqi_pmi_ri_report;
+	};
+} nfapi_ul_config_cqi_ri_information_rel9_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG 0x2011
+
+typedef struct {
+	uint16_t dl_cqi_pmi_ri_size_2;
+} nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t;
+
+typedef struct {
+} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t report_type; // Convience parameter, not sent on the wire
+	union {
+		nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t periodic_cqi_pmi_ri_report;
+		nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t aperiodic_cqi_pmi_ri_report;
+	};
+} nfapi_ul_config_cqi_ri_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG 0x2045
+
+typedef struct {
+	nfapi_ul_config_cqi_ri_information_rel8_t cqi_ri_information_rel8;
+	nfapi_ul_config_cqi_ri_information_rel9_t cqi_ri_information_rel9;
+	nfapi_ul_config_cqi_ri_information_rel13_t cqi_ri_information_rel13;
+} nfapi_ul_config_cqi_ri_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t delta_offset_harq;
+	uint8_t ack_nack_mode;
+} nfapi_ul_config_ulsch_harq_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG 0x2012
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t harq_size_2;
+	uint8_t delta_offset_harq_2;
+} nfapi_ul_config_ulsch_harq_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG 0x2046
+
+typedef struct {
+	nfapi_ul_config_ulsch_harq_information_rel10_t harq_information_rel10;
+	nfapi_ul_config_ulsch_harq_information_rel13_t harq_information_rel13;
+} nfapi_ul_config_ulsch_harq_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t n_srs_initial;
+	uint8_t initial_number_of_resource_blocks;
+} nfapi_ul_config_initial_transmission_parameters_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG 0x200F
+
+typedef struct {
+	nfapi_ul_config_initial_transmission_parameters_rel8_t initial_transmission_parameters_rel8;
+} nfapi_ul_config_initial_transmission_parameters;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_ri_information cqi_ri_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_cqi_ri_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_ulsch_harq_information harq_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_ri_information cqi_ri_information;
+	nfapi_ul_config_ulsch_harq_information harq_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_cqi_harq_ri_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t rnti;
+} nfapi_ul_config_ue_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG 0x2013
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+} nfapi_ul_config_ue_information_rel11_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG 0x2047
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t  ue_type;
+	uint8_t  empty_symbols;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+} nfapi_ul_config_ue_information_rel13_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG 0x2048
+
+typedef struct {
+	nfapi_ul_config_ue_information_rel8_t ue_information_rel8;
+	nfapi_ul_config_ue_information_rel11_t ue_information_rel11;
+	nfapi_ul_config_ue_information_rel13_t ue_information_rel13;
+} nfapi_ul_config_ue_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t pucch_index;
+	uint8_t dl_cqi_pmi_size;
+} nfapi_ul_config_cqi_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG 0x2014
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pucch_resource;
+	uint16_t pucch_index_p1;
+} nfapi_ul_config_cqi_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG 0x2015
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_mode;
+	uint16_t dl_cqi_pmi_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} nfapi_ul_config_cqi_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG 0x2049
+
+typedef struct {
+	nfapi_ul_config_cqi_information_rel8_t cqi_information_rel8;
+	nfapi_ul_config_cqi_information_rel10_t cqi_information_rel10;
+	nfapi_ul_config_cqi_information_rel13_t cqi_information_rel13;
+} nfapi_ul_config_cqi_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t pucch_index;
+} nfapi_ul_config_sr_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG 0x2016
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pucch_resources;
+	uint16_t pucch_index_p1;
+} nfapi_ul_config_sr_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG 0x2017
+
+typedef struct { 
+	nfapi_ul_config_sr_information_rel8_t sr_information_rel8;
+	nfapi_ul_config_sr_information_rel10_t sr_information_rel10;
+} nfapi_ul_config_sr_information;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} nfapi_ul_config_harq_information_rel10_tdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG 0x2018
+
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t n_pucch_1_0;
+	uint8_t harq_size;
+} nfapi_ul_config_harq_information_rel8_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG 0x2019
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} nfapi_ul_config_harq_information_rel9_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG 0x201a
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t  num_ant_ports;
+	uint16_t n_pucch_2_0;
+	uint16_t n_pucch_2_1;
+	uint16_t n_pucch_2_2;
+	uint16_t n_pucch_2_3;	
+} nfapi_ul_config_harq_information_rel11_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG 0x204A
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t  harq_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} nfapi_ul_config_harq_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG 0x204B
+
+typedef struct {
+	nfapi_ul_config_harq_information_rel10_tdd_t harq_information_rel10_tdd;
+	nfapi_ul_config_harq_information_rel8_fdd_t harq_information_rel8_fdd;
+	nfapi_ul_config_harq_information_rel9_fdd_t harq_information_rel9_fdd;
+	nfapi_ul_config_harq_information_rel11_t harq_information_rel11;
+	nfapi_ul_config_harq_information_rel13_t harq_information_rel13;
+} nfapi_ul_config_harq_information;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t srs_bandwidth;
+	uint8_t frequency_domain_position;
+	uint8_t srs_hopping_bandwidth;
+	uint8_t transmission_comb;
+	uint16_t i_srs;
+	uint8_t sounding_reference_cyclic_shift;
+} nfapi_ul_config_srs_pdu_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG 0x201b
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t antenna_port;
+} nfapi_ul_config_srs_pdu_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG 0x201c
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t number_of_combs;
+} nfapi_ul_config_srs_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG 0x204c
+
+typedef struct {
+	nfapi_ul_config_srs_pdu_rel8_t srs_pdu_rel8;
+	nfapi_ul_config_srs_pdu_rel10_t srs_pdu_rel10;
+	nfapi_ul_config_srs_pdu_rel13_t srs_pdu_rel13;
+} nfapi_ul_config_srs_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+} nfapi_ul_config_uci_cqi_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_sr_information sr_information;
+} nfapi_ul_config_uci_sr_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_sr_information sr_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_sr_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_cqi_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_sr_information sr_information;
+} nfapi_ul_config_uci_cqi_sr_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_sr_information sr_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_cqi_sr_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+} nfapi_ul_config_harq_buffer_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_information csi_information;
+} nfapi_ul_config_ulsch_uci_csi_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_ulsch_uci_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_information csi_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_ulsch_csi_uci_harq_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_ack_resource;
+} nfapi_ul_config_nb_harq_information_rel13_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG 0x2061
+
+typedef struct {
+	nfapi_ul_config_nb_harq_information_rel13_fdd_t nb_harq_information_rel13_fdd;
+} nfapi_ul_config_nb_harq_information;
+
+typedef struct {
+	nfapi_tl_t tl;	
+	uint8_t nulsch_format;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indication;
+	uint8_t n_srs;
+	uint16_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_nb_harq_information nb_harq_information;
+} nfapi_ul_config_nulsch_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG 0x205F
+
+typedef struct {
+	nfapi_ul_config_nulsch_pdu_rel13_t nulsch_pdu_rel13;
+} nfapi_ul_config_nulsch_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nprach_config_0;
+	uint8_t nprach_config_1;
+	uint8_t nprach_config_2;
+} nfapi_ul_config_nrach_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG 0x2067
+
+typedef struct {
+	nfapi_ul_config_nrach_pdu_rel13_t nrach_pdu_rel13;
+} nfapi_ul_config_nrach_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_ul_config_ulsch_pdu				ulsch_pdu;
+		nfapi_ul_config_ulsch_cqi_ri_pdu		ulsch_cqi_ri_pdu;
+		nfapi_ul_config_ulsch_harq_pdu			ulsch_harq_pdu;
+		nfapi_ul_config_ulsch_cqi_harq_ri_pdu	ulsch_cqi_harq_ri_pdu;
+		nfapi_ul_config_uci_cqi_pdu				uci_cqi_pdu;
+		nfapi_ul_config_uci_sr_pdu				uci_sr_pdu;
+		nfapi_ul_config_uci_harq_pdu			uci_harq_pdu;
+		nfapi_ul_config_uci_sr_harq_pdu			uci_sr_harq_pdu;
+		nfapi_ul_config_uci_cqi_harq_pdu		uci_cqi_harq_pdu;
+		nfapi_ul_config_uci_cqi_sr_pdu			uci_cqi_sr_pdu;
+		nfapi_ul_config_uci_cqi_sr_harq_pdu		uci_cqi_sr_harq_pdu;
+		nfapi_ul_config_srs_pdu					srs_pdu;
+		nfapi_ul_config_harq_buffer_pdu			harq_buffer_pdu;
+		nfapi_ul_config_ulsch_uci_csi_pdu		ulsch_uci_csi_pdu;
+		nfapi_ul_config_ulsch_uci_harq_pdu		ulsch_uci_harq_pdu;
+		nfapi_ul_config_ulsch_csi_uci_harq_pdu	ulsch_csi_uci_harq_pdu;
+		nfapi_ul_config_nulsch_pdu				nulsch_pdu;
+		nfapi_ul_config_nrach_pdu				nrach_pdu;
+	};
+} nfapi_ul_config_request_pdu_t;
+
+#define NFAPI_UL_CONFIG_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pdus;
+	uint8_t rach_prach_frequency_resources;
+	uint8_t srs_present;
+	nfapi_ul_config_request_pdu_t* ul_config_pdu_list;
+} nfapi_ul_config_request_body_t;
+#define NFAPI_UL_CONFIG_REQUEST_BODY_TAG 0x200C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t resource_block_start;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t hi_value;
+	uint8_t i_phich;
+	uint16_t transmission_power;
+} nfapi_hi_dci0_hi_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG 0x201e
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t flag_tb2;
+	uint8_t hi_value_2;
+} nfapi_hi_dci0_hi_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG 0x201f
+
+typedef struct {
+	nfapi_hi_dci0_hi_pdu_rel8_t		hi_pdu_rel8;
+	nfapi_hi_dci0_hi_pdu_rel10_t	hi_pdu_rel10;
+} nfapi_hi_dci0_hi_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_block;
+	uint8_t mcs_1;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication_1;
+	uint8_t ue_tx_antenna_seleciton;
+	uint8_t tpc;
+	uint8_t cqi_csi_request;
+	uint8_t ul_index;
+	uint8_t dl_assignment_index;
+	uint32_t tpc_bitmap;
+	uint16_t transmission_power;
+} nfapi_hi_dci0_dci_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG 0x2020
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t size_of_cqi_csi_feild;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t resource_allocation_flag;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t mcs_2;
+	uint8_t new_data_indication_2;
+	uint8_t number_of_antenna_ports;
+	uint8_t tpmi;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_ul_rb;
+} nfapi_hi_dci0_dci_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG 0x2021
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t pscch_resource;
+	uint8_t time_resource_pattern;
+} nfapi_hi_dci0_dci_pdu_rel12_t;
+
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG 0x204D
+
+typedef struct {
+	nfapi_hi_dci0_dci_pdu_rel8_t	dci_pdu_rel8;
+	nfapi_hi_dci0_dci_pdu_rel10_t	dci_pdu_rel10;
+	nfapi_hi_dci0_dci_pdu_rel12_t	dci_pdu_rel12;
+} nfapi_hi_dci0_dci_pdu;
+
+typedef nfapi_hi_dci0_dci_pdu_rel8_t nfapi_hi_dci0_epdcch_dci_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG 0x2020
+
+typedef nfapi_hi_dci0_dci_pdu_rel10_t nfapi_hi_dci0_epdcch_dci_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG 0x2021
+
+typedef nfapi_dl_config_epdcch_parameters_rel11_t nfapi_hi_dci0_epdcch_parameters_rel11_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG 0x2041
+
+typedef struct {
+	nfapi_hi_dci0_epdcch_dci_pdu_rel8_t		epdcch_dci_pdu_rel8;
+	nfapi_hi_dci0_epdcch_dci_pdu_rel10_t	epdcch_dci_pdu_rel10;
+	nfapi_hi_dci0_epdcch_parameters_rel11_t	epdcch_parameters_rel11;
+} nfapi_hi_dci0_epdcch_dci_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mpdcch_narrowband;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_transmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggreagation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t mcs;
+	uint8_t pusch_repetition_levels;
+	uint8_t frequency_hopping_flag;
+	uint8_t new_data_indication;
+	uint8_t harq_process;
+	uint8_t redudency_version;
+	uint8_t tpc;
+	uint8_t csi_request;
+	uint8_t ul_inex;
+	uint8_t dai_presence_flag;
+	uint8_t dl_assignment_index;
+	uint8_t srs_request;
+	uint8_t dci_subframe_repetition_number;
+	uint32_t tcp_bitmap;
+	uint8_t total_dci_length_include_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[NFAPI_MAX_ANTENNA_PORT_COUNT];
+} nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t;
+#define NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG 0x204E
+
+typedef struct {
+	nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t	mpdcch_dci_pdu_rel13;
+} nfapi_hi_dci0_mpdcch_dci_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t scheduling_delay;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indicator;
+	uint8_t dci_subframe_repetition_number;
+} nfapi_hi_dci0_npdcch_dci_pdu_rel13_t;
+
+#define NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG 0x2062
+
+typedef struct {
+	nfapi_hi_dci0_npdcch_dci_pdu_rel13_t	npdcch_dci_pdu_rel13;
+} nfapi_hi_dci0_npdcch_dci_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_hi_dci0_hi_pdu			hi_pdu;
+		nfapi_hi_dci0_dci_pdu			dci_pdu;
+		nfapi_hi_dci0_epdcch_dci_pdu	epdcch_dci_pdu;
+		nfapi_hi_dci0_mpdcch_dci_pdu	mpdcch_dci_pdu;
+		nfapi_hi_dci0_npdcch_dci_pdu	npdcch_dci_pdu;
+	};
+} nfapi_hi_dci0_request_pdu_t;
+
+#define NFAPI_HI_DCI0_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t sfnsf;
+	uint8_t number_of_dci;
+	uint8_t number_of_hi;
+	nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu_list;
+} nfapi_hi_dci0_request_body_t;
+#define NFAPI_HI_DCI0_REQUEST_BODY_TAG 0x201D
+
+#define NFAPI_TX_MAX_SEGMENTS 32
+typedef struct {
+	uint16_t pdu_length;
+	uint16_t pdu_index;
+	uint8_t num_segments;
+	struct {
+		uint32_t segment_length;
+		uint8_t* segment_data;
+	} segments[NFAPI_TX_MAX_SEGMENTS];
+} nfapi_tx_request_pdu_t;
+
+#define NFAPI_TX_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_tx_request_pdu_t* tx_pdu_list;
+} nfapi_tx_request_body_t;
+#define NFAPI_TX_REQUEST_BODY_TAG 0x2022
+
+// P7 Message Structures
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t t1;
+	int32_t delta_sfn_sf;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_dl_node_sync_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t t1;
+	uint32_t t2;
+	uint32_t t3;	
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ul_node_sync_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t last_sfn_sf;
+	uint32_t time_since_last_timing_info;
+	uint32_t dl_config_jitter;
+	uint32_t tx_request_jitter;
+	uint32_t ul_config_jitter;
+	uint32_t hi_dci0_jitter;
+	int32_t dl_config_latest_delay;
+	int32_t tx_request_latest_delay;
+	int32_t ul_config_latest_delay;
+	int32_t hi_dci0_latest_delay;
+	int32_t dl_config_earliest_arrival;
+	int32_t tx_request_earliest_arrival;
+	int32_t ul_config_earliest_arrival;
+	int32_t hi_dci0_earliest_arrival;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_timing_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t rnti;
+} nfapi_rx_ue_information;
+#define NFAPI_RX_UE_INFORMATION_TAG 0x2038
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+} nfapi_harq_indication_tdd_harq_data_bundling_t;
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+	uint8_t value_2;
+	uint8_t value_3;
+} nfapi_harq_indication_tdd_harq_data_multiplexing_t;
+
+typedef struct { 
+	uint8_t value_0;
+} nfapi_harq_indication_tdd_harq_data_special_bundling_t;
+
+typedef struct { 
+	uint8_t value_0;
+} nfapi_harq_indication_tdd_harq_data_t;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_bundling_t			bundling;
+		nfapi_harq_indication_tdd_harq_data_multiplexing_t		multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+	} harq_data;
+} nfapi_harq_indication_tdd_rel8_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL8_TAG 0x2027
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_t	bundling;
+		nfapi_harq_indication_tdd_harq_data_t	multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+		nfapi_harq_indication_tdd_harq_data_t	channel_selection;
+		nfapi_harq_indication_tdd_harq_data_t	format_3;
+	} harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD];
+} nfapi_harq_indication_tdd_rel9_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL9_TAG 0x2028
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_t					bundling;
+		nfapi_harq_indication_tdd_harq_data_t					multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+		nfapi_harq_indication_tdd_harq_data_t					channel_selection;
+		nfapi_harq_indication_tdd_harq_data_t			format_3;
+		nfapi_harq_indication_tdd_harq_data_t			format_4;
+		nfapi_harq_indication_tdd_harq_data_t			format_5;
+	} harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD];
+} nfapi_harq_indication_tdd_rel13_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL13_TAG 0x204F
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_tb1;
+	uint8_t harq_tb2;
+} nfapi_harq_indication_fdd_rel8_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL8_TAG 0x2029
+
+#define NFAPI_HARQ_ACK_NACK_REL9_MAX 10
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL9_MAX];
+} nfapi_harq_indication_fdd_rel9_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL9_TAG 0x202a
+
+#define NFAPI_HARQ_ACK_NACK_REL13_MAX 22 // Need to check this max?
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL13_MAX];
+} nfapi_harq_indication_fdd_rel13_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL13_TAG 0x2050
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ul_cqi;
+	uint8_t channel;
+} nfapi_ul_cqi_information_t;
+#define NFAPI_UL_CQI_INFORMATION_TAG 0x2052
+
+// Only expect 1 harq_indication TLV.tag to be set
+// Would this be a better a an union, but not clear which combinations
+// are valid
+typedef struct {
+	uint16_t							instance_length;
+	nfapi_rx_ue_information				rx_ue_information;
+	nfapi_harq_indication_tdd_rel8_t	harq_indication_tdd_rel8;
+	nfapi_harq_indication_tdd_rel9_t	harq_indication_tdd_rel9;
+	nfapi_harq_indication_tdd_rel13_t	harq_indication_tdd_rel13;
+	nfapi_harq_indication_fdd_rel8_t	harq_indication_fdd_rel8;
+	nfapi_harq_indication_fdd_rel9_t	harq_indication_fdd_rel9;
+	nfapi_harq_indication_fdd_rel13_t	harq_indication_fdd_rel13;
+	nfapi_ul_cqi_information_t			ul_cqi_information;
+} nfapi_harq_indication_pdu_t;
+
+#define NFAPI_HARQ_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_harqs;
+	nfapi_harq_indication_pdu_t* harq_pdu_list;
+} nfapi_harq_indication_body_t;
+#define NFAPI_HARQ_INDICATION_BODY_TAG 0x2026
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t crc_flag;
+} nfapi_crc_indication_rel8_t;
+#define NFAPI_CRC_INDICATION_REL8_TAG 0x202c
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_crc_indication_rel8_t	crc_indication_rel8;
+} nfapi_crc_indication_pdu_t;
+
+#define NFAPI_CRC_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_crcs;
+	nfapi_crc_indication_pdu_t* crc_pdu_list;
+} nfapi_crc_indication_body_t;
+#define NFAPI_CRC_INDICATION_BODY_TAG 0x202b
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_ul_cqi_information_t	ul_cqi_information;
+} nfapi_sr_indication_pdu_t;
+
+#define NFAPI_SR_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_srs;				// Question : should this be srs
+	nfapi_sr_indication_pdu_t* sr_pdu_list;
+} nfapi_sr_indication_body_t;
+#define NFAPI_SR_INDICATION_BODY_TAG 0x202d
+
+// The data offset should be set to 0 or 1 before encoding
+// If it is set to 1 the nfapi library will detemine the correct offset
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t ri;
+	uint16_t timing_advance;
+} nfapi_cqi_indication_rel8_t;
+#define NFAPI_CQI_INDICATION_REL8_TAG 0x202f
+
+#define NFAPI_CC_MAX 4
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t number_of_cc_reported;
+	uint8_t ri[NFAPI_CC_MAX];
+	uint16_t timing_advance;
+	uint16_t timing_advance_r9;
+} nfapi_cqi_indication_rel9_t;
+#define NFAPI_CQI_INDICATION_REL9_TAG 0x2030
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_cqi_indication_rel8_t cqi_indication_rel8;
+	nfapi_cqi_indication_rel9_t cqi_indication_rel9;
+	nfapi_ul_cqi_information_t	ul_cqi_information;
+} nfapi_cqi_indication_pdu_t;
+
+#define NFAPI_CQI_RAW_MAX_LEN 12
+typedef struct {
+	uint8_t pdu[NFAPI_CQI_RAW_MAX_LEN];
+} nfapi_cqi_indication_raw_pdu_t;
+
+#define NFAPI_CQI_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_cqis;
+	nfapi_cqi_indication_pdu_t*			cqi_pdu_list;
+	nfapi_cqi_indication_raw_pdu_t*		cqi_raw_pdu_list;
+} nfapi_cqi_indication_body_t;
+#define NFAPI_CQI_INDICATION_BODY_TAG 0x202e
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t rnti;
+	uint8_t preamble;
+	uint16_t timing_advance;
+} nfapi_preamble_pdu_rel8_t;
+#define NFAPI_PREAMBLE_REL8_TAG 0x2032
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+} nfapi_preamble_pdu_rel9_t;
+#define NFAPI_PREAMBLE_REL9_TAG 0x2033
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t rach_resource_type;
+} nfapi_preamble_pdu_rel13_t;
+#define NFAPI_PREAMBLE_REL13_TAG 0x2051
+
+typedef struct { 
+	uint16_t					instance_length;
+	nfapi_preamble_pdu_rel8_t	preamble_rel8;
+	nfapi_preamble_pdu_rel9_t	preamble_rel9;
+	nfapi_preamble_pdu_rel13_t	preamble_rel13;
+} nfapi_preamble_pdu_t;
+
+#define NFAPI_PREAMBLE_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_preambles;
+	nfapi_preamble_pdu_t*			preamble_list;
+} nfapi_rach_indication_body_t;
+#define NFAPI_RACH_INDICATION_BODY_TAG 0x2031
+
+#define NFAPI_NUM_RB_MAX 1000
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t doppler_estimation;
+	uint16_t timing_advance;
+	uint8_t number_of_resource_blocks;
+	uint8_t rb_start;
+	uint8_t snr[NFAPI_NUM_RB_MAX];
+} nfapi_srs_indication_fdd_rel8_t;
+#define NFAPI_SRS_INDICATION_FDD_REL8_TAG 0x2035
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+} nfapi_srs_indication_fdd_rel9_t;
+#define NFAPI_SRS_INDICATION_FDD_REL9_TAG 0x2036
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t uppts_symbol;
+} nfapi_srs_indication_ttd_rel10_t;
+#define NFAPI_SRS_INDICATION_TDD_REL10_TAG 0x2037
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t ul_rtoa;
+} nfapi_srs_indication_fdd_rel11_t;
+#define NFAPI_SRS_INDICATION_FDD_REL11_TAG 0x2053
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_atennas;
+	struct {
+		uint8_t subband_index;
+		uint16_t channel[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS];
+	} subands[NFAPI_MAX_NUM_SUBBANDS];
+} nfapi_tdd_channel_measurement_t;
+#define NFAPI_TDD_CHANNEL_MEASUREMENT_TAG 0x2054
+
+typedef struct {
+	uint16_t							instance_length;
+	nfapi_rx_ue_information				rx_ue_information;
+	nfapi_srs_indication_fdd_rel8_t		srs_indication_fdd_rel8;
+	nfapi_srs_indication_fdd_rel9_t		srs_indication_fdd_rel9;
+	nfapi_srs_indication_ttd_rel10_t	srs_indication_tdd_rel10;
+	nfapi_srs_indication_fdd_rel11_t	srs_indication_fdd_rel11;
+	nfapi_tdd_channel_measurement_t		tdd_channel_measurement;
+} nfapi_srs_indication_pdu_t;
+
+#define NFAPI_SRS_IND_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_ues;
+	nfapi_srs_indication_pdu_t* srs_pdu_list;
+} nfapi_srs_indication_body_t;
+#define NFAPI_SRS_INDICATION_BODY_TAG 0x2034
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t offset;
+	uint8_t ul_cqi;
+	uint16_t timing_advance;
+} nfapi_rx_indication_rel8_t;
+#define NFAPI_RX_INDICATION_REL8_TAG 0x2024
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+ } nfapi_rx_indication_rel9_t;
+#define NFAPI_RX_INDICATION_REL9_TAG 0x2025
+
+typedef struct {
+	nfapi_rx_ue_information rx_ue_information;
+	nfapi_rx_indication_rel8_t rx_indication_rel8;
+	nfapi_rx_indication_rel9_t rx_indication_rel9;
+	uint8_t* data;
+} nfapi_rx_indication_pdu_t;
+
+#define NFAPI_RX_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_rx_indication_pdu_t* rx_pdu_list;
+} nfapi_rx_indication_body_t;
+#define NFAPI_RX_INDICATION_BODY_TAG 0x2023
+
+typedef struct {
+	nfapi_tl_t tl;	
+	uint8_t harq_tb1;
+} nfapi_nb_harq_indication_fdd_rel13_t;
+#define NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG 0x2064
+
+typedef struct {
+	uint16_t								instance_length;
+	nfapi_rx_ue_information					rx_ue_information;
+	nfapi_nb_harq_indication_fdd_rel13_t	nb_harq_indication_fdd_rel13;
+	nfapi_ul_cqi_information_t				ul_cqi_information;
+} nfapi_nb_harq_indication_pdu_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_harqs;
+	nfapi_nb_harq_indication_pdu_t* nb_harq_pdu_list;
+} nfapi_nb_harq_indication_body_t;
+#define NFAPI_NB_HARQ_INDICATION_BODY_TAG 0x2063
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t rnti;
+	uint8_t initial_sc;
+	uint16_t timing_advance;
+	uint8_t nrach_ce_level;
+} nfapi_nrach_indication_pdu_rel13_t;
+#define NFAPI_NRACH_INDICATION_REL13_TAG 0x2066
+
+typedef struct {
+	nfapi_nrach_indication_pdu_rel13_t		nrach_indication_rel13;
+} nfapi_nrach_indication_pdu_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_initial_scs_detected;
+	nfapi_nrach_indication_pdu_t* nrach_pdu_list;
+} nfapi_nrach_indication_body_t;
+#define NFAPI_NRACH_INDICATION_BODY_TAG 0x2065
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t mp_cca;
+	uint32_t n_cca;
+	uint32_t offset;
+	uint32_t lte_txop_sf;
+	uint16_t txop_sfn_sf_end;
+	uint32_t lbt_mode;
+} nfapi_lbt_pdsch_req_pdu_rel13_t;
+#define NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG 0x2056
+
+typedef struct {
+	nfapi_lbt_pdsch_req_pdu_rel13_t lbt_pdsch_req_pdu_rel13;
+} nfapi_lbt_pdsch_req_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t offset;
+	uint16_t sfn_sf_end;
+	uint32_t lbt_mode;
+} nfapi_lbt_drs_req_pdu_rel13_t;
+#define NFAPI_LBT_DRS_REQ_PDU_REL13_TAG 0x2057
+
+typedef struct {
+	nfapi_lbt_drs_req_pdu_rel13_t lbt_drs_req_pdu_rel13;
+} nfapi_lbt_drs_req_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_lbt_pdsch_req_pdu		lbt_pdsch_req_pdu;
+		nfapi_lbt_drs_req_pdu		lbt_drs_req_pdu;
+	};
+} nfapi_lbt_dl_config_request_pdu_t;
+
+#define NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_lbt_dl_config_request_pdu_t*		lbt_dl_config_req_pdu_list;
+} nfapi_lbt_dl_config_request_body_t;
+#define NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG 0x2055
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t result;
+	uint32_t lte_txop_symbols;
+	uint32_t initial_partial_sf;
+} nfapi_lbt_pdsch_rsp_pdu_rel13_t;
+#define NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG 0x2059
+
+typedef struct {
+	nfapi_lbt_pdsch_rsp_pdu_rel13_t lbt_pdsch_rsp_pdu_rel13;
+} nfapi_lbt_pdsch_rsp_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t result;
+} nfapi_lbt_drs_rsp_pdu_rel13_t;
+#define NFAPI_LBT_DRS_RSP_PDU_REL13_TAG 0x205A
+
+typedef struct {
+	nfapi_lbt_drs_rsp_pdu_rel13_t lbt_drs_rsp_pdu_rel13;
+} nfapi_lbt_drs_rsp_pdu;
+
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_lbt_pdsch_rsp_pdu		lbt_pdsch_rsp_pdu;
+		nfapi_lbt_drs_rsp_pdu		lbt_drs_rsp_pdu;
+	};
+} nfapi_lbt_dl_indication_pdu_t;
+
+#define NFAPI_LBT_IND_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_lbt_dl_indication_pdu_t* lbt_indication_pdu_list;
+} nfapi_lbt_dl_indication_body_t;
+#define NFAPI_LBT_DL_INDICATION_BODY_TAG 0x2058
+
+typedef struct {
+} nfapi_error_indication_msg_invalid_state;
+
+typedef struct {
+} nfapi_error_indication_msg_bch_missing;
+
+typedef struct {
+	uint16_t recieved_sfn_sf;
+	uint16_t expected_sfn_sf;
+} nfapi_error_indication_sfn_out_of_sync;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t direction;
+	uint16_t rnti;
+	uint8_t pdu_type;
+} nfapi_error_indication_msg_pdu_err;
+
+typedef struct {
+	uint16_t recieved_sfn_sf;
+	uint16_t expected_sfn_sf;
+} nfapi_error_indication_msg_invalid_sfn;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t phich_lowest_ul_rb_index;
+} nfapi_error_indication_msg_hi_err;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint16_t pdu_index;
+} nfapi_error_indication_msg_tx_err;
+
+// 
+// P4 Message Structures
+//
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint8_t bandwidth;
+	uint32_t timeout;
+	uint8_t number_of_earfcns;
+	uint16_t earfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_lte_rssi_request_t;
+
+#define NFAPI_LTE_RSSI_REQUEST_TAG 0x3000
+
+#define NFAPI_P4_START_TAG NFAPI_LTE_RSSI_REQUEST_TAG
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_uarfcns;
+	uint16_t uarfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_utran_rssi_request_t;
+
+#define NFAPI_UTRAN_RSSI_REQUEST_TAG 0x3001
+
+typedef struct {
+	uint16_t arfcn;
+	uint8_t direction;
+} nfapi_arfcn_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_arfcns;
+	nfapi_arfcn_t arfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_geran_rssi_request_t;
+
+#define NFAPI_GERAN_RSSI_REQUEST_TAG 0x3002
+
+
+
+typedef struct {
+	uint16_t earfcn;
+	uint8_t number_of_ro_dl;
+	uint8_t ro_dl[NFAPI_MAX_RO_DL];
+} nfapi_earfcn_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_earfcns;
+	nfapi_earfcn_t earfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_nb_iot_rssi_request_t;
+
+#define NFAPI_NB_IOT_RSSI_REQUEST_TAG 0x3020
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rssi;
+	int16_t rssi[NFAPI_MAX_RSSI];
+} nfapi_rssi_indication_body_t;
+
+#define NFAPI_RSSI_INDICATION_TAG 0x3003
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t measurement_bandwidth;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_pci;
+	uint16_t pci[NFAPI_MAX_PCI_LIST];
+} nfapi_lte_cell_search_request_t;
+
+#define NFAPI_LTE_CELL_SEARCH_REQUEST_TAG 0x3004
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_psc;
+	uint16_t psc[NFAPI_MAX_PSC_LIST];
+} nfapi_utran_cell_search_request_t;
+
+#define NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG 0x3005
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t timeout;
+	uint8_t number_of_arfcn;
+	uint16_t arfcn[NFAPI_MAX_ARFCN_LIST];
+} nfapi_geran_cell_search_request_t;
+
+#define NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG 0x3006
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_pci;
+	uint16_t pci[NFAPI_MAX_PCI_LIST];
+} nfapi_nb_iot_cell_search_request_t;
+
+#define NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG 0x3021
+
+typedef struct {
+	uint16_t pci;
+	uint8_t rsrp;
+	uint8_t rsrq;
+	int16_t frequency_offset;
+} nfapi_lte_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_lte_cells_found;
+	nfapi_lte_found_cell_t lte_found_cells[NFAPI_MAX_LTE_CELLS_FOUND];
+} nfapi_lte_cell_search_indication_t;
+
+#define NFAPI_LTE_CELL_SEARCH_INDICATION_TAG 0x3007
+
+typedef struct {
+	uint16_t psc;
+	uint8_t rscp;
+	uint8_t ecno;
+	int16_t frequency_offset;
+} nfapi_utran_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_utran_cells_found;
+	nfapi_utran_found_cell_t utran_found_cells[NFAPI_MAX_UTRAN_CELLS_FOUND];
+} nfapi_utran_cell_search_indication_t;
+
+#define NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG 0x3008
+
+typedef struct {
+	uint16_t arfcn;
+	uint8_t bsic;
+	uint8_t rxlev;
+	uint8_t rxqual;
+	int16_t frequency_offset;
+	uint32_t sfn_offset;
+} nfapi_gsm_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_gsm_cells_found;
+	nfapi_gsm_found_cell_t gsm_found_cells[NFAPI_MAX_GSM_CELLS_FOUND];
+} nfapi_geran_cell_search_indication_t;
+
+#define NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG 0x3009
+
+typedef struct {
+	uint16_t pci;
+	uint8_t rsrp;
+	uint8_t rsrq;
+	int16_t frequency_offset;
+} nfapi_nb_iot_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_nb_iot_cells_found;
+	nfapi_nb_iot_found_cell_t nb_iot_found_cells[NFAPI_MAX_NB_IOT_CELLS_FOUND];
+} nfapi_nb_iot_cell_search_indication_t;
+
+#define NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG 0x3022
+
+typedef nfapi_opaqaue_data_t nfapi_pnf_cell_search_state_t;
+
+#define NFAPI_PNF_CELL_SEARCH_STATE_TAG 0x300A
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint32_t timeout;
+} nfapi_lte_broadcast_detect_request_t;
+
+#define NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG 0x300B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint16_t psc;
+	uint32_t timeout;
+} nfapi_utran_broadcast_detect_request_t;
+
+#define NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG 0x300C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint32_t timeout;
+} nfapi_nb_iot_broadcast_detect_request_t;
+
+#define NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG 0x3023
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_tx_antenna;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_lte_broadcast_detect_indication_t;
+
+#define NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG 0x300E
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_utran_broadcast_detect_indication_t;
+
+#define NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG 0x300F
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_tx_antenna;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_nb_iot_broadcast_detect_indication_t;
+
+#define NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG 0x3024
+
+#define NFAPI_PNF_CELL_BROADCAST_STATE_TAG 0x3010
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint16_t downlink_channel_bandwidth;
+	uint8_t phich_configuration;
+	uint8_t number_of_tx_antenna;
+	uint8_t retry_count;
+	uint32_t timeout;
+} nfapi_lte_system_information_schedule_request_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3011
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint8_t scheduling_info_sib1_nb;
+	uint32_t timeout;
+} nfapi_nb_iot_system_information_schedule_request_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3025
+
+typedef nfapi_opaqaue_data_t nfapi_pnf_cell_broadcast_state_t;
+
+typedef struct {
+	uint8_t si_periodicity;
+	uint8_t si_index;
+} nfapi_lte_system_information_si_periodicity_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint16_t downlink_channel_bandwidth;
+	uint8_t phich_configuration;
+	uint8_t number_of_tx_antenna;
+	uint8_t number_of_si_periodicity;
+	nfapi_lte_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY];
+	uint8_t si_window_length;
+	uint32_t timeout;
+} nfapi_lte_system_information_request_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG 0x3014
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint16_t psc;
+	uint32_t timeout;
+} nfapi_utran_system_information_request_t;
+
+#define NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3015
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t arfcn;
+	uint8_t bsic;
+	uint32_t timeout;
+} nfapi_geran_system_information_request_t;
+
+#define NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3016
+
+typedef struct {
+	uint8_t si_periodicity;
+	uint8_t si_repetition_pattern;
+	uint8_t si_tb_size;
+	uint8_t number_of_si_index;
+	uint8_t si_index[NFAPI_MAX_SI_INDEX];
+} nfapi_nb_iot_system_information_si_periodicity_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint8_t number_of_si_periodicity;
+	nfapi_nb_iot_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY];
+	uint8_t si_window_length;
+	uint32_t timeout;
+} nfapi_nb_iot_system_information_request_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG 0x3027
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t sib_type;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_lte_system_information_indication_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG 0x3018
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_utran_system_information_indication_t;
+
+#define NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG 0x3019
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t si_length;
+	uint8_t si[NFAPI_MAX_SI_LENGTH];
+} nfapi_geran_system_information_indication_t;
+
+#define NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG 0x301a
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t sib_type;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_nb_iot_system_information_indication_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG 0x3026
+
+
+//
+// Top level NFAP messages
+//
+
+//
+// P7
+//
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_dl_config_request_body_t dl_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_dl_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_ul_config_request_body_t ul_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ul_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_hi_dci0_request_body_t hi_dci0_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_hi_dci0_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_tx_request_body_t tx_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_tx_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+} nfapi_subframe_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_harq_indication_body_t harq_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_harq_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_crc_indication_body_t crc_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_crc_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_sr_indication_body_t sr_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_sr_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_cqi_indication_body_t cqi_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cqi_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_rach_indication_body_t rach_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rach_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_srs_indication_body_t srs_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_srs_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_rx_indication_body_t rx_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rx_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_nb_harq_indication_body_t nb_harq_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nb_harq_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_nrach_indication_body_t nrach_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nrach_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_lbt_dl_config_request_body_t lbt_dl_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_lbt_dl_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_lbt_dl_indication_body_t lbt_dl_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_lbt_dl_indication_t;
+
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint8_t message_id;
+	uint8_t error_code;
+	union {
+		nfapi_error_indication_msg_invalid_state	msg_invalid_state;
+		nfapi_error_indication_msg_bch_missing		msg_bch_missing;
+		nfapi_error_indication_sfn_out_of_sync		sfn_out_of_sync;
+		nfapi_error_indication_msg_pdu_err			msg_pdu_err;
+		nfapi_error_indication_msg_invalid_sfn		msg_invalid_sfn;
+		nfapi_error_indication_msg_hi_err			msg_hi_err;
+		nfapi_error_indication_msg_tx_err			msg_tx_err;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_error_indication_t;
+
+// 
+// P4 Messages
+// 
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_rssi_request_t					lte_rssi_request;
+		nfapi_utran_rssi_request_t					utran_rssi_request;
+		nfapi_geran_rssi_request_t					geran_rssi_request;
+		nfapi_nb_iot_rssi_request_t					nb_iot_rssi_request;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_rssi_indication_body_t rssi_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_cell_search_request_t				lte_cell_search_request;
+		nfapi_utran_cell_search_request_t			utran_cell_search_request;
+		nfapi_geran_cell_search_request_t			geran_cell_search_request;
+		nfapi_nb_iot_cell_search_request_t			nb_iot_cell_search_request;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_cell_search_indication_t lte_cell_search_indication;
+	nfapi_utran_cell_search_indication_t utran_cell_search_indication;
+	nfapi_geran_cell_search_indication_t geran_cell_search_indication;
+	nfapi_pnf_cell_search_state_t pnf_cell_search_state;
+	nfapi_nb_iot_cell_search_indication_t nb_iot_cell_search_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_indication_t;
+
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_broadcast_detect_request_t		lte_broadcast_detect_request;
+		nfapi_utran_broadcast_detect_request_t		utran_broadcast_detect_request;
+		nfapi_nb_iot_broadcast_detect_request_t		nb_iot_broadcast_detect_request;
+	};
+	nfapi_pnf_cell_search_state_t pnf_cell_search_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_broadcast_detect_indication_t lte_broadcast_detect_indication;
+	nfapi_utran_broadcast_detect_indication_t utran_broadcast_detect_indication;
+	nfapi_nb_iot_broadcast_detect_indication_t nb_iot_broadcast_detect_indication;
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_system_information_schedule_request_t lte_system_information_schedule_request;
+		nfapi_nb_iot_system_information_schedule_request_t nb_iot_system_information_schedule_request;
+	};
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_response_t;
+
+typedef struct { 
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_system_information_indication_t lte_system_information_indication;
+	nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_system_information_request_t lte_system_information_request;
+		nfapi_utran_system_information_request_t utran_system_information_request;
+		nfapi_geran_system_information_request_t geran_system_information_request;
+		nfapi_nb_iot_system_information_request_t nb_iot_system_information_request;
+	};
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_system_information_indication_t lte_system_information_indication;
+	nfapi_utran_system_information_indication_t utran_system_information_indication;
+	nfapi_geran_system_information_indication_t geran_system_information_indication;
+	nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nmm_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nmm_stop_response_t;
+
+//
+// Configuration options for the encode decode functions
+//
+
+/*! Configuration options for the p7 pack unpack functions
+ *
+ */
+typedef struct nfapi_p7_codec_config {
+
+	/*! Optional call back to allow the user to define the memory allocator. 
+	 *  \param size The size of the memory to allocate
+	 *  \return a pointer to a valid memory block or 0 if it has failed.
+	 *
+	 * If not set the nfapi unpack functions will use malloc
+	 */
+	void* (*allocate)(size_t size);
+
+	/*! Optional call back to allow the user to define the memory deallocator. 
+	 *  \param ptr A poiner to a memory block allocated by the allocate callback
+	 * 
+	 *	If not set the client should use free
+	 */
+	void (*deallocate)(void* ptr);
+
+	/*! Optional call back function to handle unpacking vendor extension tlv.
+	 *  \param tl A pointer to a decoded tag length structure
+	 *  \param ppReadPackedMsg A handle to the read buffer. 
+	 *  \param end The end of the read buffer
+	 *  \param ve A handle to a vendor extention structure that the call back should allocate if the structure can be decoded
+	 *  \param config A pointer to the p7 codec configuration
+	 *  \return return 0 if packed successfully, -1 if failed.
+	 *
+	 *  If not set the tlv will be skipped
+	 *
+	 *  Client should use the help methods in nfapi.h to decode the vendor extention.
+	 * 
+	 *  \todo Add code example
+	 */
+	int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension tlv. 
+	 *  \param ve A pointer to a vendor extention structure.
+	 *  \param ppWritePackedMsg A handle to the write buffer
+	 *  \param end The end of the write buffer. The callee should make sure not to write beyond the end
+	 *  \param config A pointer to the p7 codec configuration
+	 *  \return return 0 if packed successfully, -1 if failed.
+	 * 
+	 *  If not set the the tlv will be skipped
+	 * 
+	 *  Client should use the help methods in nfapi.h to encode the vendor extention
+	 * 
+	 *  \todo Add code example
+	 */
+	int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle unpacking vendor extension messages. 
+	 *  \param header A pointer to a decode P7 message header for the vendor extention message
+	 *  \param ppReadPackedMsg A handle to the encoded data buffer
+	 *  \param end A pointer to the end of the encoded data buffer
+	 *  \param config  A pointer to the p7 codec configuration
+	 *  \return 0 if unpacked successfully, -1 if failed
+	 *
+	 *  If not set the message will be ignored
+	 *
+	 *  If the message if is unknown the function should return -1
+	 */
+	int (*unpack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension messages. 
+	 *  \param header A poiner to a P7 message structure for the venfor extention message
+	 *  \param ppWritePackedmsg A handle to the buffer to write the encoded message into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param cofig A pointer to the p7 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 * 
+	 * If not set the the message will be ingored
+	 *	 
+	 *  If the message if is unknown the function should return -1
+	 */
+	int (*pack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedmsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional user data that will be passed back with callbacks
+	 */
+	void* user_data;
+
+} nfapi_p7_codec_config_t;
+
+/*! Configuration options for the p4 & p5 pack unpack functions
+ *
+ */
+typedef struct nfapi_p4_p5_codec_config {
+
+	/*! Optional call back to allow the user to define the memory allocator.
+     *  \param size The size of the memory to allocate
+	 *  \return a pointer to a valid memory block or 0 if it has failed.
+	 *
+	 *  If not set the nfapi unpack functions will use malloc
+	 */
+	void* (*allocate)(size_t size);
+
+	/*! Optional call back to allow the user to define the memory deallocator. 
+	 *  \param ptr A poiner to a memory block allocated by the allocate callback
+	 *
+	 *  If not set free will be used
+	 */
+	void (*deallocate)(void* ptr);
+
+	/*! Optional call back function to handle unpacking vendor extension tlv.
+	 *  \param tl A pointer to a decoded tag length structure
+	 *  \param ppReadPackedMsg A handle to the data buffer to decode
+	 *  \param end A pointer to the end of the buffer
+	 *  \param ve A handle to a vendor extention structure that will be allocated by this callback
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if unpacked successfully, -1 if failed
+	 *  
+	 *  If not set the tlv will be skipped
+	 */
+	int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension tlv. 
+	 *  \param ve
+	 *  \param ppWritePackedMsg A handle to the data buffer pack the tlv into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *
+	 *  If not set the the tlv will be skipped
+	 */
+	int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle unpacking vendor extension messages. 
+	 *  \param header A pointer to a decode P4/P5 message header
+	 *  \param ppReadPackgedMsg A handle to the data buffer to decode
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *
+	 * If not set the message will be ignored
+	 */
+	int (*unpack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension messages.
+	 *  \param header A pointer to the P4/P5 message header to be encoded
+	 *  \param ppWritePackedMsg A handle to the data buffer pack the message into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *  
+	 *  If not set the the message will be ingored
+	 */
+	int (*pack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppwritepackedmsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional user data that will be passed back with callbacks
+	 */
+	void* user_data;
+
+} nfapi_p4_p5_codec_config_t;
+
+//
+// Functions
+// 
+
+/*! \brief Encodes an NFAPI P4 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p4 message structure
+ *  \param messageBufLen The size of the p4 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p4 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P4 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P4 message header
+ *  \param pMessageBuf A pointer to an encoded P4 message header
+ *  \param messageBufLen The size of the encoded P4 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf
+ */
+int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P4 message
+ *  \param pMessageBuf A pointer to an encoded P4 message
+ *  \param messageBufLen The size of the encoded P4 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p4 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Encodes an NFAPI P5 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p5 message structure
+ *  \param messageBufLen The size of the p5 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p5 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P5 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes an NFAPI P5 message header
+ *  \param pMessageBuf A pointer to an encoded P5 message header
+ *  \param messageBufLen The size of the encoded P5 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf
+ */
+int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P5 message
+ *  \param pMessageBuf A pointer to an encoded P5 message
+ *  \param messageBufLen The size of the encoded P5 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Encodes an NFAPI P7 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p7 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p7 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P7 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Decodes an NFAPI P7 message header
+ *  \param pMessageBuf A pointer to an encoded P7 message header
+ *  \param messageBufLen The size of the encoded P7 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p7_message_header structure pointer to by pUnpackedBuf
+
+ */
+int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P7 message
+ *  \param pMessageBuf A pointer to an encoded P7 message
+ *  \param messageBufLen The size of the encoded P7 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Calculates the checksum of a  message
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param len The length of the message
+ *  \return The checksum. If there is an error the function with return -1
+ */
+uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len);
+
+/*! \brief Calculates & updates the checksum in the message
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param len The length of the message
+  *  \return 0 means success, -1 means failure.
+ */
+int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len);
+
+/*! \brief Updates the transmition time stamp in the p7 message header
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param timestamp The time stamp value
+  *  \return 0 means success, -1 means failure.
+ */
+int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp);
+
+#endif /* _NFAPI_INTERFACE_H_ */
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c
new file mode 100644
index 0000000000..3f017bc9a4
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c
@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2001-2016, Cisco Systems, Inc.
+ * All rights reserved.
+ *  
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *  
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <nfapi_interface.h>
+#include <nfapi.h>
+#include <debug.h>
+
+
+// Fundamental routines
+
+uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+
+	if((end - pOut) >= 1)
+	{
+		pOut[0] = in;
+
+		(*out)+=1;
+
+		return 1;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+
+}
+
+uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+
+	if((end - pOut) >= 1)
+	{
+		pOut[0] = in;
+
+		(*out)+=1;
+
+		return 1;
+	}
+	else 
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+	
+	if((end - pOut) >= 2)
+	{
+		pOut[0] = (in & 0xFF00) >> 8;
+		pOut[1] = (in & 0xFF);
+
+		(*out)+=2;
+
+		return 2;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+
+	if((end - pOut) >= 2)
+	{
+		pOut[0] = (in & 0xFF00) >> 8;
+		pOut[1] = (in & 0xFF);
+
+		(*out)+=2;
+
+		return 2;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+	if((end - pOut) >= 4)
+	{
+		pOut[0] = (in & 0xFF000000) >> 24;
+		pOut[1] = (in & 0xFF0000) >> 16;
+		pOut[2] = (in & 0xFF00) >> 8;
+		pOut[3] = (in & 0xFF);
+
+		(*out)+=4;
+
+		return 4;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end)
+{
+	uint8_t *pOut = *out;
+
+	if((end - pOut) >= 4)
+	{
+		pOut[0] = (in & 0xFF000000) >> 24;
+		pOut[1] = (in & 0xFF0000) >> 16;
+		pOut[2] = (in & 0xFF00) >> 8;
+		pOut[3] = (in & 0xFF);
+
+		(*out)+=4;
+
+		return 4;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >= 1 )
+	{
+		*out = *pIn;
+
+		(*in)+=1;
+
+		return 1;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >= 1 )
+	{
+		*out = *pIn;
+
+		(*in)+=1;
+
+		return 1;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >=2 )
+	{
+		*out = ((pIn[0]) << 8) | pIn[1];
+		(*in)+=2;
+
+		return 2;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >=2 )
+	{
+		*out = ((pIn[0]) << 8) | pIn[1];
+
+		(*in)+=2;
+
+		return 2;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >=4 )
+	{
+		*out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
+
+		(*in)+=4;
+
+		return 4;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n",  __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end)
+{
+	uint8_t *pIn = *in;
+
+	if((end - pIn) >=4 )
+	{
+		*out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
+
+		(*in)+=4;
+
+		return 4;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+/*
+inline void pusharray16(uint8_t **, uint16_t, uint32_t len)
+{
+}
+*/
+
+uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - (*in)) >= sizeof(uint16_t) * len)
+	{
+		uint32_t idx;
+		for(idx = 0; idx < len; ++idx)
+		{
+			if(!pull16(in, &out[idx], end))
+				return 0;
+		}
+
+		return sizeof(uint16_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - (*in)) >= sizeof(uint16_t) * len)
+	{
+		uint32_t idx;
+		for(idx = 0; idx < len; ++idx)
+		{
+			if(!pulls16(in, &out[idx], end))
+			return 0;
+		}
+
+		return sizeof(uint16_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - (*out)) >= sizeof(uint16_t) * len)
+	{
+		uint32_t idx;
+		for(idx = 0; idx < len; ++idx)
+		{
+			if(!push16(in[idx], out, end))
+				return 0;
+		}
+		return sizeof(uint16_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - (*out)) >= sizeof(uint16_t) * len)
+	{
+		uint32_t idx;
+		for(idx = 0; idx < len; ++idx)
+		{
+			pushs16(in[idx], out, end);
+		}
+		return sizeof(uint16_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - out) >= sizeof(uint8_t) * len)
+	{
+		memcpy(out, (*in), len);
+		(*in)+=len;
+
+		return sizeof(uint8_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end)
+{
+	if(len == 0)
+		return 1;
+
+	if(len > max_len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len);
+		return 0;
+	}
+
+	if((end - (*out)) >= sizeof(uint8_t) * len)
+	{
+		memcpy((*out), in, len);
+		(*out)+=len;
+
+		return sizeof(uint8_t) * len;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+		return 0;
+	}
+}
+
+uint8_t packarray(void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t **ppwritepackedmsg, uint8_t *end, pack_array_elem_fn fn)
+{
+	if(count > max_count)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count);
+		return 0;
+	}
+
+	uint16_t i = 0;
+	for(i = 0; i < count; ++i)
+	{
+		if((fn)(array, ppwritepackedmsg, end) == 0)
+			return 0;
+
+		array += array_element_size;
+	}
+
+	return 1;
+}
+
+uint8_t unpackarray(uint8_t **ppReadPackedMsg, void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn)
+{
+	if(count > max_count)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count);
+		return 0;
+	}
+
+	uint16_t i = 0;
+	for(i = 0; i < count; ++i)
+	{
+		if((fn)(array, ppReadPackedMsg, end) == 0)
+			return 0;
+
+		array += array_element_size;
+	}
+
+	return 1;
+}
+
+
+uint32_t pack_vendor_extension_tlv(nfapi_tl_t* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	if(ve != 0 && config != 0)
+	{
+		if(config->pack_vendor_extension_tlv)
+		{
+
+			uint8_t* pStartOfTlv = *ppWritePackedMsg;
+			if(pack_tl(ve, ppWritePackedMsg, end) == 0)
+				return 0;
+
+			uint8_t* pStartOfValue = *ppWritePackedMsg;
+			if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0)
+				return 0;
+
+			ve->length = (*ppWritePackedMsg) - pStartOfValue;
+
+			pack_tl(ve, &pStartOfTlv, end);
+
+			return 1;
+
+		}
+	}
+	return 1;
+}
+
+uint32_t unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve_tlv)
+{
+	if(ve_tlv != 0 && config != 0)
+	{
+		if(config->unpack_vendor_extension_tlv)
+		{
+			return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config);
+		}
+	}
+	return 1;
+}
+
+uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end ,nfapi_p7_codec_config_t* config)
+{
+	if(ve != 0 && config != 0)
+	{
+		if(config->pack_vendor_extension_tlv)
+		{
+			uint8_t* pStartOfTlv = *ppWritePackedMsg;
+			if(pack_tl(ve, ppWritePackedMsg, end) == 0)
+				return 0;
+
+			uint8_t* pStartOfValue = *ppWritePackedMsg;
+			if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0)
+				return 0;
+
+			ve->length = (*ppWritePackedMsg) - pStartOfValue;
+
+			pack_tl(ve, &pStartOfTlv, end);
+
+			return 1;
+			
+		}
+	}
+	return 1;
+}
+
+int unpack_p7_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve_tlv)
+{
+	if(ve_tlv != 0 && config != 0)
+	{
+		if(config->unpack_vendor_extension_tlv)
+		{
+			return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config);
+		}
+	}
+	return 1;
+}
+
+
+uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return (push16(tl->tag, ppWritePackedMsg, end) &&
+			push16(tl->length, ppWritePackedMsg, end));
+}
+
+uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end)
+{
+	return (pull16(ppReadPackedMsg, &tl->tag, end) &&
+			pull16(ppReadPackedMsg, &tl->length, end));
+}
+
+int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve)
+{
+	nfapi_tl_t generic_tl;
+	uint8_t numBadTags = 0;
+	uint16_t idx = 0;
+
+	while ((uint8_t*)(*ppReadPackedMsg) < end)
+	{
+		// unpack the tl and process the values accordingly
+		if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+			return 0;
+
+		uint8_t tagMatch = 0;
+
+		uint8_t* pStartOfValue = *ppReadPackedMsg;
+
+		for(idx = 0; idx < size; ++idx)
+		{
+			if(unpack_fns[idx].tag == generic_tl.tag)
+			{
+				tagMatch = 1;
+				nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv);
+				tl->tag = generic_tl.tag;
+				tl->length = generic_tl.length;
+
+				int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end);
+
+				if(result == 0)
+				{
+					return 0;
+				}
+
+				// check if the length was right;
+				if(tl->length != (*ppReadPackedMsg - pStartOfValue))
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue));
+				}
+			}
+		}
+
+		if(tagMatch == 0)
+		{
+
+			if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && 
+			   generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE)
+			{
+				int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve);
+				if(result == 0)
+				{
+					// got tot the end.
+					return 0;
+				}
+				else if(result < 0)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag);
+
+					if (++numBadTags > MAX_BAD_TAG)
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+						return 0;
+					}
+
+					if((end - *ppReadPackedMsg) >= generic_tl.length)
+					{
+						// Advance past the unknown TLV
+						(*ppReadPackedMsg) += generic_tl.length;
+					}
+					else
+					{
+						// go to the end
+						return 0;
+					}
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag);
+
+				if (++numBadTags > MAX_BAD_TAG)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+					return 0;
+				}
+
+				if((end - *ppReadPackedMsg) >= generic_tl.length)
+				{
+					// Advance past the unknown TLV
+					(*ppReadPackedMsg) += generic_tl.length;
+				}
+				else
+				{
+					// go to the end
+					return 0;
+				}
+			}
+
+		}
+	}
+
+	return 1;
+}
+int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve)
+{
+	nfapi_tl_t generic_tl;
+	uint8_t numBadTags = 0;
+	uint16_t idx = 0;
+
+	while ((uint8_t*)(*ppReadPackedMsg) < end)
+	{
+		// unpack the tl and process the values accordingly
+		if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+			return 0;
+
+		uint8_t tagMatch = 0;
+
+		uint8_t* pStartOfValue = *ppReadPackedMsg;
+
+		for(idx = 0; idx < size; ++idx)
+		{
+			if(unpack_fns[idx].tag == generic_tl.tag)
+			{
+				tagMatch = 1;
+				nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv);
+				tl->tag = generic_tl.tag;
+				tl->length = generic_tl.length;
+
+				int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end , config);
+
+				if(result == 0)
+				{
+					return  0;
+				}
+
+				// check if the length was right;
+				if(tl->length != (*ppReadPackedMsg - pStartOfValue))
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue));
+				}
+			}
+		}
+
+		if(tagMatch == 0)
+		{
+
+			if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && 
+			   generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE)
+			{
+				int result = unpack_p7_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve);
+				if(result == 0)
+				{
+					// got to end
+					return 0;
+				}
+				else if(result < 0)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag);
+
+					if (++numBadTags > MAX_BAD_TAG)
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+						return -1;
+					}
+
+					if((end - *ppReadPackedMsg) >= generic_tl.length)
+					{
+						// Advance past the unknown TLV
+						(*ppReadPackedMsg) += generic_tl.length;
+					}
+					else
+					{
+						// got ot the dn
+						return 0;
+					}
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag);
+
+				if (++numBadTags > MAX_BAD_TAG)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+					return -1;
+				}
+
+				if((end - *ppReadPackedMsg) >= generic_tl.length)
+				{
+					// Advance past the unknown TLV
+					(*ppReadPackedMsg) += generic_tl.length;
+				}
+				else
+				{
+					// got ot the dn
+					return 0;
+				}
+
+			}
+
+		}
+	}
+
+	return 1;
+}
+
+// This intermediate function deals with calculating the length of the value
+// and writing into the tlv header.
+uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn)
+{
+	nfapi_tl_t* tl = (nfapi_tl_t*)tlv;
+
+	// If the tag is defined
+	if(tl->tag == tag)
+	{
+		uint8_t* pStartOfTlv = *ppWritePackedMsg;
+
+		// write a dumy tlv header
+		if(pack_tl(tl, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Record the start of the value
+		uint8_t* pStartOfValue = *ppWritePackedMsg;
+
+		// pack the tlv value
+		if(fn(tlv, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// calculate the length of the value and rewrite the tl header
+		tl->length = (*ppWritePackedMsg) - pStartOfValue;
+
+		// rewrite the header with the correct length
+		pack_tl(tl, &pStartOfTlv, end);
+	}
+	else
+	{
+		if(tl->tag != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", tl->tag, tag);
+		}
+                else
+                {
+			//NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag);
+                }
+	}
+
+	return 1;
+}
+
+const char* nfapi_error_code_to_str(nfapi_error_code_e value)
+{
+	switch(value)
+	{
+		case NFAPI_MSG_OK:
+			return "NFAPI_MSG_OK";
+		case NFAPI_MSG_INVALID_STATE:
+			return "NFAPI_MSG_INVALID_STATE";
+		case NFAPI_MSG_INVALID_CONFIG:
+			return "NFAPI_MSG_INVALID_CONFIG";
+		case NFAPI_SFN_OUT_OF_SYNC:
+			return "NFAPI_SFN_OUT_OF_SYNC";
+		case NFAPI_MSG_SUBFRAME_ERR:
+			return "NFAPI_MSG_SUBFRAME_ERR";
+		case NFAPI_MSG_BCH_MISSING:
+			return "NFAPI_MSG_BCH_MISSING";
+		case NFAPI_MSG_INVALID_SFN:
+			return "NFAPI_MSG_INVALID_SFN";
+		case NFAPI_MSG_HI_ERR:
+			return "NFAPI_MSG_HI_ERR";
+		case NFAPI_MSG_TX_ERR:
+			return "NFAPI_MSG_TX_ERR";
+		default:
+			return "UNKNOWN";
+	}
+}
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
new file mode 100644
index 0000000000..1eb85e6254
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
@@ -0,0 +1,2084 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <arpa/inet.h> // need for uintptr_t?
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <nfapi_interface.h>
+#include <nfapi.h>
+#include <debug.h>
+
+static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd)
+{
+	if (msgEnd < msgHead)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd);
+		return 0;
+	}
+
+	return (msgEnd - msgHead);
+}
+
+static uint8_t pack_opaque_data_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv;
+	return pusharray8(value->value, NFAPI_MAX_OPAQUE_DATA, value->length, ppWritePackedMsg, end);
+}
+
+static uint8_t unpack_opaque_data_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv;
+	value->length = value->tl.length;
+	if(value->length <= NFAPI_MAX_OPAQUE_DATA)
+	{
+		if(!pullarray8(ppReadPackedMsg, value->value, NFAPI_MAX_OPAQUE_DATA, value->length, end))
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Opaque date to long %d \n", value->length);
+		return 0;
+	}
+
+	return 1;
+
+}
+
+static uint8_t pack_lte_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv;
+
+	return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) &&
+			push16(value->measurement_period, ppWritePackedMsg, end) &&
+			push8(value->bandwidth, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_earfcns, ppWritePackedMsg, end) &&
+			pusharray16(value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_utran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv;
+
+	return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) &&
+			push16(value->measurement_period, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_uarfcns, ppWritePackedMsg, end) &&
+			pusharray16(value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_geran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) &&
+		 push16(value->measurement_period, ppWritePackedMsg, end) &&
+		 push32(value->timeout, ppWritePackedMsg, end) &&
+		 push8(value->number_of_arfcns, ppWritePackedMsg, end)))
+		return 0;
+
+	for(;idx < value->number_of_arfcns; ++idx)
+	{
+		if(!(push16(value->arfcn[idx].arfcn, ppWritePackedMsg, end) &&
+			push8(value->arfcn[idx].direction, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_nb_iot_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) &&
+		 push16(value->measurement_period, ppWritePackedMsg, end) &&
+		 push32(value->timeout, ppWritePackedMsg, end) &&
+		 push8(value->number_of_earfcns, ppWritePackedMsg, end)))
+		return 0;
+
+	for(;idx < value->number_of_earfcns; ++idx)
+	{
+		if(!(push16(value->earfcn[idx].earfcn, ppWritePackedMsg, end) &&
+			 push8(value->earfcn[idx].number_of_ro_dl, ppWritePackedMsg, end)))
+			return 0;
+			
+		uint8_t ro_dl_idx = 0;
+		for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx)
+		{
+			if(!push8(value->earfcn[idx].ro_dl[ro_dl_idx], ppWritePackedMsg, end))
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+
+static uint8_t pack_rssi_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg;
+
+	if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	switch(pNfapiMsg->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+			if(pack_tlv(NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, ppWritePackedMsg, end, &pack_lte_rssi_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_UTRAN:
+			if(pack_tlv(NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, ppWritePackedMsg, end, &pack_utran_rssi_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_GERAN:
+			if(pack_tlv(NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, ppWritePackedMsg, end, &pack_geran_rssi_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_NB_IOT:
+			if(pack_tlv(NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, ppWritePackedMsg, end, &pack_nb_iot_rssi_request_value) == 0)
+				return 0;
+			break;
+	}
+
+	return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+static uint8_t pack_rssi_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_rssi_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv;
+
+	return (push16(value->number_of_rssi, ppWritePackedMsg, end) &&
+			pusharrays16(value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_rssi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg;
+
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, ppWritePackedMsg, end, &pack_rssi_indication_body_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+
+static uint8_t pack_lte_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push8(value->measurement_bandwidth,  ppWritePackedMsg, end) &&
+			push8(value->exhaustive_search, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_pci, ppWritePackedMsg, end) &&
+			pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_utran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)msg;
+
+	return (push16(value->uarfcn, ppWritePackedMsg, end) &&
+			push8(value->exhaustive_search, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_psc, ppWritePackedMsg, end) &&
+			pusharray16(value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_geran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)msg;
+
+	return (push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_arfcn, ppWritePackedMsg, end) &&
+			pusharray16(value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_nb_iot_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push8(value->ro_dl, ppWritePackedMsg, end) &&
+			push8(value->exhaustive_search, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end) &&
+			push8(value->number_of_pci, ppWritePackedMsg, end) &&
+			pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_cell_search_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg;
+
+	if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	switch(pNfapiMsg->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+			{
+				if(pack_tlv(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, ppWritePackedMsg, end, &pack_lte_cell_search_request_value) == 0)
+					return 0;
+			}
+			break;
+		case NFAPI_RAT_TYPE_UTRAN:
+			{
+				if(pack_tlv(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, ppWritePackedMsg, end, &pack_utran_cell_search_request_value) == 0)
+					return 0;
+			}
+			break;
+		case NFAPI_RAT_TYPE_GERAN:
+			{
+				if(pack_tlv(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, ppWritePackedMsg, end, &pack_geran_cell_search_request_value) == 0)
+					return 0;
+			}
+			break;
+		case NFAPI_RAT_TYPE_NB_IOT:
+			{
+				if(pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, ppWritePackedMsg, end, &pack_nb_iot_cell_search_request_value) == 0)
+					return 0;
+			}
+			break;
+	};
+	
+	return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_cell_search_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lte_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)msg;
+	uint16_t idx = 0;
+
+	if(push16(value->number_of_lte_cells_found, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	for(idx = 0; idx < value->number_of_lte_cells_found; ++idx)
+	{
+		if(!(push16(value->lte_found_cells[idx].pci, ppWritePackedMsg, end) &&
+			 push8(value->lte_found_cells[idx].rsrp, ppWritePackedMsg, end) &&
+			 push8(value->lte_found_cells[idx].rsrq, ppWritePackedMsg, end) &&
+			 pushs16(value->lte_found_cells[idx].frequency_offset, ppWritePackedMsg, end)))
+			return 0;
+	}
+	return 1;
+}
+
+static uint8_t pack_utran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)msg;
+	uint16_t idx = 0;
+
+	if(push16(value->number_of_utran_cells_found, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	for(idx = 0; idx < value->number_of_utran_cells_found; ++idx)
+	{
+		if(!(push16(value->utran_found_cells[idx].psc, ppWritePackedMsg, end) &&
+			 push8(value->utran_found_cells[idx].rscp, ppWritePackedMsg, end) &&
+			 push8(value->utran_found_cells[idx].ecno, ppWritePackedMsg, end) &&
+			 pushs16(value->utran_found_cells[idx].frequency_offset, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_geran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)msg;
+	uint16_t idx = 0;
+
+	if(push16(value->number_of_gsm_cells_found, ppWritePackedMsg, end) == 0)
+		return 0;
+ 
+	for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx)
+	{
+		if(!(push16(value->gsm_found_cells[idx].arfcn, ppWritePackedMsg, end) &&
+			 push8(value->gsm_found_cells[idx].bsic, ppWritePackedMsg, end) &&
+			 push8(value->gsm_found_cells[idx].rxlev, ppWritePackedMsg, end) &&
+			 push8(value->gsm_found_cells[idx].rxqual, ppWritePackedMsg, end) &&
+			 pushs16(value->gsm_found_cells[idx].frequency_offset, ppWritePackedMsg, end) &&
+			 push32(value->gsm_found_cells[idx].sfn_offset, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_nb_iot_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)msg;
+	uint16_t idx = 0;
+
+	if(push16(value->number_of_nb_iot_cells_found, ppWritePackedMsg, end) == 0)
+		return 0;
+ 
+	for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx)
+	{
+		if(!(push16(value->nb_iot_found_cells[idx].pci, ppWritePackedMsg, end) &&
+			 push8(value->nb_iot_found_cells[idx].rsrp, ppWritePackedMsg, end) &&
+			 push8(value->nb_iot_found_cells[idx].rsrq, ppWritePackedMsg, end) &&
+			 pushs16(value->nb_iot_found_cells[idx].frequency_offset, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+static uint8_t pack_cell_search_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg;
+
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, ppWritePackedMsg, end, &pack_lte_cell_search_indication_value) &&
+			pack_tlv(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, ppWritePackedMsg, end, &pack_utran_cell_search_indication_value) &&
+			pack_tlv(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, ppWritePackedMsg, end, &pack_geran_cell_search_indication_value) &&
+			pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) &&
+			pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, ppWritePackedMsg, end, &pack_nb_iot_cell_search_indication_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+
+static uint8_t pack_lte_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push16(value->pci, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_utran_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)msg;
+
+	return (push16(value->uarfcn, ppWritePackedMsg, end) &&
+			push16(value->psc, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_nb_iot_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push8(value->ro_dl, ppWritePackedMsg, end) &&
+			push16(value->pci, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_broadcast_detect_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t * end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg;
+
+	if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	switch(pNfapiMsg->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+			if(pack_tlv(NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, ppWritePackedMsg, end ,&pack_lte_broadcast_detect_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_UTRAN:
+			if(pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, ppWritePackedMsg, end, &pack_utran_broadcast_detect_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_NB_IOT:
+			if(pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_request_value) == 0)
+				return 0;
+			break;
+			
+	}
+
+	return (pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_broadcast_detect_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lte_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)msg;
+
+	return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) &&
+			push16(value->mib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) &&
+			push32(value->sfn_offset, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_utran_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)msg;
+
+	return (push16(value->mib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) &&
+			push32(value->sfn_offset, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_nb_iot_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)msg;
+
+	return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) &&
+			push16(value->mib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) &&
+			push32(value->sfn_offset, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_broadcast_detect_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg;
+
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, ppWritePackedMsg, end, &pack_lte_broadcast_detect_indication_value) &&
+			pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, ppWritePackedMsg, end, &pack_utran_broadcast_detect_indication_value) &&
+			pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) &&
+			pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_indication_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lte_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push16(value->pci, ppWritePackedMsg, end) &&
+			push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) &&
+			push8(value->phich_configuration, ppWritePackedMsg, end) &&
+			push8(value->number_of_tx_antenna, ppWritePackedMsg, end) &&
+			push8(value->retry_count, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_nb_iot_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)msg;
+
+	return (push16(value->earfcn, ppWritePackedMsg, end) &&
+			push8(value->ro_dl, ppWritePackedMsg, end) &&
+			push16(value->pci, ppWritePackedMsg, end) &&
+			push8(value->scheduling_info_sib1_nb, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_system_information_schedule_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg;
+
+	if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	switch(pNfapiMsg->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+			if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, ppWritePackedMsg, end, &pack_lte_system_information_schedule_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_NB_IOT:
+			if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_schedule_request_value) == 0)
+				return 0;
+			break;
+	}
+
+	return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+
+static uint8_t pack_system_information_schedule_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lte_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)msg;
+
+	return (push8(value->sib_type, ppWritePackedMsg, end) &&
+			push16(value->sib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_nb_iot_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)msg;
+
+	return (push8(value->sib_type, ppWritePackedMsg, end) &&
+			push16(value->sib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_system_information_schedule_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg;
+
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) &&
+			pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lte_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)msg;
+	uint16_t idx = 0;
+
+	if(!(push16(value->earfcn, ppWritePackedMsg, end) &&
+		 push16(value->pci, ppWritePackedMsg, end) &&
+		 push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) &&
+		 push8(value->phich_configuration, ppWritePackedMsg, end) &&
+		 push8(value->number_of_tx_antenna, ppWritePackedMsg, end) &&
+		 push8(value->number_of_si_periodicity, ppWritePackedMsg, end)))
+		return 0;
+
+	for(idx = 0; idx < value->number_of_si_periodicity; ++idx)
+	{
+		if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) &&
+			 push8(value->si_periodicity[idx].si_index, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return (push8(value->si_window_length, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+static uint8_t pack_utran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)msg;
+
+	return (push16(value->uarfcn, ppWritePackedMsg, end) &&
+			push16(value->psc, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+static uint8_t pack_geran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)msg;
+
+	return (push16(value->arfcn, ppWritePackedMsg, end) &&
+			push8(value->bsic, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+static uint8_t pack_nb_iot_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)msg;
+	uint16_t idx = 0;
+
+	if(!(push16(value->earfcn, ppWritePackedMsg, end) &&
+		 push8(value->ro_dl, ppWritePackedMsg, end) &&
+		 push16(value->pci, ppWritePackedMsg, end) &&
+		 push8(value->number_of_si_periodicity, ppWritePackedMsg, end)))
+		return 0;
+
+	for(idx = 0; idx < value->number_of_si_periodicity; ++idx)
+	{
+		if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) &&
+			 push8(value->si_periodicity[idx].si_repetition_pattern, ppWritePackedMsg, end) &&
+			 push8(value->si_periodicity[idx].si_tb_size, ppWritePackedMsg, end) &&
+			 push8(value->si_periodicity[idx].number_of_si_index, ppWritePackedMsg, end)))
+			return 0;
+			
+		uint8_t si_idx;	
+		for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx)
+		{
+			if(!(push8(value->si_periodicity[idx].si_index[si_idx], ppWritePackedMsg, end)))
+				return 0;
+		}
+	}
+
+	return (push8(value->si_window_length, ppWritePackedMsg, end) &&
+			push32(value->timeout, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_system_information_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg;
+
+	if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	switch(pNfapiMsg->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+			if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, ppWritePackedMsg, end, &pack_lte_system_information_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_UTRAN:
+			if(pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, ppWritePackedMsg, end, &pack_utran_system_information_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_GERAN:
+			if(pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, ppWritePackedMsg, end, &pack_geran_system_information_request_value) == 0)
+				return 0;
+			break;
+		case NFAPI_RAT_TYPE_NB_IOT:
+			if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_request_value) == 0)
+				return 0;
+			break;
+	}
+
+	return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_system_information_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end,  nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_utran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)msg;
+	
+	return (push16(value->sib_length, ppWritePackedMsg, end) &&
+			pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_geran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)msg;
+
+	return (push16(value->si_length, ppWritePackedMsg, end) &&
+			pusharray8(value->si, NFAPI_MAX_SIB_LENGTH, value->si_length, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_system_information_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) &&
+			pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, ppWritePackedMsg, end, &pack_utran_system_information_indication_value) &&
+			pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, ppWritePackedMsg, end, &pack_geran_system_information_indication_value) &&
+			pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+	
+static uint8_t pack_nmm_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg;
+
+	return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_nmm_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg;
+	
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t unpack_lte_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	//int result = 0;
+	nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) &&
+		 pull16(ppReadPackedMsg, &value->measurement_period, end) &&
+		 pull8(ppReadPackedMsg, &value->bandwidth, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_earfcns, end)))
+		return 0;
+
+	if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns);
+		return 0;
+	}
+
+	return 1;
+
+}
+
+static uint8_t unpack_utran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) &&
+		 pull16(ppReadPackedMsg, &value->measurement_period, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_uarfcns, end)))
+		return 0;
+
+	if(value->number_of_uarfcns <= NFAPI_MAX_CARRIER_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More UARFCN's than we can decode %d \n", value->number_of_uarfcns);
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_geran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) &&
+	 	 pull16(ppReadPackedMsg, &value->measurement_period, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_arfcns, end)))
+		return 0;
+
+	if(value->number_of_arfcns <= NFAPI_MAX_CARRIER_LIST)
+	{
+		for(idx = 0; idx < value->number_of_arfcns; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->arfcn[idx].arfcn, end) &&
+			 	 pull8(ppReadPackedMsg, &value->arfcn[idx].direction, end)))
+				return 0;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcns);
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) &&
+	 	 pull16(ppReadPackedMsg, &value->measurement_period, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_earfcns, end)))
+		return 0;
+
+	if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST)
+	{
+		for(idx = 0; idx < value->number_of_earfcns; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->earfcn[idx].earfcn, end) &&
+			 	 pull8(ppReadPackedMsg, &value->earfcn[idx].number_of_ro_dl, end)))
+				return 0;
+				
+			if(value->earfcn[idx].number_of_ro_dl <= NFAPI_MAX_RO_DL)
+			{
+				uint8_t ro_dl_idx = 0;
+				for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx)
+				{
+					if(!pull8(ppReadPackedMsg, &value->earfcn[idx].ro_dl[ro_dl_idx], end))
+						return 0;
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ROdl's than we can decode %d \n", value->earfcn[idx].number_of_ro_dl);
+				return 0;
+			}
+			
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns);
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_rssi_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, &unpack_lte_rssi_request_value},
+		{ NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, &unpack_utran_rssi_request_value},
+		{ NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, &unpack_geran_rssi_request_value},
+		{ NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, &unpack_nb_iot_rssi_request_value},
+	};
+
+	int result = 0;
+
+	result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) &&
+			  unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+
+
+	// Verify that the rat type and the tlv match
+	if(result == 1 &&
+	   !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_rssi_request.tl.tag == NFAPI_LTE_RSSI_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_rssi_request.tl.tag == NFAPI_UTRAN_RSSI_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_rssi_request.tl.tag == NFAPI_GERAN_RSSI_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_rssi_request.tl.tag == NFAPI_NB_IOT_RSSI_REQUEST_TAG)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_rssi_request.tl.tag);
+		result = 0;
+	}
+	
+	return result;
+}
+
+static uint8_t unpack_rssi_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+}
+
+static uint8_t unpack_rssi_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_rssi, end) == 0)
+		return 0;
+
+	if(value->number_of_rssi <= NFAPI_MAX_RSSI)
+	{
+		if(pullarrays16(ppReadPackedMsg, value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More RSSI's than we can decode %d \n", value->number_of_rssi);
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_rssi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, &unpack_rssi_indication_value},
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+		    unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)tlv;
+
+	if(!(pull16(ppReadPackedMsg, &value->earfcn, end) &&
+		 pull8(ppReadPackedMsg, &value->measurement_bandwidth, end) &&
+		 pull8(ppReadPackedMsg, &value->exhaustive_search, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_pci, end)))
+		return 0;
+
+	if(value->number_of_pci <= NFAPI_MAX_PCI_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_utran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)tlv;
+
+	if(!(pull16(ppReadPackedMsg, &value->uarfcn, end) &&
+		 pull8(ppReadPackedMsg, &value->exhaustive_search, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_psc, end)))
+		return 0;
+
+	if(value->number_of_psc <= NFAPI_MAX_PSC_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PSC's than we can decode %d \n", value->number_of_psc);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_geran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)tlv;
+
+	if(!(pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_arfcn, end)))
+		return 0;
+
+	if(value->number_of_arfcn <= NFAPI_MAX_ARFCN_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcn);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_nb_iot_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)tlv;
+
+	if(!(pull16(ppReadPackedMsg, &value->earfcn, end) &&
+		 pull8(ppReadPackedMsg, &value->ro_dl, end) &&
+		 pull8(ppReadPackedMsg, &value->exhaustive_search, end) &&
+		 pull32(ppReadPackedMsg, &value->timeout, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_pci, end)))
+		return 0;
+
+	if(value->number_of_pci <= NFAPI_MAX_PCI_LIST)
+	{
+		if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0)
+			return 0;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_cell_search_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, &unpack_lte_cell_search_request_value},
+		{ NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, &unpack_utran_cell_search_request_value},
+		{ NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, &unpack_geran_cell_search_request_value},
+		{ NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, &unpack_nb_iot_cell_search_request_value},
+	};
+
+	int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) &&
+			  unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+	// Verify that the rat type and the tlv match
+	if(result == 1 &&
+	   !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_cell_search_request.tl.tag == NFAPI_LTE_CELL_SEARCH_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_cell_search_request.tl.tag == NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_cell_search_request.tl.tag == NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_cell_search_request.tl.tag == NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_cell_search_request.tl.tag);
+		result = 0;
+	}
+	
+	return result;
+}
+
+static uint8_t unpack_cell_search_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)tlv;
+
+	uint16_t idx = 0;
+	if(pull16(ppReadPackedMsg, &value->number_of_lte_cells_found, end) == 0)
+		return 0;
+
+	if(value->number_of_lte_cells_found <= NFAPI_MAX_LTE_CELLS_FOUND)
+	{
+		for(idx = 0; idx < value->number_of_lte_cells_found; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->lte_found_cells[idx].pci, end) &&
+				 pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrp, end) &&
+				 pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrq, end) &&
+				 pulls16(ppReadPackedMsg, &value->lte_found_cells[idx].frequency_offset, end)))
+				return 0;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found LTE cells than we can decode %d \n", value->number_of_lte_cells_found);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_utran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)tlv;
+
+	uint16_t idx = 0;
+	if(pull16(ppReadPackedMsg, &value->number_of_utran_cells_found, end) == 0)
+		return 0;
+
+	if(value->number_of_utran_cells_found <= NFAPI_MAX_UTRAN_CELLS_FOUND)
+	{
+		for(idx = 0; idx < value->number_of_utran_cells_found; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->utran_found_cells[idx].psc, end) &&
+				 pull8(ppReadPackedMsg, &value->utran_found_cells[idx].rscp, end) &&
+				 pull8(ppReadPackedMsg, &value->utran_found_cells[idx].ecno, end) &&
+				 pulls16(ppReadPackedMsg, &value->utran_found_cells[idx].frequency_offset, end)))
+				return 0;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found UTRAN cells than we can decode %d \n", value->number_of_utran_cells_found);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_geran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)tlv;
+
+	uint16_t idx = 0;
+	if(pull16(ppReadPackedMsg, &value->number_of_gsm_cells_found, end) == 0)
+		return 0;
+
+	if(value->number_of_gsm_cells_found <= NFAPI_MAX_GSM_CELLS_FOUND)
+	{
+		for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->gsm_found_cells[idx].arfcn, end) &&
+				 pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].bsic, end) &&
+				 pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxlev, end) &&
+				 pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxqual, end) &&
+				 pulls16(ppReadPackedMsg, &value->gsm_found_cells[idx].frequency_offset, end) &&
+				 pull32(ppReadPackedMsg, &value->gsm_found_cells[idx].sfn_offset, end)))
+				return 0;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found GSM cells than we can decode %d \n", value->number_of_gsm_cells_found);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_nb_iot_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)tlv;
+
+	uint16_t idx = 0;
+	if(pull16(ppReadPackedMsg, &value->number_of_nb_iot_cells_found, end) == 0)
+		return 0;
+
+	if(value->number_of_nb_iot_cells_found <= NFAPI_MAX_NB_IOT_CELLS_FOUND)
+	{
+		for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx)
+		{
+			if(!(pull16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].pci, end) &&
+				 pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrp, end) &&
+				 pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrq, end) &&
+				 pulls16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].frequency_offset, end)))
+				return 0;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found NB_IOT cells than we can decode %d \n", value->number_of_nb_iot_cells_found);
+		return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_cell_search_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, &unpack_lte_cell_search_indication_value},
+		{ NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, &unpack_utran_cell_search_indication_value},
+		{ NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, &unpack_geran_cell_search_indication_value},
+		{ NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value},
+		{ NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, &unpack_nb_iot_cell_search_indication_value},
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+		
+}
+
+static uint8_t unpack_lte_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->earfcn, end) &&
+			pull16(ppReadPackedMsg, &value->pci, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_utran_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->uarfcn, end) &&
+			pull16(ppReadPackedMsg, &value->psc, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_nb_iot_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->earfcn, end) &&
+			pull8(ppReadPackedMsg, &value->ro_dl, end) &&
+			pull16(ppReadPackedMsg, &value->pci, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_broadcast_detect_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, &unpack_lte_broadcast_detect_request_value},
+		{ NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, &unpack_utran_broadcast_detect_request_value},
+		{ NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value},
+		{ NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, &unpack_nb_iot_broadcast_detect_request_value}
+	};
+
+	return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) &&	
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_broadcast_detect_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) &&
+	 	 pull16(ppReadPackedMsg, &value->mib_length, end)))
+		return 0;
+
+	if(value->mib_length > NFAPI_MAX_MIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length);
+		return 0;
+	}
+	
+	return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) &&
+			pull32(ppReadPackedMsg, &value->sfn_offset, end));
+}
+
+static uint8_t unpack_utran_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->mib_length, end) == 0)
+		return 0;
+
+	if(value->mib_length > NFAPI_MAX_MIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length);
+		return 0;
+	}
+
+	return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) &&
+			pull32(ppReadPackedMsg, &value->sfn_offset, end));
+}
+
+static uint8_t unpack_nb_iot_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && 
+		 pull16(ppReadPackedMsg, &value->mib_length, end)))
+		return 0;
+
+	if(value->mib_length > NFAPI_MAX_MIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length);
+		return 0;
+	}
+
+	return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) &&
+			pull32(ppReadPackedMsg, &value->sfn_offset, end));
+}
+
+static uint8_t unpack_broadcast_detect_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, &unpack_lte_broadcast_detect_indication_value},
+		{ NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, &unpack_utran_broadcast_detect_indication_value},
+		{ NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, &unpack_nb_iot_broadcast_detect_indication_value},
+		{ NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value}
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->earfcn, end) &&
+			pull16(ppReadPackedMsg, &value->pci, end) &&
+			pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) &&
+			pull8(ppReadPackedMsg, &value->phich_configuration, end) &&
+			pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) &&
+			pull8(ppReadPackedMsg, &value->retry_count, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_nb_iot_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->earfcn, end) &&
+			pull8(ppReadPackedMsg, &value->ro_dl, end) &&	
+			pull16(ppReadPackedMsg, &value->pci, end) &&
+			pull8(ppReadPackedMsg, &value->scheduling_info_sib1_nb, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_system_information_schedule_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, &unpack_lte_system_information_schedule_request_value},
+		{ NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, &unpack_nb_iot_system_information_schedule_request_value},
+		{ NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value}
+	};
+
+	return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_system_information_schedule_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->sib_type, end) &&
+		 pull16(ppReadPackedMsg, &value->sib_length, end)))
+		return 0;
+
+	if(value->sib_length > NFAPI_MAX_SIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length);
+		return 0;
+	}
+	
+	if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH,  value->sib_length, end) == 0)
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_nb_iot_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->sib_type, end) &&
+		 pull16(ppReadPackedMsg, &value->sib_length, end)))
+		return 0;
+
+	if(value->sib_length > NFAPI_MAX_SIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length);
+		return 0;
+	}
+	
+	if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH,  value->sib_length, end) == 0)
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_system_information_schedule_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value},
+		{ NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value},
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lte_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(pull16(ppReadPackedMsg, &value->earfcn, end) &&
+		 pull16(ppReadPackedMsg, &value->pci, end) &&
+		 pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) &&
+		 pull8(ppReadPackedMsg, &value->phich_configuration, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end)))
+		return 0;
+
+	if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity);
+		return 0;
+	}
+
+	for(idx = 0; idx < value->number_of_si_periodicity; ++idx)
+	{
+		if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) &&
+			 pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index, end)))
+			return 0;
+	}
+
+	if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) &&
+	 	 pull32(ppReadPackedMsg, &value->timeout, end)))
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_utran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->uarfcn, end) &&
+			pull16(ppReadPackedMsg, &value->psc, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_geran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->arfcn, end) &&
+			pull8(ppReadPackedMsg, &value->bsic, end) &&
+			pull32(ppReadPackedMsg, &value->timeout, end));
+}
+
+static uint8_t unpack_nb_iot_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)tlv;
+	uint16_t idx = 0;
+
+	if(!(pull16(ppReadPackedMsg, &value->earfcn, end) &&
+		 pull8(ppReadPackedMsg, &value->ro_dl, end) &&
+		 pull16(ppReadPackedMsg, &value->pci, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end)))
+		return 0;
+
+	if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity);
+		return 0;
+	}
+
+	for(idx = 0; idx < value->number_of_si_periodicity; ++idx)
+	{
+		if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) &&
+			 pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_repetition_pattern, end) &&
+			 pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_tb_size, end) &&
+			 pull8(ppReadPackedMsg, &value->si_periodicity[idx].number_of_si_index, end)))
+			return 0;
+			
+		uint8_t si_idx;
+		for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx)
+		{
+			if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index[si_idx], end)))
+				return 0;
+			
+		}
+	}
+
+	if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) &&
+	 	 pull32(ppReadPackedMsg, &value->timeout, end)))
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_system_information_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, &unpack_lte_system_information_request_value},
+		{ NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, &unpack_utran_system_information_request_value},
+		{ NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, &unpack_geran_system_information_request_value},
+		{ NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, &unpack_nb_iot_system_information_request_value},
+		{ NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value}
+	};
+
+
+	int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) &&
+				  unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+	// Verify that the rat type and the tlv match
+	if(result == 1 &&
+	   !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_system_information_request.tl.tag == NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_system_information_request.tl.tag == NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG) ||
+	    (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_system_information_request.tl.tag == NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_system_information_request.tl.tag);
+		result = 0;
+	}
+	
+	return result;
+}
+
+static uint8_t unpack_system_information_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_utran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->sib_length, end) == 0)
+		return 0;
+
+	if(value->sib_length > NFAPI_MAX_SIB_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length);
+		return 0;
+	}
+	
+	if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0)
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_geran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->si_length, end) == 0)
+		return 0;
+
+	if(value->si_length > NFAPI_MAX_SI_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->si_length);
+		return 0;
+	}
+
+	if(pullarray8(ppReadPackedMsg, value->si, NFAPI_MAX_SI_LENGTH, value->si_length, end) == 0)
+		return 0;
+
+	return 1;
+}
+
+static uint8_t unpack_system_information_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value},
+		{ NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, &unpack_utran_system_information_indication_value},
+		{ NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, &unpack_geran_system_information_indication_value},
+		{ NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value},
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+}
+
+static uint8_t unpack_nmm_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension);
+}
+
+static uint8_t unpack_nmm_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+
+static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen)
+{
+	int retLen = 0;
+
+	switch (msgId)
+	{
+		case NFAPI_RSSI_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_rssi_request_t))
+				retLen = sizeof(nfapi_rssi_request_t);
+			break;
+
+		case NFAPI_RSSI_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_rssi_response_t))
+				retLen = sizeof(nfapi_rssi_response_t);
+			break;
+
+		case NFAPI_RSSI_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_rssi_indication_t))
+				retLen = sizeof(nfapi_rssi_indication_t);
+			break;
+
+		case NFAPI_CELL_SEARCH_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_cell_search_request_t))
+				retLen = sizeof(nfapi_cell_search_request_t);
+			break;
+
+		case NFAPI_CELL_SEARCH_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_cell_search_response_t))
+				retLen = sizeof(nfapi_cell_search_response_t);
+			break;
+
+		case NFAPI_CELL_SEARCH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_cell_search_indication_t))
+				retLen = sizeof(nfapi_cell_search_indication_t);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_request_t))
+				retLen = sizeof(nfapi_broadcast_detect_request_t);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_response_t))
+				retLen = sizeof(nfapi_broadcast_detect_response_t);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_indication_t))
+				retLen = sizeof(nfapi_broadcast_detect_indication_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_request_t))
+				retLen = sizeof(nfapi_system_information_schedule_request_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_response_t))
+				retLen = sizeof(nfapi_system_information_schedule_response_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_indication_t))
+				retLen = sizeof(nfapi_system_information_schedule_indication_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_request_t))
+				retLen = sizeof(nfapi_system_information_request_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_response_t))
+				retLen = sizeof(nfapi_system_information_response_t);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_system_information_indication_t))
+				retLen = sizeof(nfapi_system_information_indication_t);
+			break;
+
+		case NFAPI_NMM_STOP_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_nmm_stop_request_t))
+				retLen = sizeof(nfapi_nmm_stop_request_t);
+			break;
+
+		case NFAPI_NMM_STOP_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_nmm_stop_response_t))
+				retLen = sizeof(nfapi_nmm_stop_response_t);
+			break;
+
+		default:
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId);
+			break;
+	}
+
+	return retLen;
+}
+
+int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf;
+	uint8_t *end = pPackedBuf + packedBufLen;
+	uint8_t *pWritePackedMessage = pPackedBuf;
+	uint8_t *pPackedLengthField = &pWritePackedMessage[4];
+	uint32_t packedMsgLen;
+	uint16_t packedMsgLen16;
+
+	if (pMessageBuf == NULL || pPackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 Pack supplied pointers are null\n");
+		return -1;
+	}
+
+	// process the header
+	if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) &&
+		 push16(pMessageHeader->message_id, &pWritePackedMessage, end) &&
+		 push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) &&
+		 push16(pMessageHeader->spare, &pWritePackedMessage, end)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header\n");
+		return -1;
+	}
+
+	// look for the specific message
+	uint8_t result = 0;
+	switch (pMessageHeader->message_id)
+	{
+		case NFAPI_RSSI_REQUEST:
+			result = pack_rssi_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RSSI_RESPONSE:
+			result = pack_rssi_response(pMessageHeader, &pWritePackedMessage,  end,config);
+			break;
+
+		case NFAPI_RSSI_INDICATION:
+			result = pack_rssi_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_CELL_SEARCH_REQUEST:
+			result = pack_cell_search_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_CELL_SEARCH_RESPONSE:
+			result = pack_cell_search_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_CELL_SEARCH_INDICATION:
+			result = pack_cell_search_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_REQUEST:
+			result = pack_broadcast_detect_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_RESPONSE:
+			result = pack_broadcast_detect_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_INDICATION:
+			result = pack_broadcast_detect_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
+			result = pack_system_information_schedule_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE:
+			result = pack_system_information_schedule_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION:
+			result = pack_system_information_schedule_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_REQUEST:
+			result = pack_system_information_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_RESPONSE:
+			result = pack_system_information_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_INDICATION:
+			result = pack_system_information_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_NMM_STOP_REQUEST:
+			result = pack_nmm_stop_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_NMM_STOP_RESPONSE:
+			result = pack_nmm_stop_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		default:
+			{
+				if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MIN)
+				{
+					if(config && config->pack_p4_p5_vendor_extension)
+					{
+						result =(config->pack_p4_p5_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config);
+					}
+					else
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve encoder provided\n", __FUNCTION__, pMessageHeader->message_id);
+					}
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
+				}
+			}
+			break;
+	}	
+	
+	// return the packed length
+	if(result == 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Result is 0\n");
+		return -1;
+	}
+
+
+	// check for a valid message length
+	packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage);
+	if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen);
+		return -1;
+	}
+	else
+	{
+		packedMsgLen16 = (uint16_t)packedMsgLen;
+	}
+
+	// Update the message length in the header
+	if(push16(packedMsgLen16, &pPackedLengthField, end) == 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header lengt\n");
+		return -1;
+	}
+
+	return (packedMsgLen);
+
+}
+
+// Main unpack functions - public
+
+int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 header unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// process the headei
+	if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) &&
+		pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+		pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+		pull16(&pReadPackedMessage, &pMessageHeader->spare, end))
+		return -1;
+
+	return 0;
+}
+
+int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	int result = 0;
+	nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// clean the supplied buffer for - tag value blanking
+	(void)memset(pUnpackedBuf, 0, unpackedBufLen);
+
+	// process the header
+	if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) &&
+	 	 pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->spare, end)))
+		return -1;
+
+	// look for the specific message
+	switch (pMessageHeader->message_id)
+	{
+		case NFAPI_RSSI_REQUEST:
+			if (check_unpack_length(NFAPI_RSSI_REQUEST, unpackedBufLen))
+				result = unpack_rssi_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_RSSI_RESPONSE:
+			if (check_unpack_length(NFAPI_RSSI_RESPONSE, unpackedBufLen))
+				result = unpack_rssi_response(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_RSSI_INDICATION:
+			if (check_unpack_length(NFAPI_RSSI_INDICATION, unpackedBufLen))
+				result = unpack_rssi_indication(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_CELL_SEARCH_REQUEST:
+			if (check_unpack_length(NFAPI_CELL_SEARCH_REQUEST, unpackedBufLen))
+				result = unpack_cell_search_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_CELL_SEARCH_RESPONSE:
+			if (check_unpack_length(NFAPI_CELL_SEARCH_RESPONSE, unpackedBufLen))
+				result = unpack_cell_search_response(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_CELL_SEARCH_INDICATION:
+			if (check_unpack_length(NFAPI_CELL_SEARCH_INDICATION, unpackedBufLen))
+				result = unpack_cell_search_indication(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_BROADCAST_DETECT_REQUEST:
+			if (check_unpack_length(NFAPI_BROADCAST_DETECT_REQUEST, unpackedBufLen))
+				result = unpack_broadcast_detect_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_BROADCAST_DETECT_RESPONSE:
+			if (check_unpack_length(NFAPI_BROADCAST_DETECT_RESPONSE, unpackedBufLen))
+				result = unpack_broadcast_detect_response(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_BROADCAST_DETECT_INDICATION:
+			if (check_unpack_length(NFAPI_BROADCAST_DETECT_INDICATION, unpackedBufLen))
+				result = unpack_broadcast_detect_indication(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, unpackedBufLen))
+				result = unpack_system_information_schedule_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+			
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, unpackedBufLen))
+				result = unpack_system_information_schedule_response(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, unpackedBufLen))
+				result = unpack_system_information_schedule_indication(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_REQUEST:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_REQUEST, unpackedBufLen))
+				result = unpack_system_information_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_RESPONSE:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen))
+				result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result =  -1;
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_INDICATION:
+			if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen))
+				result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result =  -1;
+			break;
+
+		case NFAPI_NMM_STOP_REQUEST:
+			if (check_unpack_length(NFAPI_NMM_STOP_REQUEST, unpackedBufLen))
+				result = unpack_nmm_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		case NFAPI_NMM_STOP_RESPONSE:
+			if (check_unpack_length(NFAPI_NMM_STOP_RESPONSE, unpackedBufLen))
+				result = unpack_nmm_stop_response(&pReadPackedMessage, end , pMessageHeader, config);
+			else
+				result = -1;
+			break;
+
+		default:
+			if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && 
+			   pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+			{
+				if(config && config->unpack_p4_p5_vendor_extension)
+				{
+					result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id);
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
+			}
+			break;
+	}
+
+	if(result == 0)
+		return -1;
+
+	return result;
+}
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
new file mode 100644
index 0000000000..b3b9b53491
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
@@ -0,0 +1,1799 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <signal.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <nfapi_interface.h>
+#include <nfapi.h>
+#include <debug.h>
+
+
+// Pack routines
+
+static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_param_request_t* request = (nfapi_pnf_param_request_t*)msg;
+	return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+static uint8_t pack_pnf_param_general_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv;
+
+	return ( push8(value->nfapi_sync_mode, ppWritePackedMsg, end) &&
+			 push8(value->location_mode, ppWritePackedMsg, end) &&
+			 push16(value->location_coordinates_length, ppWritePackedMsg, end) &&
+			 pusharray8(value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, ppWritePackedMsg, end) &&
+			 push32(value->dl_config_timing, ppWritePackedMsg, end) &&
+			 push32(value->tx_timing, ppWritePackedMsg, end) &&
+			 push32(value->ul_config_timing, ppWritePackedMsg, end) &&
+			 push32(value->hi_dci0_timing, ppWritePackedMsg, end) &&
+			 push16(value->maximum_number_phys, ppWritePackedMsg, end) &&
+			 push16(value->maximum_total_bandwidth, ppWritePackedMsg, end) &&
+			 push8(value->maximum_total_number_dl_layers, ppWritePackedMsg, end) &&
+			 push8(value->maximum_total_number_ul_layers, ppWritePackedMsg, end) &&
+			 push8(value->shared_bands, ppWritePackedMsg, end) &&
+			 push8(value->shared_pa, ppWritePackedMsg, end) &&
+			 pushs16(value->maximum_total_power, ppWritePackedMsg, end) &&
+			 pusharray8(value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rf_config_info_t* rf = (nfapi_rf_config_info_t*)elem;
+
+	return (push16(rf->rf_config_index, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_pnf_phy_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t* end)
+{
+	nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem;
+
+	return (  push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+			  push16(phy->number_of_rfs, ppWritePackedMsg, end) &&
+			  packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) &&
+			  push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) &&
+			  packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) &&
+			  push16(phy->downlink_channel_bandwidth_supported, ppWritePackedMsg, end) &&
+			  push16(phy->uplink_channel_bandwidth_supported, ppWritePackedMsg, end) &&
+			  push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) &&
+			  push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) &&
+			  push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) &&
+			  push8(phy->nmm_modes_supported, ppWritePackedMsg, end));
+
+
+}
+
+static uint8_t pack_pnf_phy_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv;
+
+	return ( push16(value->number_of_phys, ppWritePackedMsg, end) &&
+			 packarray(value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_info));
+}
+
+static uint8_t pack_pnf_rf_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv;
+	uint16_t rf_index = 0;
+
+	if(push16(value->number_of_rfs, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	for(; rf_index < value->number_of_rfs; ++rf_index)
+	{
+		if( !(push16(value->rf[rf_index].rf_config_index, ppWritePackedMsg, end) &&
+			  push16(value->rf[rf_index].band, ppWritePackedMsg, end) &&
+			  pushs16(value->rf[rf_index].maximum_transmit_power, ppWritePackedMsg, end) &&
+			  pushs16(value->rf[rf_index].minimum_transmit_power, ppWritePackedMsg, end) &&
+			  push8(value->rf[rf_index].number_of_antennas_suppported, ppWritePackedMsg, end) &&
+			  push32(value->rf[rf_index].minimum_downlink_frequency, ppWritePackedMsg, end) &&
+			  push32(value->rf[rf_index].maximum_downlink_frequency, ppWritePackedMsg, end) &&
+			  push32(value->rf[rf_index].minimum_uplink_frequency, ppWritePackedMsg, end) &&
+			  push32(value->rf[rf_index].maximum_uplink_frequency, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+static uint8_t pack_pnf_phy_rel10_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem;
+
+	return(push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+		   push16(phy->transmission_mode_7_supported, ppWritePackedMsg, end) &&
+		   push16(phy->transmission_mode_8_supported, ppWritePackedMsg, end) &&
+		   push16(phy->two_antenna_ports_for_pucch, ppWritePackedMsg, end) &&
+		   push16(phy->transmission_mode_9_supported, ppWritePackedMsg, end) &&
+		   push16(phy->simultaneous_pucch_pusch, ppWritePackedMsg, end) &&
+		   push16(phy->four_layer_tx_with_tm3_and_tm4, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_pnf_phy_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv;
+
+	return (push16(value->number_of_phys, ppWritePackedMsg, end) &&
+			packarray(value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel10_info));
+
+}
+
+static uint8_t pack_pnf_phy_rel11_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem;
+		
+	return (push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+			push16(phy->edpcch_supported, ppWritePackedMsg, end) &&
+			push16(phy->multi_ack_csi_reporting, ppWritePackedMsg, end) &&
+			push16(phy->pucch_tx_diversity, ppWritePackedMsg, end) &&
+			push16(phy->ul_comp_supported, ppWritePackedMsg, end) &&
+			push16(phy->transmission_mode_5_supported, ppWritePackedMsg, end ));
+}
+static uint8_t pack_pnf_phy_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv;
+
+	return (push16(value->number_of_phys, ppWritePackedMsg, end) &&
+			packarray(value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel11_info));
+}
+static uint8_t pack_pnf_phy_rel12_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem;
+
+	return( push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+			push16(phy->csi_subframe_set, ppWritePackedMsg, end) &&
+			push16(phy->enhanced_4tx_codebook, ppWritePackedMsg, end) &&
+			push16(phy->drs_supported, ppWritePackedMsg, end) &&
+			push16(phy->ul_64qam_supported, ppWritePackedMsg, end) &&
+			push16(phy->transmission_mode_10_supported, ppWritePackedMsg, end) &&
+			push16(phy->alternative_bts_indices, ppWritePackedMsg, end));
+}
+static uint8_t pack_pnf_phy_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv;
+
+	return (push16(value->number_of_phys, ppWritePackedMsg, end) &&
+			packarray(value->phy, sizeof(nfapi_pnf_phy_rel12_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel12_info));
+
+}
+
+static uint8_t pack_pnf_phy_rel13_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem;
+		
+	return( push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+			push16(phy->pucch_format4_supported, ppWritePackedMsg, end) &&
+			push16(phy->pucch_format5_supported, ppWritePackedMsg, end) &&
+			push16(phy->more_than_5_ca_support, ppWritePackedMsg, end) &&
+			push16(phy->laa_supported, ppWritePackedMsg, end) &&
+			push16(phy->laa_ending_in_dwpts_supported, ppWritePackedMsg, end) &&
+			push16(phy->laa_starting_in_second_slot_supported, ppWritePackedMsg, end) &&
+			push16(phy->beamforming_supported, ppWritePackedMsg, end) &&
+			push16(phy->csi_rs_enhancement_supported, ppWritePackedMsg, end) &&
+			push16(phy->drms_enhancement_supported, ppWritePackedMsg, end) &&
+			push16(phy->srs_enhancement_supported, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_pnf_phy_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv;
+
+	return (push16(value->number_of_phys, ppWritePackedMsg, end) &&
+	        packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_info));
+}
+
+static uint8_t pack_pnf_phy_rel13_nb_iot_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem;
+		
+	return( push16(phy->phy_config_index, ppWritePackedMsg, end) &&
+			push16(phy->number_of_rfs, ppWritePackedMsg, end) &&
+			packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) &&
+			push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) &&
+			packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) &&
+			push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) &&
+			push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) &&
+			push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) &&
+			push8(phy->nmm_modes_supported, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv;
+
+	return (push16(value->number_of_phys, ppWritePackedMsg, end) &&
+	        packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info));
+}
+
+
+static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg;
+
+	return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) &&
+			pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) &&
+			pack_tlv(NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, ppWritePackedMsg, end, &pack_pnf_rf_value) &&
+			pack_tlv(NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, ppWritePackedMsg, end, &pack_pnf_phy_rel10_value) &&
+			pack_tlv(NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, ppWritePackedMsg, end, &pack_pnf_phy_rel11_value) &&
+			pack_tlv(NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, ppWritePackedMsg, end, &pack_pnf_phy_rel12_value) &&
+			pack_tlv(NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, ppWritePackedMsg, end, &pack_pnf_phy_rel13_value) &&
+			pack_tlv(NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_phy_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem;
+		
+	return (push16(rf->phy_id, ppWritePackedMsg, end) &&
+			push16(rf->phy_config_index, ppWritePackedMsg, end) &&
+			push16(rf->rf_config_index, ppWritePackedMsg, end));
+}
+		
+
+static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t*)tlv;
+
+	return(push16(value->number_phy_rf_config_info, ppWritePackedMsg, end) &&
+		   packarray(value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, ppWritePackedMsg, end, &pack_phy_rf_config_info));
+
+}
+
+static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg;
+	return ( pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && 
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config));
+}
+
+
+static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg;
+
+	return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg;
+	return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg;
+
+	return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && 
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg;
+	return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+}
+
+static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg;
+
+	return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+		 	 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg;
+	return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_uint16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv;
+	return push16(value->value, ppWritePackedMsg, end);
+}
+
+static uint8_t unpack_uint16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv;
+	return pull16(ppReadPackedMsg, &value->value, end);
+}
+static uint8_t pack_int16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv;
+	return pushs16(value->value, ppWritePackedMsg, end);
+}
+
+static uint8_t unpack_int16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv;
+	return pulls16(ppReadPackedMsg, &value->value, end);
+}
+
+static uint8_t pack_uint8_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv;
+	return push8(value->value, ppWritePackedMsg, end);
+}
+static uint8_t unpack_uint8_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv;
+	return pull8(ppReadPackedMsg, &value->value, end);
+}
+
+static uint8_t pack_ipv4_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv;
+	return pusharray8(value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, ppWritePackedMsg, end);
+}
+static uint8_t unpack_ipv4_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv;
+	return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, end);
+}
+static uint8_t pack_ipv6_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ipv6_address_t* value = (nfapi_ipv6_address_t*)tlv;
+	return pusharray8(value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, ppWritePackedMsg, end);
+}
+static uint8_t unpack_ipv6_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv;
+	return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, end);
+}
+
+static uint8_t pack_rf_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv;
+	
+	return ( push16(value->number_rf_bands, ppWritePackedMsg, end) &&
+			 pusharray16(value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, ppWritePackedMsg, end));
+}
+static uint8_t unpack_rf_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end)
+{
+	nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_rf_bands, end) &&
+			 pullarray16(ppReadPackedMsg, value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, end));
+}
+
+static uint8_t pack_nmm_frequency_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv;
+	
+	return( push16(value->number_of_rf_bands, ppWritePackedMsg, end) &&
+			pusharray16(value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, ppWritePackedMsg, end));
+}
+static uint8_t unpack_nmm_frequency_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) &&
+			 pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end));
+}
+
+static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg;
+
+	return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_L1_STATUS_PHY_STATE_TAG,  &pNfapiMsg->l1_status.phy_state, ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			// Do we check the phy state and then just fill those sepecified, however
+			// we do not know the duplex mode, so just attempt to pack all and assumme
+			// that the callee has set the right tlvs
+
+			pack_tlv(NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && 
+			pack_tlv(NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && 
+			pack_tlv(NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.phy_antenna_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.mbsfn_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			// laa capability
+
+			pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value)&&
+			pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && 
+			pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end ,&pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) &&
+			pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) &&
+
+			pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) &&
+			pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) &&
+
+			pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+
+			pack_tlv(NFAPI_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) &&
+
+			pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+
+			pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+
+			pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+
+}
+
+static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg;
+
+	return ( push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) &&
+
+			 // Do we check the phy state and then just fill those sepecified, however
+			 // we do not know the duplex mode, so just attempt to pack all and assumme
+			 // that the callee has set the right tlvs
+
+			 pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_pdsch), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &(pNfapiMsg->laa_config.pd_threshold), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &(pNfapiMsg->laa_config.multi_carrier_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &(pNfapiMsg->laa_config.multi_carrier_tx), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &(pNfapiMsg->laa_config.multi_carrier_freeze), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_antenna_ports_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_power_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &(pNfapiMsg->emtc_config.pbch_repetitions_enable_r13), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_catm_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &(pNfapiMsg->emtc_config.prach_catm_high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+			 pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+
+			 pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) &&
+			 pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) &&
+			 pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) &&
+			 pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) &&
+			 pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+
+			 pack_tlv(NFAPI_PHY_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) &&
+
+			 pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+
+			 pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			 pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+
+
+			 pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			 pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			 pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) &&
+			 pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) &&
+
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+}
+
+static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg;
+
+	return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+}
+
+static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg;
+	return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg;
+
+	return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) &&
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+}
+
+static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg;
+	return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+static uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg;
+
+	return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			 pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) );
+}
+
+static uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg;
+
+	return( pack_tlv(NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &(pNfapiMsg->dl_rs_tx_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &(pNfapiMsg->received_interference_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_tlv(NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &(pNfapiMsg->thermal_noise_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) &&
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_recevied_interference_power_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv;
+	
+	return  ( push16(value->number_of_resource_blocks, ppWritePackedMsg, end) &&
+			  pusharrays16(value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg;
+
+	return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) &&
+			pack_tlv(NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &(pNfapiMsg->dl_rs_tx_power_measurement), ppWritePackedMsg, end, &pack_int16_tlv_value) &&
+			pack_tlv(NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &(pNfapiMsg->received_interference_power_measurement), ppWritePackedMsg, end, &pack_recevied_interference_power_measurement_value) &&
+			pack_tlv(NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &(pNfapiMsg->thermal_noise_power_measurement), ppWritePackedMsg, end, &pack_uint16_tlv_value) && 
+			pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	uint8_t result = 0;
+	// look for the specific message
+	switch (header->message_id)
+	{
+		case NFAPI_PNF_PARAM_REQUEST:
+			result = pack_pnf_param_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_PARAM_RESPONSE:
+			result = pack_pnf_param_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_CONFIG_REQUEST:
+			result = pack_pnf_config_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_CONFIG_RESPONSE:
+			result = pack_pnf_config_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_START_REQUEST:
+			result = pack_pnf_start_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_START_RESPONSE:
+			result = pack_pnf_start_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_STOP_REQUEST:
+			result = pack_pnf_stop_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PNF_STOP_RESPONSE:
+			result = pack_pnf_stop_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PARAM_REQUEST:
+			result = pack_param_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_PARAM_RESPONSE:
+			result = pack_param_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_CONFIG_REQUEST:
+			result = pack_config_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_CONFIG_RESPONSE:
+			result = pack_config_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_START_REQUEST:
+			result = pack_start_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_START_RESPONSE:
+			result = pack_start_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_STOP_REQUEST:
+			result = pack_stop_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_STOP_RESPONSE:
+			result = pack_stop_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_MEASUREMENT_REQUEST:
+			result = pack_measurement_request(header, ppWritePackedMsg, end, config);
+			break;
+
+		case NFAPI_MEASUREMENT_RESPONSE:
+			result = pack_measurement_response(header, ppWritePackedMsg, end, config);
+			break;
+
+		default:
+			{
+				if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					if(config && config->pack_p4_p5_vendor_extension)
+					{
+						result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config);
+					}
+					else
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id);
+					}
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id);
+				}
+			}
+			break;
+	}
+
+	return result;
+}
+
+
+// helper function for message length calculation -
+// takes the pointers to the start of message to end of message
+
+static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd)
+{
+	if (msgEnd < msgHead)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd);
+		return 0;
+	}
+
+	return (msgEnd - msgHead);
+}
+
+// Main pack function - public
+
+int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf;
+	uint8_t *pWritePackedMessage = pPackedBuf;
+	uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen;
+	uint8_t *pPackedLengthField = &pWritePackedMessage[4];
+	uint32_t packedMsgLen;
+	uint16_t packedMsgLen16;
+
+	if (pMessageBuf == NULL || pPackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n");
+		return -1;
+	}
+
+	// pack the message
+	if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) &&
+	   push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) &&
+	   push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, pPackMessageEnd) &&
+	   push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) &&
+	   pack_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config))
+	{
+		// check for a valid message length
+		packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage);
+		if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen);
+			return -1;
+		}
+		else
+		{
+			packedMsgLen16 = (uint16_t)packedMsgLen;
+		}
+
+		// Update the message length in the header
+		if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd))
+			return -1;
+
+		// return the packed length
+		return (packedMsgLen);
+	}
+	else
+	{
+		// Failed to pack the meassage
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n");
+		return -1;
+    }
+
+}
+
+
+
+// Unpack routines
+static uint8_t  unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t*)msg;
+	
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+	
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_pnf_param_general_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv;
+	
+	return( pull8(ppReadPackedMsg, &value->nfapi_sync_mode, end) &&
+			pull8(ppReadPackedMsg, &value->location_mode, end) &&
+			pull16(ppReadPackedMsg, &value->location_coordinates_length, end) &&
+			pullarray8(ppReadPackedMsg, value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, end) &&
+			pull32(ppReadPackedMsg, &value->dl_config_timing, end) &&
+			pull32(ppReadPackedMsg, &value->tx_timing, end) &&
+			pull32(ppReadPackedMsg, &value->ul_config_timing, end) &&
+			pull32(ppReadPackedMsg, &value->hi_dci0_timing, end) &&
+			pull16(ppReadPackedMsg, &value->maximum_number_phys, end) &&
+			pull16(ppReadPackedMsg, &value->maximum_total_bandwidth, end) &&
+			pull8(ppReadPackedMsg, &value->maximum_total_number_dl_layers, end) &&
+			pull8(ppReadPackedMsg, &value->maximum_total_number_ul_layers, end) &&
+			pull8(ppReadPackedMsg, &value->shared_bands, end) &&
+			pull8(ppReadPackedMsg, &value->shared_pa, end) &&
+			pulls16(ppReadPackedMsg, &value->maximum_total_power, end) &&
+			pullarray8(ppReadPackedMsg, value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, end));
+}
+
+static uint8_t unpack_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_rf_config_info_t* info = (nfapi_rf_config_info_t*)elem;
+	return pull16(ppReadPackedMsg, &info->rf_config_index, end);
+}
+
+static uint8_t unpack_pnf_phy_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem;
+
+	return ( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && 
+			 pull16(ppReadPackedMsg, &phy->number_of_rfs, end) &&
+			 unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) &&
+			 pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) &&
+			 unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) &&
+			 pull16(ppReadPackedMsg, &phy->downlink_channel_bandwidth_supported, end) &&
+			 pull16(ppReadPackedMsg, &phy->uplink_channel_bandwidth_supported, end) &&
+			 pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) &&
+			 pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) &&
+			 pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) &&
+			 pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end));
+}
+
+
+static uint8_t unpack_pnf_phy_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv;
+	return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && 
+			 unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_info));
+}
+
+static uint8_t unpack_pnf_rf_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_rf_info_t* rf = (nfapi_pnf_rf_info_t*)elem;
+		
+	return( pull16(ppReadPackedMsg, &rf->rf_config_index, end) &&
+			pull16(ppReadPackedMsg, &rf->band, end) &&
+			pulls16(ppReadPackedMsg, &rf->maximum_transmit_power, end) &&
+			pulls16(ppReadPackedMsg, &rf->minimum_transmit_power, end) &&
+			pull8(ppReadPackedMsg, &rf->number_of_antennas_suppported, end) &&
+			pull32(ppReadPackedMsg, &rf->minimum_downlink_frequency, end) &&
+			pull32(ppReadPackedMsg, &rf->maximum_downlink_frequency, end) &&
+			pull32(ppReadPackedMsg, &rf->minimum_uplink_frequency, end) &&
+			pull32(ppReadPackedMsg, &rf->maximum_uplink_frequency, end));
+
+}
+static uint8_t unpack_pnf_rf_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_of_rfs, end) &&
+		     unpackarray(ppReadPackedMsg, value->rf, sizeof(nfapi_pnf_rf_info_t), NFAPI_MAX_PNF_RF, value->number_of_rfs, end, &unpack_pnf_rf_info));
+}
+
+static uint8_t unpack_pnf_phy_rel10_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem;
+		
+	return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &phy->transmission_mode_7_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->transmission_mode_8_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->two_antenna_ports_for_pucch, end) &&
+			pull16(ppReadPackedMsg, &phy->transmission_mode_9_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->simultaneous_pucch_pusch, end) &&
+			pull16(ppReadPackedMsg, &phy->four_layer_tx_with_tm3_and_tm4, end));
+
+
+}
+static uint8_t unpack_pnf_phy_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) &&
+			 unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel10_info));
+
+}
+
+
+static uint8_t unpack_pnf_phy_rel11_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem;
+
+	return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &phy->edpcch_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->multi_ack_csi_reporting, end ) &&
+			pull16(ppReadPackedMsg, &phy->pucch_tx_diversity, end) &&
+			pull16(ppReadPackedMsg, &phy->ul_comp_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->transmission_mode_5_supported, end));
+}
+
+static uint8_t unpack_pnf_phy_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) &&
+			 unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel11_info));
+
+}
+
+static uint8_t unpack_phy_phy_rel12_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem;
+
+	return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &phy->csi_subframe_set, end) &&
+			pull16(ppReadPackedMsg, &phy->enhanced_4tx_codebook, end) &&
+			pull16(ppReadPackedMsg, &phy->drs_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->ul_64qam_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->transmission_mode_10_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->alternative_bts_indices, end));
+}
+
+static uint8_t unpack_pnf_phy_rel12_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv;
+
+	return (pull16(ppReadPackedMsg, &value->number_of_phys, end) &&
+			unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel12_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_phy_phy_rel12_info));
+
+}
+
+static uint8_t unpack_pnf_phy_rel13_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem;
+
+	return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &phy->pucch_format4_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->pucch_format5_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->more_than_5_ca_support, end) &&
+			pull16(ppReadPackedMsg, &phy->laa_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->laa_ending_in_dwpts_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->laa_starting_in_second_slot_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->beamforming_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->csi_rs_enhancement_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->drms_enhancement_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->srs_enhancement_supported, end));
+}
+
+static uint8_t unpack_pnf_phy_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) &&
+			 unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_info));
+}
+
+static uint8_t unpack_pnf_phy_rel13_nb_info_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem;
+
+	return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &phy->number_of_rfs, end) &&
+			unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) &&
+			pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) &&
+			unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) &&
+			pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) &&
+			pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) &&
+			pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) &&
+			pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end));
+}
+
+static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) &&
+			 unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info));
+}
+
+
+
+static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg;
+	
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value},
+		{ NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value},
+		{ NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, &unpack_pnf_rf_value},
+		{ NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, &unpack_pnf_phy_rel10_value},
+		{ NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, &unpack_pnf_phy_rel11_value},
+		{ NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value},
+		{ NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value},
+		{ NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value},
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_phy_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem;
+		
+	return( pull16(ppReadPackedMsg, &rf->phy_id, end) &&
+			pull16(ppReadPackedMsg, &rf->phy_config_index, end) &&
+			pull16(ppReadPackedMsg, &rf->rf_config_index, end));
+
+}
+
+static uint8_t unpack_pnf_phy_rf_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_pnf_phy_rf_config_t* value = (nfapi_pnf_phy_rf_config_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_phy_rf_config_info, end) &&
+			 unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info));
+}
+
+static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg;
+	
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value},
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension);
+}
+
+static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg;
+	
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+
+}
+
+static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg;
+	
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+}
+
+static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_pnf_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+
+}
+
+static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_bandwidth_support, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_bandwidth_support, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_modulation_support, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_modulation_support, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.phy_antenna_capability, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.release_capability, &unpack_uint16_tlv_value},
+		{ NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.mbsfn_capability, &unpack_uint16_tlv_value},
+
+		{ NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, &pNfapiMsg->laa_capability.laa_support, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.pd_sensing_lbt_support, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.multi_carrier_lbt_support, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, &pNfapiMsg->laa_capability.partial_sf_support, &unpack_uint16_tlv_value},
+
+		{ NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value},
+
+		{ NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value},
+		{ NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value},
+		{ NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value},
+
+		{ NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value},
+		{ NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value},
+		{ NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value},
+
+		{ NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value},
+
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value},
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value},
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value},
+
+		{ NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value},
+		{ NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value},
+
+		{ NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value},
+
+		{ NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value},
+		{ NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value},
+		{ NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value},
+		{ NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value},
+		{ NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value},
+		{ NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value},
+
+	};
+
+	return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+}
+
+static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value},
+		{ NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value},
+
+		{ NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value},
+		{ NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value},
+		{ NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value},
+		{ NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value},
+
+		{ NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value},
+		{ NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value},
+		{ NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value},
+		{ NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value},
+
+		{ NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value},
+		{ NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value},
+
+		{ NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value},
+
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value},
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value},
+		{ NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value},
+
+
+		{ NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_pdsch, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_drs, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &pNfapiMsg->laa_config.pd_threshold, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &pNfapiMsg->laa_config.multi_carrier_type, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &pNfapiMsg->laa_config.multi_carrier_tx, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &pNfapiMsg->laa_config.multi_carrier_freeze, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_antenna_ports_drs, &unpack_uint16_tlv_value},
+		{ NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_power_drs, &unpack_uint16_tlv_value},
+
+		{ NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &pNfapiMsg->emtc_config.pbch_repetitions_enable_r13, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->emtc_config.prach_catm_root_sequence_index, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &pNfapiMsg->emtc_config.prach_catm_high_speed_flag, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea, &unpack_uint16_tlv_value},
+		{ NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, &unpack_uint16_tlv_value},
+
+		{ NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value},
+		{ NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value},
+
+		{ NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value},
+		{ NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value},
+
+		{ NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value},
+		{ NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value},
+		{ NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value},
+		{ NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value},
+		{ NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value},
+		{ NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value},
+		{ NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value},
+		{ NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value},
+		{ NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value},
+
+	};
+
+	return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) &&
+		     unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+}
+
+static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && 
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+}
+
+static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+
+}
+
+static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+
+}
+static uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &pNfapiMsg->dl_rs_tx_power, &unpack_uint16_tlv_value},
+		{ NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &pNfapiMsg->received_interference_power, &unpack_uint16_tlv_value},
+		{ NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &pNfapiMsg->thermal_noise_power, &unpack_uint16_tlv_value},
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+
+}
+
+static uint8_t unpack_received_interference_power_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv;
+
+	return ( pull16(ppReadPackedMsg, &value->number_of_resource_blocks, end) &&
+			 pullarrays16(ppReadPackedMsg, value->received_interference_power,  NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, end)); 
+}
+
+
+static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg;
+
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &pNfapiMsg->dl_rs_tx_power_measurement, &unpack_int16_tlv_value},
+		{ NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &pNfapiMsg->received_interference_power_measurement, &unpack_received_interference_power_measurement_value},
+		{ NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &pNfapiMsg->thermal_noise_power_measurement, &unpack_int16_tlv_value},
+	};
+
+	return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
+			 unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+}
+
+// unpack length check
+
+static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen)
+{
+	int retLen = 0;
+
+	switch (msgId)
+	{
+		case NFAPI_PNF_PARAM_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t))
+				retLen = sizeof(nfapi_pnf_param_request_t);
+			break;
+
+		case NFAPI_PNF_PARAM_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_param_response_t))
+				retLen = sizeof(nfapi_pnf_param_response_t);
+			break;
+
+		case NFAPI_PNF_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_config_request_t))
+				retLen = sizeof(nfapi_pnf_config_request_t);
+			break;
+
+		case NFAPI_PNF_CONFIG_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_config_response_t))
+				retLen = sizeof(nfapi_pnf_config_response_t);
+			break;
+
+		case NFAPI_PNF_START_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_start_request_t))
+				retLen = sizeof(nfapi_pnf_start_request_t);
+			break;
+
+		case NFAPI_PNF_START_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_start_response_t))
+				retLen = sizeof(nfapi_pnf_start_response_t);
+			break;
+
+		case NFAPI_PNF_STOP_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_stop_request_t))
+				retLen = sizeof(nfapi_pnf_stop_request_t);
+			break;
+
+		case NFAPI_PNF_STOP_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_pnf_stop_response_t))
+				retLen = sizeof(nfapi_pnf_stop_response_t);
+			break;
+
+		case NFAPI_PARAM_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_param_request_t))
+				retLen = sizeof(nfapi_param_request_t);
+			break;
+
+		case NFAPI_PARAM_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_param_response_t))
+				retLen = sizeof(nfapi_param_response_t);
+			break;
+
+		case NFAPI_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_config_request_t))
+				retLen = sizeof(nfapi_config_request_t);
+			break;
+
+		case NFAPI_CONFIG_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_config_response_t))
+				retLen = sizeof(nfapi_config_response_t);
+			break;
+
+		case NFAPI_START_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_start_request_t))
+				retLen = sizeof(nfapi_start_request_t);
+			break;
+
+		case NFAPI_START_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_start_response_t))
+				retLen = sizeof(nfapi_start_response_t);
+			break;
+
+		case NFAPI_STOP_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_stop_request_t))
+				retLen = sizeof(nfapi_stop_request_t);
+			break;
+
+		case NFAPI_STOP_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_stop_response_t))
+				retLen = sizeof(nfapi_stop_response_t);
+			break;
+
+		case NFAPI_MEASUREMENT_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_measurement_request_t))
+				retLen = sizeof(nfapi_measurement_request_t);
+			break;
+
+		case NFAPI_MEASUREMENT_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_measurement_response_t))
+				retLen = sizeof(nfapi_measurement_response_t);
+			break;
+
+		default:
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId);
+			break;
+	}
+
+	return retLen;
+}
+
+
+// Main unpack functions - public
+
+int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// process the header
+	return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) &&
+			 pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+			 pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+			 pull16(&pReadPackedMessage, &pMessageHeader->spare, end) );
+
+}
+
+int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config)
+{
+	nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// clean the supplied buffer for - tag value blanking
+	(void)memset(pUnpackedBuf, 0, unpackedBufLen);
+
+	// process the header
+	if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && 
+		  pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+		  pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+		  pull16(&pReadPackedMessage, &pMessageHeader->spare, end)))
+	{
+		// failed to read the header
+		return -1;
+	}
+
+	int result = -1;
+
+
+	if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0)
+	{
+		// the unpack buffer is not big enough for the struct 
+		return -1;
+	}
+
+	// look for the specific message
+	switch (pMessageHeader->message_id)
+	{
+		case NFAPI_PNF_PARAM_REQUEST:
+			result = unpack_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_PARAM_RESPONSE:
+			result = unpack_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_CONFIG_REQUEST:
+			result = unpack_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_CONFIG_RESPONSE:
+			result = unpack_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_START_REQUEST:
+			result = unpack_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_START_RESPONSE:
+			result = unpack_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_STOP_REQUEST:
+			result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PNF_STOP_RESPONSE:
+			result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PARAM_REQUEST:
+			result = unpack_param_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_PARAM_RESPONSE:
+			result = unpack_param_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_CONFIG_REQUEST:
+			result = unpack_config_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_CONFIG_RESPONSE:
+			result = unpack_config_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_START_REQUEST:
+			result = unpack_start_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_START_RESPONSE:
+			result = unpack_start_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_STOP_REQUEST:
+			result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_STOP_RESPONSE:
+			result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_MEASUREMENT_REQUEST:
+			result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		case NFAPI_MEASUREMENT_RESPONSE:
+			result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config);
+			break;
+
+		default:
+			if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && 
+			   pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+			{
+				if(config && config->unpack_p4_p5_vendor_extension)
+				{
+					result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id);
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
+			}
+			break;
+	}
+
+	return result;
+}
+
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
new file mode 100644
index 0000000000..69ff860774
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
@@ -0,0 +1,6184 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <assert.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <zlib.h>
+#include <sched.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <nfapi_interface.h>
+#include <nfapi.h>
+#include <debug.h>
+
+extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data);
+extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data);
+
+uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len)
+{
+	uint32_t chksum = 0;
+	// calcaulte upto the checksum
+	chksum = crc32(chksum, buffer, 8);
+	
+	// skip the checksum
+	uint8_t zeros[4] = {0, 0, 0, 0};
+	chksum = crc32(chksum, zeros, 4);
+	
+	// continu with the rest of the mesage
+	chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH);
+	
+	// return the inverse
+	return ~(chksum);
+}
+
+int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len)
+{
+	uint32_t checksum = nfapi_calculate_checksum(buffer, len);
+
+	uint8_t* p_write = &buffer[8];
+	return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1);
+}
+
+int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp)
+{
+	uint8_t* p_write = &buffer[12];
+	return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1);
+}
+
+uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len)
+{
+	return nfapi_calculate_checksum(buffer, len);
+}
+
+void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config)
+{
+	if(size == 0)
+		return 0;
+
+	if(config && config->allocate)
+	{
+		return (config->allocate)(size);
+	}
+	else
+	{
+		return calloc(1, size);
+	}
+}
+
+void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config)
+{
+	if(ptr == NULL)
+		return;
+
+	if(config && config->deallocate)
+	{
+		return (config->deallocate)(ptr);
+	}
+	else
+	{
+		return free(ptr);
+	}
+}
+// Pack routines
+
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv;
+	
+        //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format);
+
+	return ( push8(value->dci_format, ppWritePackedMsg, end) &&
+			 push8(value->cce_idx, ppWritePackedMsg, end) &&
+			 push8(value->aggregation_level, ppWritePackedMsg, end) &&
+			 push16(value->rnti, ppWritePackedMsg, end) &&
+			 push8(value->resource_allocation_type, ppWritePackedMsg, end) &&
+			 push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) &&
+			 push32(value->resource_block_coding, ppWritePackedMsg, end) &&
+			 push8(value->mcs_1, ppWritePackedMsg, end) &&
+			 push8(value->redundancy_version_1, ppWritePackedMsg, end) &&
+			 push8(value->new_data_indicator_1, ppWritePackedMsg, end) &&
+			 push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) &&
+			 push8(value->mcs_2, ppWritePackedMsg, end) &&
+			 push8(value->redundancy_version_2, ppWritePackedMsg, end) &&
+			 push8(value->new_data_indicator_2, ppWritePackedMsg, end) &&
+			 push8(value->harq_process, ppWritePackedMsg, end) &&
+			 push8(value->tpmi, ppWritePackedMsg, end) &&
+			 push8(value->pmi, ppWritePackedMsg, end) &&
+			 push8(value->precoding_information, ppWritePackedMsg, end) &&
+			 push8(value->tpc, ppWritePackedMsg, end) &&
+			 push8(value->downlink_assignment_index, ppWritePackedMsg, end) &&
+			 push8(value->ngap, ppWritePackedMsg, end) &&
+			 push8(value->transport_block_size_index, ppWritePackedMsg, end) &&
+			 push8(value->downlink_power_offset, ppWritePackedMsg, end) &&
+			 push8(value->allocate_prach_flag, ppWritePackedMsg, end) &&
+			 push8(value->preamble_index, ppWritePackedMsg, end) &&
+			 push8(value->prach_mask_index, ppWritePackedMsg, end) &&
+			 push8(value->rnti_type, ppWritePackedMsg, end) &&
+			 push16(value->transmission_power, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv;
+
+	return( push8(value->mcch_flag, ppWritePackedMsg, end) &&
+			push8(value->mcch_change_notification, ppWritePackedMsg, end) &&
+			push8(value->scrambling_identity, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv;
+	
+	return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) &&
+			 push8(value->carrier_indicator, ppWritePackedMsg, end) &&
+			 push8(value->srs_flag, ppWritePackedMsg, end) &&
+			 push8(value->srs_request, ppWritePackedMsg, end) &&
+			 push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) &&
+			 push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && 
+			 push8(value->n_dl_rb, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv;
+	
+	return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) &&
+		 	 push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv;
+	
+	return ( push8(value->primary_cell_type, ppWritePackedMsg, end) &&
+			 push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) &&
+			 push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) &&
+			 pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) &&
+	       push8(value->number_of_subbands, ppWritePackedMsg, end) &&
+	       push8(value->num_antennas, ppWritePackedMsg, end)))
+		return 0;
+	
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_subbands; ++idx)
+	{
+		nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]);
+		
+		if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) &&
+			 push8(subband_info->scheduled_ues, ppWritePackedMsg, end)))
+			return 0;	
+		
+
+		uint8_t antenna_idx = 0;
+		uint8_t scheduled_ue_idx = 0;
+		
+		for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx)
+		{
+			for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx)
+			{
+				if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end))
+					return 0;
+			}
+		}
+
+	}
+	
+	
+	return 1;			
+	
+}
+
+static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv;
+
+	return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) &&
+			push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) &&
+			push8(value->initial_lbt_sf, ppWritePackedMsg, end) &&
+			push8(value->codebook_size_determination, ppWritePackedMsg, end) &&
+			push8(value->drms_table_flag, ppWritePackedMsg, end) &&
+			push8(value->tpm_struct_flag, ppWritePackedMsg, end) &&
+			(value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1));
+}
+
+static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv;
+	
+        //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__);
+
+	return( push16(value->length, ppWritePackedMsg, end) &&
+			push16(value->pdu_index, ppWritePackedMsg, end) &&
+			push16(value->transmission_power, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv;
+
+	return ( push16(value->length, ppWritePackedMsg, end) &&
+			 push16(value->pdu_index, ppWritePackedMsg, end) &&
+			 push16(value->rnti, ppWritePackedMsg, end) &&
+			 push8(value->resource_allocation_type, ppWritePackedMsg, end) &&
+			 push32(value->resource_block_coding, ppWritePackedMsg, end) &&
+			 push8(value->modulation, ppWritePackedMsg, end) &&
+			 push16(value->transmission_power, ppWritePackedMsg, end) &&
+			 push16(value->mbsfn_area_id, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem;
+
+	return ( push8(bf->subband_index, ppWritePackedMsg, end) &&
+			 push8(bf->num_antennas, ppWritePackedMsg, end) &&
+			 pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end));
+
+	
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv;
+
+	return ( push16(value->length, ppWritePackedMsg, end) && 
+			 push16(value->pdu_index, ppWritePackedMsg, end) &&
+			 push16(value->rnti, ppWritePackedMsg, end) &&
+			 push8(value->resource_allocation_type, ppWritePackedMsg, end) &&
+			 push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) &&
+			 push32(value->resource_block_coding, ppWritePackedMsg, end) &&
+			 push8(value->modulation, ppWritePackedMsg, end) &&
+			 push8(value->redundancy_version, ppWritePackedMsg, end) &&
+			 push8(value->transport_blocks, ppWritePackedMsg, end) &&
+			 push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) &&
+			 push8(value->transmission_scheme, ppWritePackedMsg, end) &&
+			 push8(value->number_of_layers, ppWritePackedMsg, end) &&
+			 push8(value->number_of_subbands, ppWritePackedMsg, end) &&
+			 pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) &&
+			 push8(value->ue_category_capacity, ppWritePackedMsg, end) &&
+			 push8(value->pa, ppWritePackedMsg, end) &&
+			 push8(value->delta_power_offset_index, ppWritePackedMsg, end) &&
+			 push8(value->ngap, ppWritePackedMsg, end) &&
+			 push8(value->nprb, ppWritePackedMsg, end) &&
+			 push8(value->transmission_mode, ppWritePackedMsg, end) &&
+			 push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) &&
+			 push8(value->num_bf_vector, ppWritePackedMsg, end) &&
+			 packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info));
+
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv;
+	return ( push8(value->nscid, ppWritePackedMsg, end) );
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv;
+	
+	return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) &&
+			 push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) &&
+			 push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) &&
+			 push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) &&
+			 pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) &&
+			 push8(value->pdsch_start, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv;
+	
+	return( push8(value->drms_config_flag, ppWritePackedMsg, end) &&
+			push16(value->drms_scrambling, ppWritePackedMsg, end) &&
+			push8(value->csi_config_flag, ppWritePackedMsg, end) &&
+			push16(value->csi_scrambling, ppWritePackedMsg, end) &&
+			push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) &&
+			push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) &&
+			push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv;
+
+	return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) &&
+			push8(value->maxlayers, ppWritePackedMsg, end) &&
+			push8(value->n_dl_harq, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv;
+	
+	return( push8(value->dwpts_symbols, ppWritePackedMsg, end) &&
+			push8(value->initial_lbt_sf, ppWritePackedMsg, end) &&
+			push8(value->ue_type, ppWritePackedMsg, end) &&
+			push8(value->pdsch_payload_type, ppWritePackedMsg, end) &&
+			push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) &&
+			push8(value->drms_table_flag, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv;
+	
+	return( push16(value->length, ppWritePackedMsg, end) &&
+			push16(value->pdu_index, ppWritePackedMsg, end) &&
+			push16(value->p_rnti, ppWritePackedMsg, end) &&
+			push8(value->resource_allocation_type, ppWritePackedMsg, end) &&
+			push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) &&
+			push32(value->resource_block_coding, ppWritePackedMsg, end) &&
+			push8(value->mcs, ppWritePackedMsg, end) &&
+			push8(value->redundancy_version, ppWritePackedMsg, end) &&
+			push8(value->number_of_transport_blocks, ppWritePackedMsg, end) &&
+			push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) &&
+			push8(value->transmission_scheme, ppWritePackedMsg, end) &&
+			push8(value->number_of_layers, ppWritePackedMsg, end) &&
+			push8(value->codebook_index, ppWritePackedMsg, end) &&
+			push8(value->ue_category_capacity, ppWritePackedMsg, end) &&
+			push8(value->pa, ppWritePackedMsg, end) &&
+			push16(value->transmission_power, ppWritePackedMsg, end) &&
+			push8(value->nprb, ppWritePackedMsg, end) &&
+			push8(value->ngap, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv;
+
+	return ( push8(value->ue_mode, ppWritePackedMsg, end) &&
+		 	 push16(value->initial_transmission_sf_io, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv;
+
+	return( push16(value->transmission_power, ppWritePackedMsg, end) &&
+			push8(value->prs_bandwidth, ppWritePackedMsg, end) &&
+			push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) &&
+			push8(value->prs_muting, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv;
+
+	return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) &&
+			push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) &&
+			push16(value->transmission_power, ppWritePackedMsg, end) &&
+			push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) &&
+			push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) &&
+			pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv;
+
+	if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) &&
+		 	 push8(value->cdm_type, ppWritePackedMsg, end) &&
+		 	 push8(value->num_bf_vector, ppWritePackedMsg, end)))
+	{
+		return 0;
+	}
+
+	uint16_t i; 
+	for(i = 0; i < value->num_bf_vector; ++i)
+	{
+		if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) &&
+		     pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( push8(vector->subband_index, ppWritePackedMsg, end) &&
+			 push8(vector->num_antennas, ppWritePackedMsg, end) &&
+		 	 pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv;
+
+	return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) &&
+			push16(value->epdcch_id, ppWritePackedMsg, end) &&
+			push8(value->epdcch_start_symbol, ppWritePackedMsg, end) &&
+			push8(value->epdcch_num_prb, ppWritePackedMsg, end) &&
+			pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) &&
+			pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv;
+	
+	return (push8(value->dwpts_symbols, ppWritePackedMsg, end) &&
+		 	push8(value->initial_lbt_sf, ppWritePackedMsg, end));
+}
+static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv;
+	
+	return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) &&
+			 push8(value->number_of_prb_pairs, ppWritePackedMsg, end) &&
+			 push8(value->resource_block_assignment, ppWritePackedMsg, end) &&
+			 push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) &&
+			 push8(value->start_symbol, ppWritePackedMsg, end) &&
+			 push8(value->ecce_index, ppWritePackedMsg, end) &&
+			 push8(value->aggregation_level, ppWritePackedMsg, end) &&
+			 push8(value->rnti_type, ppWritePackedMsg, end) &&
+			 push16(value->rnti, ppWritePackedMsg, end) &&
+			 push8(value->ce_mode, ppWritePackedMsg, end) &&
+			 push16(value->drms_scrambling_init, ppWritePackedMsg, end) &&
+			 push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) &&
+			 push16(value->transmission_power, ppWritePackedMsg, end) &&
+			 push8(value->dci_format, ppWritePackedMsg, end) &&
+			 push16(value->resource_block_coding, ppWritePackedMsg, end) &&
+			 push8(value->mcs, ppWritePackedMsg, end) &&
+			 push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) &&
+			 push8(value->redundancy_version, ppWritePackedMsg, end) &&
+			 push8(value->new_data_indicator, ppWritePackedMsg, end) &&
+			 push8(value->harq_process, ppWritePackedMsg, end) &&
+			 push8(value->tpmi_length, ppWritePackedMsg, end) &&
+			 push8(value->tpmi, ppWritePackedMsg, end) &&
+			 push8(value->pmi_flag, ppWritePackedMsg, end) &&
+			 push8(value->pmi, ppWritePackedMsg, end) &&
+			 push8(value->harq_resource_offset, ppWritePackedMsg, end) &&
+			 push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) &&
+			 push8(value->tpc, ppWritePackedMsg, end) &&
+			 push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) &&
+			 push8(value->downlink_assignment_index, ppWritePackedMsg, end) &&
+			 push8(value->allocate_prach_flag, ppWritePackedMsg, end) &&
+			 push8(value->preamble_index, ppWritePackedMsg, end) &&
+			 push8(value->prach_mask_index, ppWritePackedMsg, end) &&
+			 push8(value->starting_ce_level, ppWritePackedMsg, end) &&
+			 push8(value->srs_request, ppWritePackedMsg, end) &&
+			 push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) &&
+			 push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) &&
+			 push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) &&
+			 push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) &&
+			 push8(value->direct_indication, ppWritePackedMsg, end) &&
+			 push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) &&
+			 push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) &&
+			 pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv;
+	
+	return (push16(value->length, ppWritePackedMsg, end) &&
+		 	push16(value->pdu_index, ppWritePackedMsg, end) &&
+		 	push16(value->transmission_power, ppWritePackedMsg, end) &&
+		 	push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv;
+	
+	return (push16(value->length, ppWritePackedMsg, end) &&
+			push16(value->pdu_index, ppWritePackedMsg, end) &&
+			push8(value->ncce_index, ppWritePackedMsg, end) &&
+			push8(value->aggregation_level, ppWritePackedMsg, end) &&
+			push8(value->start_symbol, ppWritePackedMsg, end) &&
+			push8(value->rnti_type, ppWritePackedMsg, end) &&
+			push16(value->rnti, ppWritePackedMsg, end) &&
+			push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) &&
+			push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) &&
+			push8(value->dci_format, ppWritePackedMsg, end) &&
+			push8(value->scheduling_delay, ppWritePackedMsg, end) &&
+			push8(value->resource_assignment, ppWritePackedMsg, end) &&
+			push8(value->repetition_number, ppWritePackedMsg, end) &&
+			push8(value->mcs, ppWritePackedMsg, end) &&
+			push8(value->new_data_indicator, ppWritePackedMsg, end) &&
+			push8(value->harq_ack_resource, ppWritePackedMsg, end) &&
+			push8(value->npdcch_order_indication, ppWritePackedMsg, end) &&
+			push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) &&
+			push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) &&
+			push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) &&
+			push8(value->direct_indication, ppWritePackedMsg, end) &&
+			push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) &&
+			push8(value->total_dci_length_including_padding, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv;
+	
+	return (push16(value->length, ppWritePackedMsg, end) &&
+			push16(value->pdu_index, ppWritePackedMsg, end) &&
+			push8(value->start_symbol, ppWritePackedMsg, end) &&
+			push8(value->rnti_type, ppWritePackedMsg, end) &&
+			push16(value->rnti, ppWritePackedMsg, end) &&
+			push16(value->resource_assignment, ppWritePackedMsg, end) &&
+			push16(value->repetition_number, ppWritePackedMsg, end) &&
+			push8(value->modulation, ppWritePackedMsg, end) &&
+			push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) &&
+			push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) &&
+			push16(value->sf_idx, ppWritePackedMsg, end) &&
+			push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv;
+
+        //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich);
+
+	if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) &&
+		 push8(value->number_dci, ppWritePackedMsg, end) &&
+		 push16(value->number_pdu, ppWritePackedMsg, end) &&
+		 push8(value->number_pdsch_rnti, ppWritePackedMsg, end) &&
+		 push16(value->transmission_power_pcfich, ppWritePackedMsg, end)))
+	{
+		return 0;
+	}
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_pdu;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]);
+
+		if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Put a 0 size in and then determine the size after the pdu 
+		// has been writen and write the calculated size
+		uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg;
+		pdu->pdu_size = 0;
+		if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
+				{
+                                  //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__);
+
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value)))
+					{
+						return 0;
+					}
+				}
+				break;
+			case NFAPI_DL_CONFIG_BCH_PDU_TYPE:
+				{
+                                  //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__);
+
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_PCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) &&
+					pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_PRS_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end,  &pack_dl_config_csi_rs_pdu_rel10_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end,  &pack_dl_config_csi_rs_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) &&
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) &
+						 pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_NBCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+
+		// add 1 for the pdu_type. The delta will include the pdu_size
+		pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize);
+		push8(pdu->pdu_size, &pWritePackedMsgPduSize, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg;
+	
+	//return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) &&
+			 //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+        { 
+          uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end);
+          uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value);
+          uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+
+          if (!x || !y || !z)
+          {
+            NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z);
+          }
+
+          return x && y && z;
+        }
+}
+
+static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end)
+{
+	nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv;
+	
+	return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv;
+	
+	return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) &&
+			push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv;
+	
+	return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv;
+
+	return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) &&
+			push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) &&
+			push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) &&
+			pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) &&
+			pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) &&
+			pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value));
+}
+
+static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv;
+
+	return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) &&
+			 push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) &&
+			 push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) &&
+			 push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) &&
+			 push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv;
+
+	if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) &&
+		 push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) &&
+		 push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end)))
+	{
+		return 0;
+	}
+
+	switch(cqi_ri_info_rel9->report_type)
+	{
+		case NFAPI_CSI_REPORT_TYPE_PERIODIC:
+			{
+				if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) &&
+					 push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end)))
+				{
+					return 0;
+				}
+			}
+			break;
+		case NFAPI_CSI_REPORT_TYPE_APERIODIC:
+			{
+				if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0)
+					return 0;
+
+				uint8_t i;
+				for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i)
+				{
+					if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0)
+						return 0;
+
+                                        uint8_t j;
+                                        for(j = 0; j < 8; ++j)
+					{
+                                              if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0)
+							return 0;
+					}
+				}
+			}
+			break;
+		default:
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type );
+			}
+			break;
+	};
+
+	return 1;
+}
+
+static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv;
+
+	switch(cqi_ri_info_rel13->report_type)
+	{
+		case NFAPI_CSI_REPORT_TYPE_PERIODIC:
+			{
+				if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0)
+					return 0;
+			}
+			break;
+		case NFAPI_CSI_REPORT_TYPE_APERIODIC:
+			{
+				// No parameters
+			}
+			break;
+		default:
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type );
+			}
+			break;
+	};
+
+	return 1;
+}
+
+static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) &&
+			pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) &&
+			pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value));
+
+}
+
+static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv;
+	
+	return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) &&
+		 	push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value);
+}
+
+static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv;
+	
+	return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) &&
+			push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) &&
+			push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv;
+	
+	return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) &&
+		 	push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) &&
+			 pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value));
+}
+
+static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv;
+	
+	return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) &&
+		 	 push16(ue_info_rel8->rnti, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv;
+
+	return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) &&
+		 	 push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv;
+
+	return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) &&
+			 push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) &&
+			 push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) &&
+			 push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value));
+}
+
+static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv;
+
+	return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) &&
+			push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) &&
+			push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) &&
+			push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) &&
+			push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) &&
+			push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) &&
+			push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv;
+
+	return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) &&
+			push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv;
+	
+	return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) &&
+			push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) &&
+			push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) &&
+			push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) &&
+			push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) &&
+			push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) &&
+			push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv;
+	
+	return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) &&
+			push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) &&
+			push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) &&
+			push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) &&
+			push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv;
+	
+	return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) &&
+			push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) &&
+			push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) &&
+			push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) &&
+			push8(harq_info_rel13->n_srs, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value));
+
+}
+
+static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv;
+
+	return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) &&
+			 push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv;
+	
+	return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) &&
+			 push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end));
+}
+static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv;
+	
+	return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) &&
+			push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) &&
+			push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) &&
+			push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) &&
+			push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) &&
+			push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && 
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value));
+
+}
+
+static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv;
+	return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end);
+}
+static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv;
+
+	return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) &&
+		 	 push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) &&
+	pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value));
+}
+
+static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv;
+	
+	return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) &&
+			push16(srs_pdu_rel8->size, ppWritePackedMsg, end) &&
+			push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) &&
+			push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) &&
+			push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) &&
+			push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) &&
+			push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) &&
+			push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) &&
+			push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv;
+	return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end);
+}
+
+static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv;
+	
+	return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv;
+	
+	return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv;
+	
+	return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) &&
+		    push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) &&
+		    push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) &&
+		    push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) &&
+		    push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) &&
+		    push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) &&
+		    push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && 
+		    pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) &&
+		    pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value));
+}
+static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv;
+	
+	return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) &&
+			 push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) &&
+			 push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end));
+	
+}
+
+static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv;
+
+	if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) &&
+	 	 push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) &&
+		 push8(value->srs_present, ppWritePackedMsg, end)))
+		return 0;
+
+	uint16_t i = 0;
+	for(i = 0; i < value->number_of_pdus; ++i)
+	{
+		nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]);
+
+		if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Put a 0 size in and then determine the size after the pdu 
+		// has been writen and write the calculated size
+		uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg;
+		pdu->pdu_size = 0;
+		if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE:
+				{
+					if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) &&
+	 					 pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_SRS_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) &&
+						 pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) &&
+						 pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE:
+				{
+					if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) &&
+						 pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end)))
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value)))	
+						return 0;
+				}
+				break;
+			case NFAPI_UL_CONFIG_NRACH_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value)))
+						return 0;
+				}
+				break;				
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+
+		// add 1 for the pdu_type. The delta will include the pdu_size
+		pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize);
+		push8(pdu->pdu_size, &pWritePackedMsgPduSize, end);
+		
+	}
+	return 1;
+}
+
+static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ;
+}
+
+static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv;
+	
+	return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) &&
+			 push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) &&
+			 push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) &&
+			 push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) &&
+			 push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv;
+	
+	return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) &&
+			 push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv;
+	
+	return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) &&
+			 push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) &&
+			 push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) &&
+			 push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv;
+	
+	return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) &&
+			 push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv;
+	
+	return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) &&
+			 push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv;
+	
+	return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) &&
+			 push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) &&
+			 push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) &&
+			 push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) &&
+			 push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) &&
+			 push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) &&
+			 push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) &&
+			 pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end));
+	
+}
+
+static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv;
+	
+	return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) &&
+			 push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) &&
+			 push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv;
+
+	if(!(push16(value->sfnsf, ppWritePackedMsg, end) &&
+		 push8(value->number_of_dci, ppWritePackedMsg, end) &&
+		 push8(value->number_of_hi, ppWritePackedMsg, end)))
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]);
+
+		if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Put a 0 size in and then determine the size after the pdu 
+		// has been writen and write the calculated size
+		uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg;
+		pdu->pdu_size = 0;
+		if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_HI_DCI0_HI_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) &&
+						 pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_HI_DCI0_DCI_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) &&
+						 pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) &&
+						 pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) &&
+						 pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) &&
+						 pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value)))
+						return 0;
+				}
+				break;
+			case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE:
+				{
+					if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value)))
+						return 0;
+				}
+				break;				
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+
+		// add 1 for the pdu_type. The delta will include the pdu_size
+		pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize);
+		push8(pdu->pdu_size, &pWritePackedMsgPduSize, end);
+		
+	}
+
+	return 1;
+}
+
+static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv;
+	
+	if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]);
+				
+		if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) &&
+			 push16(pdu->pdu_index, ppWritePackedMsg, end)))
+			return 0;
+
+		uint8_t j;
+		for(j = 0; j < pdu->num_segments; ++j)
+		{
+			// Use -1 as it is unbounded 
+			// DJP - does not handle -1
+                        // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0)
+			int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end);
+                        
+                        if (0 && pdu->segments[j].segment_length == 3)
+                        {
+                          NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, 
+                          pdu->segments[j].segment_data[0], 
+                          pdu->segments[j].segment_data[1], 
+                          pdu->segments[j].segment_data[2]
+                          );
+                        }
+                        //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret);
+
+                        if (push_ret == 0)
+			{
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg;
+	
+	int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end);
+        int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value);
+        int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+
+        //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z);
+
+        return x && y && z;
+}
+
+static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv;
+	
+	return ( push32(value->handle, ppWritePackedMsg, end) &&
+			 push16(value->rnti, ppWritePackedMsg, end) );
+}
+
+static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv;
+	
+	return ( pull32(ppReadPackedMsg, &value->handle, end) &&
+			 pull16(ppReadPackedMsg, &value->rnti, end));
+}
+
+static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( push8(data->value_0, ppWritePackedMsg, end) &&
+			 push8(data->value_1, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( push8(data->value_0, ppWritePackedMsg, end) &&
+			 push8(data->value_1, ppWritePackedMsg, end) &&
+			 push8(data->value_2, ppWritePackedMsg, end) &&
+			 push8(data->value_3, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( push8(data->value_0, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	return ( push8(data->value_0, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv;
+	
+	if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) &&
+		 push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end)))
+			return 0;
+
+	uint8_t result = 0;
+	switch(harq_indication_tdd_rel8->mode)
+	{
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+			result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+			result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+			result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+			result = 1;
+			break;			
+		default:
+			// err....
+			break;
+	}
+
+	return result;
+	
+}
+
+static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv;
+	
+	if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) &&
+		 push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)))
+		return 0;
+
+	uint8_t idx; 
+	for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx)
+	{
+		uint8_t result = 0;
+
+		switch(harq_indication_tdd_rel9->mode)
+		{
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+				result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+				result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end);
+				break;
+			default:
+				// err....
+				break;
+		}
+
+		if(result == 0)
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv;
+	
+	if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) &&
+		 push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)))
+		return 0;
+
+	uint8_t idx; 
+	for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx)
+	{
+		uint8_t result = 0;
+		switch(harq_indication_tdd_rel13->mode)
+		{
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+				result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5:
+				result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end);
+				break;
+			default:
+				// err....
+				break;
+		}
+
+		if(result == 0)
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv;
+	
+	return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) &&
+			 push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv;
+	
+	return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) &&
+			 push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) &&
+			 pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv;
+	
+	return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) &&
+			 push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) &&
+			 pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv;
+	
+	return ( push8(value->ul_cqi, ppWritePackedMsg, end) &&
+			 push8(value->channel, ppWritePackedMsg, end));
+
+}
+
+static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv;
+	
+	if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_harqs;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]);
+
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) &&
+			 pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv;
+	
+	return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv;
+	
+	if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_crcs;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]);
+		
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+		
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+	return 1;
+}
+
+static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv;
+	
+	return ( push16(value->length, ppWritePackedMsg, end) &&
+			 push16(value->offset, ppWritePackedMsg, end) &&
+			 push8(value->ul_cqi, ppWritePackedMsg, end) &&
+			 push16(value->timing_advance, ppWritePackedMsg, end));
+}
+static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv;
+	
+	return ( push16(value->timing_advance_r9, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv;
+
+        //printf("RX ULSCH BODY\n");
+
+	if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	// need to calculate the data offset's. 
+	uint16_t i = 0;
+	uint16_t offset = 2; // taking into account the number_of_pdus
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+        //printf("ULSCH:pdus:%d\n", total_number_of_pdus);
+
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]);
+		if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG)
+		{
+                  //printf("NFAPI_RX_UE_INFORMATION_TAG\n");
+			offset += 4 + 6; 
+		}
+				
+		if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG)
+		{
+                  //printf("NFAPI_RX_INDICATION_REL8_TAG\n");
+			offset += 4 + 7;
+		}
+
+		if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG)
+		{
+                  //printf("NFAPI_RX_INDICATION_REL9_TAG\n");
+			offset += 4 + 2;
+		}
+	}
+
+	// Now update the structure to include the offset
+	for(i =0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]);
+				
+		if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG)
+		{
+			if(pdu->rx_indication_rel8.offset == 1)
+			{
+				pdu->rx_indication_rel8.offset = offset;
+				offset += pdu->rx_indication_rel8.length;
+			}
+		}
+	}
+	
+	// Write out the pdu
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]);
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) &&
+			 pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value)))
+			return 0;
+	}
+
+	// Write out the pdu data
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		uint16_t length = 0;
+		nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]);
+
+		if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG)
+		{
+			length = pdu->rx_indication_rel8.length;
+		}
+
+		if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+
+static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv;
+	
+	return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) &&
+			 push8(preamble_rel8->preamble, ppWritePackedMsg, end) &&
+			 push16(preamble_rel8->timing_advance, ppWritePackedMsg, end));
+}
+static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv;
+	
+	return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) );
+}
+static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv;
+	
+	return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv;
+	
+	if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_preambles;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]);
+		
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+		
+		if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) &&
+			 pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) &&
+			 pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv;
+	
+	return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) &&
+			 push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) &&
+			 push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) &&
+			 push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) &&
+			 pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv;
+	
+	return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv;
+	
+	return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) );
+	
+}
+
+static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv;
+	
+	return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ;
+}
+
+static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv;
+
+	if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) &&
+		 push8(value->number_of_subbands, ppWritePackedMsg, end) &&
+		 push8(value->num_atennas, ppWritePackedMsg, end)))
+		return 0;
+
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_subbands; ++idx)
+	{
+		if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) &&
+			 pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end)))
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg,  uint8_t *end)
+{
+	nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv;
+
+	if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_ues;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]);
+		
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+		
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) &&
+			 pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) &&
+			 pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) &&
+			 pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) &&
+			 pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+
+static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv;
+
+	if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_srs;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]);
+
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+	return 1;
+}
+
+static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+
+static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv;
+	
+	return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) &&
+			 push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) &&
+			 push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) &&
+			 push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) &&
+			 push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv;
+	
+	return  ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) &&
+			  push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) &&
+			  push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) &&
+			  push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) &&
+			  pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) &&
+			  push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) &&
+			  push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv;
+
+	if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	// need to calculate the data offset's. This very bittle due the hardcoding
+	// of the sizes. can not use the sizeof as we have an array for the Rel9
+	// info
+	uint16_t i = 0;
+	uint16_t offset = 2; // taking into account the number_of_cqis
+	uint16_t total_number_of_pdus = value->number_of_cqis;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]);
+		
+		offset += 2; // for the instance length
+		
+		if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG)
+		{
+			offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t)
+		}
+				
+		if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG)
+		{
+			offset += 4 + 8;
+		}
+
+		if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG)
+		{
+			offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported;
+		}
+
+		if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG)
+		{
+			offset += 4 + 2;
+		}
+	}
+
+	// Now update the structure to include the offset
+	for(i =0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]);
+				
+		if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG)
+		{
+			if(pdu->cqi_indication_rel8.data_offset == 1)
+			{
+				pdu->cqi_indication_rel8.data_offset = offset;
+				offset += pdu->cqi_indication_rel8.length;
+			}
+		}
+
+		if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG)
+		{
+			if(pdu->cqi_indication_rel9.data_offset == 1)
+			{
+				pdu->cqi_indication_rel9.data_offset = offset;
+				offset += pdu->cqi_indication_rel9.length;
+			}
+		}
+
+	}
+	
+	// Write out the cqi information
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]);
+
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+		
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) &&
+			 pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) &&
+			 pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value)))
+			return 0;
+
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+		
+	}
+
+	// Write out the cqi raw data
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		uint16_t length = 0;
+		nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]);
+
+		if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG)
+		{
+			length = pdu->cqi_indication_rel8.length;
+		}
+
+		if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG)
+		{
+			length = pdu->cqi_indication_rel9.length;
+		}
+
+		if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0)
+			return 0;
+	}
+
+	return 1; 
+}
+
+static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+
+}
+
+static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv;
+	
+	return ( push32(value->handle, ppWritePackedMsg, end) &&
+			 push32(value->mp_cca, ppWritePackedMsg, end) &&
+			 push32(value->n_cca, ppWritePackedMsg, end) &&
+			 push32(value->offset, ppWritePackedMsg, end) &&
+			 push32(value->lte_txop_sf, ppWritePackedMsg, end) &&
+			 push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) &&
+			 push32(value->lbt_mode, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv;
+	
+	return ( push32(value->handle, ppWritePackedMsg, end) &&
+			 push32(value->offset, ppWritePackedMsg, end) &&
+			 push16(value->sfn_sf_end, ppWritePackedMsg, end) &&
+			 push32(value->lbt_mode, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv;
+	
+	if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]);
+		
+		if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Put a 0 size in and then determine the size after the pdu 
+		// has been writen and write the calculated size
+		uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg;
+		pdu->pdu_size = 0;
+		if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE:
+				{
+					if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0)
+						return 0;
+				}
+				break;
+			case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE:
+				{
+					if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0)
+						return 0;
+				}
+				break;
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+
+		// add 1 for the pdu_type. The delta will include the pdu_size
+		pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize);
+		push8(pdu->pdu_size, &pWritePackedMsgPduSize, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv;
+	
+	return ( push32(value->handle, ppWritePackedMsg, end) &&
+			 push32(value->result, ppWritePackedMsg, end) &&
+			 push32(value->lte_txop_symbols, ppWritePackedMsg, end) &&
+			 push32(value->initial_partial_sf, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv;
+	
+	return ( push32(value->handle, ppWritePackedMsg, end) &&
+			 push32(value->result, ppWritePackedMsg, end));
+}
+
+static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv;
+	
+	if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(; i < total_number_of_pdus; ++i)
+	{
+		nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]);
+		
+		if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		// Put a 0 size in and then determine the size after the pdu 
+		// has been writen and write the calculated size
+		uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg;
+		pdu->pdu_size = 0;
+		
+		if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE:
+				{
+					if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0)
+						return 0;
+				}
+				break;
+			case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE:
+				{
+					if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0)
+						return 0;
+				}
+				break;
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+
+		// add 1 for the pdu_type. The delta will include the pdu_size
+		pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize);
+		push8(pdu->pdu_size, &pWritePackedMsgPduSize, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv;
+	
+	return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) );
+}
+
+static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv;
+	
+	if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_harqs = value->number_of_harqs;
+	for(; i < total_number_of_harqs; ++i)
+	{
+		nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]);
+		
+		uint8_t* instance_length_p = *ppWritePackedMsg;
+		if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+			return 0;
+
+		if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) &&
+			 pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) &&
+			 pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value)))
+			return 0;
+			
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		push16(instance_length, &instance_length_p, end);
+	}
+
+	return 1;
+}
+
+
+static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv;
+	
+	return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) &&
+			 push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) &&
+			 push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) &&
+			 push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end));
+}
+
+
+static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+	nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv;
+	
+	if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0)
+		return 0;
+
+	uint16_t i = 0;
+	uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected;
+	for(; i < total_number_of_initial_scs_detected; ++i)
+	{
+		nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]);
+		
+		//uint8_t* instance_length_p = *ppWritePackedMsg;
+		//if(!push16(pdu->instance_length, ppWritePackedMsg, end))
+		//	return 0;
+
+		if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value)))
+			return 0;
+			
+		// calculate the instance length subtracting the size of the instance
+		// length feild
+		//uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2;
+		//push16(instance_length, &instance_length_p, end);
+	}
+
+	return 1;
+}
+
+static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg;
+	
+	return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) &&
+			 pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg;
+
+	return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) &&
+			 pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) &&
+			 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg;
+
+	return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->t2, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->t3, ppWritePackedMsg, end) &&
+			pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg;
+
+	return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) &&
+			push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) &&
+			pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) &&
+			pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+
+// Main pack function - public
+
+int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config)
+{
+	nfapi_p7_message_header_t *pMessageHeader = pMessageBuf;
+	uint8_t *pWritePackedMessage = pPackedBuf;
+	uint8_t *pPackedLengthField = &pWritePackedMessage[4];
+	uint8_t *end = pPackedBuf + packedBufLen;
+
+	if (pMessageBuf == NULL || pPackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n");
+		return -1;
+	}
+
+	// process the header
+	if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) &&
+		 push16(pMessageHeader->message_id, &pWritePackedMessage, end) &&
+		 push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) &&
+		 push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) &&
+		 push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) &&
+		 push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n");
+		return -1;
+	}
+
+        if (pMessageHeader->message_id != NFAPI_TIMING_INFO)
+        {
+          //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp);
+        }
+	// look for the specific message
+	uint8_t result = 0;
+	switch (pMessageHeader->message_id)
+	{
+		case NFAPI_DL_CONFIG_REQUEST:
+                  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__);
+			result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_UL_CONFIG_REQUEST:
+			result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_HI_DCI0_REQUEST:
+			result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_TX_REQUEST:
+                        //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__);
+			result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_HARQ_INDICATION:
+			result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_CRC_INDICATION:
+			result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RX_ULSCH_INDICATION:
+                        //printf("RX ULSCH\n");
+			result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RACH_INDICATION:
+			result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SRS_INDICATION:
+			result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RX_SR_INDICATION:
+			result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_LBT_DL_INDICATION:
+			result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_NB_HARQ_INDICATION:
+			result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_NRACH_INDICATION:
+			result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_DL_NODE_SYNC:
+			result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_UL_NODE_SYNC:
+			result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_TIMING_INFO:
+			result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		default:
+			{
+				if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					if(config && config->pack_p7_vendor_extension)
+					{
+						result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config);
+					}
+					else
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id);
+					}
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
+				}
+			}
+			break;
+	}
+
+	if(result == 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n");
+		return -1;
+	}
+
+	// check for a valid message length
+	uintptr_t msgHead = (uintptr_t)pPackedBuf;
+	uintptr_t msgEnd = (uintptr_t)pWritePackedMessage;
+	uint32_t packedMsgLen = msgEnd - msgHead;
+	uint16_t packedMsgLen16;
+	if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen);
+		return -1;
+	}
+	else
+	{
+		packedMsgLen16 = (uint16_t)packedMsgLen;
+	}
+
+	// Update the message length in the header
+	pMessageHeader->message_length = packedMsgLen16;
+	
+	if(!push16(packedMsgLen16, &pPackedLengthField, end))
+		return -1;
+		
+	if(1)
+	{
+		//quick test
+		if(pMessageHeader->message_length != packedMsgLen)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id);
+		}
+	}
+
+	return (packedMsgLen);
+}
+
+
+
+// Unpack routines
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; 
+
+	return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) &&
+			pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) &&
+			pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) &&
+			pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end));
+
+}
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) &&
+			 pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) &&
+			 pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end));
+}
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv;
+
+	return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end));
+}
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && 
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end));
+}
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) &&
+			pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end));
+}
+
+static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end)
+{
+	if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && 
+		 pull8(ppReadPackedMsg, &value->number_of_subbands, end) &&
+		 pull8(ppReadPackedMsg, &value->num_antennas, end)))
+		return 0;
+	
+	
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_subbands; ++idx)
+	{
+		nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]);
+		
+		if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) &&
+			 pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end)))
+			return 0;
+			
+		uint8_t antenna_idx = 0;
+		uint8_t scheduled_ue_idx = 0;
+		
+		for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx)
+		{
+			for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx)
+			{
+				if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end))
+					return 0;
+			}
+		}
+
+	}
+	
+	
+	return 1;
+			
+}
+
+
+static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv;
+	
+	// If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been 
+	// added
+	uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5;
+	dci_dl_pdu_rel13->tpm_struct_flag = 0;
+	
+	return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) &&
+			pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && 
+			( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) &&
+			( (tpm_struct_flag_present == 1 &&  dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1));
+			
+}
+
+static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) &&
+			 pull16(ppReadPackedMsg, &bch_pdu_rel8->pdu_index, end) &&
+			 pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end));
+}
+
+static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) &&
+			pull16(ppReadPackedMsg, &mch_pdu_rel8->pdu_index, end) &&
+			pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) &&
+			pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) &&
+			pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) &&
+			pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) &&
+			pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end));
+}
+
+static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv;
+	
+	if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) &&
+		  pull16(ppReadPackedMsg, &dlsch_pdu_rel8->pdu_index, end) &&
+		  pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) &&
+		  pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) &&
+		  pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) &&
+		  pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end)))
+		return 0;
+
+	uint16_t j = 0;
+	for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j)
+	{								
+		if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) &&
+			 pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end)))
+			return 0;
+	}
+	return 1;
+}
+static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv;
+	return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) );
+}
+static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) &&
+			 pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) &&
+			 pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ;
+}
+static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) &&
+			 pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) &&
+			 pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end));
+}
+static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end));
+}
+static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) &&
+			 pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) &&
+			 pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end));
+}
+
+static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) &&
+			 pull16(ppReadPackedMsg, &pch_pdu_rel8->pdu_index, end) &&
+			 pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) &&
+			 pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) &&
+			 pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) &&
+			 pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end));
+}
+static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) &&
+			 pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end));
+}
+
+static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) &&
+			 pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) &&
+			 pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) &&
+			 pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end));
+}
+
+static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) &&
+			 pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) &&
+			 pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) &&
+			 pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) &&
+			 pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) &&
+			 pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end));
+}
+
+static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv;
+	
+	if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) &&
+		  pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) &&
+		  pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end)))
+		return 0;
+
+	
+	uint16_t idx =0;
+	for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx)
+	{
+		if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end)))
+			return 0;
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n");
+		//pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??);
+	}
+	return 1;
+}
+
+static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) &&
+			pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) &&
+			pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) &&
+			pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) &&
+			pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) &&
+			pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) &&
+			pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) &&
+			pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end));
+}
+
+static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) &&
+			 pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end));
+}
+
+static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv;
+	
+	
+	return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) &&
+			 pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) &&
+			 pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) &&
+			 pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) &&
+			 pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) &&
+			 pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) &&
+			 pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) &&
+			 pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end));
+}
+
+
+static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) &&
+			 pull16(ppReadPackedMsg, &nbch_params_rel13->pdu_index, end) &&
+			 pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) &&
+			 pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end));
+}
+
+static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) &&
+			 pull16(ppReadPackedMsg, &npdcch_params_rel13->pdu_index, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) &&
+			 pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) &&
+			 pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end));
+}
+
+static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) &&
+			 pull16(ppReadPackedMsg, &ndlsch_params_rel13->pdu_index, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) &&
+			 pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) &&
+			 pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) &&
+			 pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) &&
+			 pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) &&
+			 pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end));
+} 
+
+
+static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) &&
+		 pull8(ppReadPackedMsg, &value->number_dci, end) &&
+		 pull16(ppReadPackedMsg, &value->number_pdu, end) &&
+		 pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) &&
+		 pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end)))
+		return 0;
+
+	if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_pdu)
+	{
+		value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config);
+		if(value->dl_config_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu);
+			return 0;
+		}
+	}
+	else
+	{
+		value->dl_config_pdu_list = 0;
+	}
+
+	uint16_t i;
+	uint16_t total_number_of_pdus = value->number_pdu;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]);
+		
+		if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) &&
+			 pull8(ppReadPackedMsg, &pdu->pdu_size, end)))
+			return 0;
+					
+		uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2;
+
+		if(packedPduEnd > end)
+		{
+			// pdu end of beyond buffer end
+			return 0;
+		}
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_BCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value},
+						{ NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_PCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value},
+						{ NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_PRS_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value},
+						{ NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value},
+						{ NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_NBCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				
+				}
+				break;
+			case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				
+				}
+				break;
+			default:
+				// Need to log an error
+				break;
+		}
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value},
+	};
+
+	return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			 unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv;
+	
+	return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) &&
+			pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) &&
+			pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end ));
+}
+static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; 
+	
+	return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) &&
+			pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) &
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) &&
+			pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end));
+}
+static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg,	&ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) &&
+			 pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) &&
+			 pull8(ppReadPackedMsg,	&ulsch_pdu_rel11->dmrs_config_flag, end) &&
+			 pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end));
+}
+static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg,  &ulsch_pdu_rel13->ue_type, end) &&
+			pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) &&
+			pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) &&
+			pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) &&
+			pull8(ppReadPackedMsg,  &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end));
+}
+static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) &&
+			pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) &&
+			pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) &&
+			pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) &&
+			pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end));
+}
+
+static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv;
+	
+	if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) &&
+		 pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) &&
+		 pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end)))
+		return 0;
+
+	switch(cqi_ri_info_rel9->report_type)
+	{
+		case NFAPI_CSI_REPORT_TYPE_PERIODIC:
+			{
+				if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) &&
+					 pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end)))
+					return 0;
+			}
+			break;
+		case NFAPI_CSI_REPORT_TYPE_APERIODIC:
+			{
+				if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0)
+					return 0;
+					
+				uint8_t i;
+				for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i)
+				{
+					if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0)
+						return 0;
+
+                                        uint8_t j;
+                                        for(j = 0; j < 8; ++j)
+					{
+						if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0)
+							return 0;
+					}
+				}
+			}
+			break;
+		default:
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type );
+				return 0;
+			}
+			break;
+	};
+	return 1;
+}
+
+// NOTE : This function is a little unconventional as we uese the side to
+// determine the report type
+static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv;
+	if(cqi_ri_info_rel13->tl.length == 0)
+	{
+		cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC;
+	}
+	else
+	{
+		cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC;
+		if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0)
+			return 0;
+	}
+	return 1;
+}
+static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) &&
+			pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end));
+}
+static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end));
+}
+
+static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end));
+}
+
+static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv;
+	
+	return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) &&
+			pull16(ppReadPackedMsg, &ue_info_rel8->rnti, end));
+}
+static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) &&
+			pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end));
+}
+static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) &&
+			pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) &&
+			pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) &&
+			pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end));
+}
+
+static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) &&
+			 pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end));
+}
+static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) &&
+			pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end));
+}
+static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) &&
+			pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) &&
+			pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) &&
+			pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) &&
+			pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) &&
+			pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end));
+}
+		
+static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv;
+	
+	return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end));
+}
+
+static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) &&
+			pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end));
+}
+
+static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) &&
+			pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) &&
+			pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) &&
+			pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) &&
+			pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) &&
+			pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) &&
+			pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end));
+}
+
+static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) &&
+			pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end));
+}
+
+static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) &&
+			pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) &&
+			pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) &&
+			pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) &&
+			pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) &&
+			pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) &&
+			pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end));
+}
+
+static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) &&
+			pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) &&
+			pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) &&
+			pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) &&
+			pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end));
+}
+
+static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) &&
+			pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end));
+}
+
+
+static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv;
+	
+	return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) &&
+			pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) &&
+			pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) &&
+			pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) &&
+			pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) &&
+			pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) &&
+			pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) &&
+			pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end));
+}
+
+static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv;
+	return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end);
+}
+
+static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv;
+
+	return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end));
+}
+
+static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv;
+
+	return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end));
+}
+
+static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && 
+		 pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && 
+		 pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && 
+		 pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && 
+		 pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && 
+		 pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && 
+		 pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end)))
+		return 0;
+		
+	unpack_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value},
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value},
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value},
+		{ NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value},
+	};
+
+	return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0);		
+}
+
+static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv;
+
+	return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) &&
+			pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) &&
+			pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end));
+}
+
+
+static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	#define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, 
+
+	#define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value},
+
+	#define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\
+		{ NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value},
+
+	#define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value},
+
+	#define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value},
+
+	#define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value},
+						
+	#define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value},
+
+	#define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value},
+
+	#define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \
+		{ NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value},
+		
+	#define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value},		
+
+	#define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \
+		{ NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value},		
+
+
+	nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv;
+
+	if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) &&
+		 pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) &&
+		 pull8(ppReadPackedMsg, &value->srs_present, end)))
+		return 0;
+
+	if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_pdus > 0)
+	{
+		value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config);
+
+		if(value->ul_config_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus);
+			return 0;
+		}
+	}
+	else
+	{
+		value->ul_config_pdu_list = 0;
+	}
+
+
+	uint16_t i;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]);
+		
+		if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) &&
+			 pull8(ppReadPackedMsg, &pdu->pdu_size, end)))
+			return 0;
+					
+		uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2;
+
+		if(packedPduEnd > end)
+		{
+			// pdu end is past buffer end
+			return 0;
+		}
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+
+			case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu)
+						UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information)
+						UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu)
+						UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information)
+						UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu)
+						UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information)
+						UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information)
+						UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information)
+						UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information)
+						UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information)
+						UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information)
+						UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_SRS_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu)
+						UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information)
+						UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;	
+			case NFAPI_UL_CONFIG_NRACH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu)
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;						
+		}
+	}
+	return 1;
+}
+
+
+static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv;
+	
+	return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) &&
+			pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) &&
+			pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) &&
+			pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) &&
+			pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end));
+}
+
+static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) &&
+			pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end));
+}
+
+static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) &&
+			pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) &&
+			pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) &&
+			pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end));
+}
+
+static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) &&
+			pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) &&
+			pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end));
+}
+
+static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv;
+	
+	return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) &&
+			 pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end));
+}
+
+static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) &&
+			pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) &&
+			pull8(ppReadPackedMsg, &value->resource_block_assignment, end) &&
+			pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) &&
+			pull8(ppReadPackedMsg, &value->start_symbol, end) &&
+			pull8(ppReadPackedMsg, &value->ecce_index, end) &&
+			pull8(ppReadPackedMsg, &value->aggreagation_level, end) &&
+			pull8(ppReadPackedMsg, &value->rnti_type, end) &&
+			pull16(ppReadPackedMsg, &value->rnti, end) &&
+			pull8(ppReadPackedMsg, &value->ce_mode, end) &&
+			pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) &&
+			pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) &&
+			pull16(ppReadPackedMsg, &value->transmission_power, end) &&
+			pull8(ppReadPackedMsg, &value->dci_format, end) &&
+			pull8(ppReadPackedMsg, &value->resource_block_start, end) &&
+			pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) &&
+			pull8(ppReadPackedMsg, &value->mcs, end) &&
+			pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) &&
+			pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) &&
+			pull8(ppReadPackedMsg, &value->new_data_indication, end) &&
+			pull8(ppReadPackedMsg, &value->harq_process, end) &&
+			pull8(ppReadPackedMsg, &value->redudency_version, end) &&
+			pull8(ppReadPackedMsg, &value->tpc, end) &&
+			pull8(ppReadPackedMsg, &value->csi_request, end) &&
+			pull8(ppReadPackedMsg, &value->ul_inex, end) &&
+			pull8(ppReadPackedMsg, &value->dai_presence_flag, end) &&
+			pull8(ppReadPackedMsg, &value->dl_assignment_index, end) &&
+			pull8(ppReadPackedMsg, &value->srs_request, end) &&
+			pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) &&
+			pull32(ppReadPackedMsg, &value->tcp_bitmap, end) &&
+			pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) &&
+			pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) &&
+			pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end));
+}
+
+static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->ncce_index, end) &&
+			pull8(ppReadPackedMsg, &value->aggregation_level, end) &&
+			pull8(ppReadPackedMsg, &value->start_symbol, end) &&
+			pull16(ppReadPackedMsg, &value->rnti, end) &&
+			pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) &&
+			pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) &&
+			pull8(ppReadPackedMsg, &value->subcarrier_indication, end) &&
+			pull8(ppReadPackedMsg, &value->resource_assignment, end) &&
+			pull8(ppReadPackedMsg, &value->scheduling_delay, end) &&
+			pull8(ppReadPackedMsg, &value->mcs, end) &&
+			pull8(ppReadPackedMsg, &value->redudancy_version, end) &&
+			pull8(ppReadPackedMsg, &value->repetition_number, end) &&
+			pull8(ppReadPackedMsg, &value->new_data_indicator, end) &&
+			pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end));
+}
+
+static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv;
+
+	if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_dci, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_hi, end)))
+		return 0;
+
+	uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci;
+
+	if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU);
+		return 0;		
+	}
+
+	if(totalNumPdus > 0)
+	{
+		value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config);
+		if(value->hi_dci0_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus);
+			return 0;
+		}
+	}
+	else
+	{
+		value->hi_dci0_pdu_list = 0;
+	}
+
+	uint8_t i;
+	for(i = 0; i < totalNumPdus; ++i)
+	{
+		nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]);
+
+		if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) &&
+			 pull8(ppReadPackedMsg, &pdu->pdu_size, end)))
+			return 0;
+
+		uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2;
+
+		if(packedPduEnd > end)
+		{
+			// pdu end if past buffer end
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end);
+			return 0;
+		}
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_HI_DCI0_HI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value},
+						{ NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_HI_DCI0_DCI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value},
+						{ NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value},
+						{ NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value},
+						{ NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value},
+						{ NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type );
+				}
+				break;
+		};
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+
+}
+
+static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	uint8_t proceed = 1;
+	nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg;
+
+	if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0)
+		return 0;
+
+	while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed)
+	{
+		nfapi_tl_t generic_tl;
+		if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+			return 0;
+
+		switch(generic_tl.tag)
+		{
+			case NFAPI_TX_REQUEST_BODY_TAG:
+			{
+				pNfapiMsg->tx_request_body.tl = generic_tl;
+
+				if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0)
+					return 0;
+
+				if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU);
+					return 0;		
+				}
+
+				if(pNfapiMsg->tx_request_body.number_of_pdus > 0)
+				{
+					pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config);
+					if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL)
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx  pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus);
+						return 0;
+					}
+				}
+				else
+				{
+					pNfapiMsg->tx_request_body.tx_pdu_list = 0;
+				}
+
+
+				uint16_t i;
+				uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus;
+				for(i = 0; i < totalNumPdus; ++i)
+				{
+					nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]);
+					
+					uint16_t length = 0;
+					uint16_t index = 0;
+					
+					if(!(pull16(ppReadPackedMsg, &length, end) &&
+						 pull16(ppReadPackedMsg, &index, end)))
+						return 0;
+
+					pdu->pdu_length = length;
+					pdu->pdu_index = index;
+					
+
+					// TODO : May need to rethink this bit
+					pdu->num_segments = 1;
+					pdu->segments[0].segment_length = pdu->pdu_length;
+					pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config);
+
+					if(pdu->segments[0].segment_data)
+					{
+						if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end))
+							return 0;
+                                                if (0 && pdu->segments[0].segment_length == 3)
+                                                {
+                                                  NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, 
+                                                      pdu->segments[0].segment_data[0], 
+                                                      pdu->segments[0].segment_data[1], 
+                                                      pdu->segments[0].segment_data[2]
+                                                      );
+                                                }
+					}
+					else
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index);
+					}
+				}
+			}
+			break;
+			default:
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag );
+			}
+			break;
+		};
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->value_0, end) &&
+			pull8(ppReadPackedMsg, &value->value_1, end));
+}
+
+static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->value_0, end) &&
+			pull8(ppReadPackedMsg, &value->value_1, end) &&
+			pull8(ppReadPackedMsg, &value->value_2, end) &&
+			pull8(ppReadPackedMsg, &value->value_3, end));
+}
+static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv;
+	return ( pull8(ppReadPackedMsg, &value->value_0, end));
+}
+static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv;
+	return  (pull8(ppReadPackedMsg, &value->value_0, end));
+}
+
+static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv;
+	
+	if(!(pull8(ppReadPackedMsg, &value->mode, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_ack_nack, end)))
+		return 0;
+
+	uint8_t result = 0;
+	switch(value->mode)
+	{
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+			result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+			result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+			result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end);
+			break;
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+		case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+			result = 1;
+			break;
+		default:
+			// TODO add error message
+			return 0;
+			break;
+	}
+	return result;
+}
+
+static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv;
+	
+	if(!(pull8(ppReadPackedMsg, &value->mode, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_ack_nack, end)))
+		return 0;
+
+	if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD)
+	{
+		// TODO : add error message
+		return 0;
+	}
+
+	uint16_t idx = 0;
+	for(idx = 0; idx < value->number_of_ack_nack; ++idx)
+	{
+		uint8_t result = 0;
+		switch(value->mode)
+		{
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+				result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end);
+				break;
+			default:
+				// TODO add error message
+				return 0;
+				break;
+		}
+
+		if(result == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv;
+	
+	if(!(pull8(ppReadPackedMsg, &value->mode, end) &&
+		 pull16(ppReadPackedMsg, &value->number_of_ack_nack, end)))
+		return 0;
+
+	if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD)
+	{
+		// TODO : add error message
+		return 0;
+	}
+
+	uint16_t idx = 0;
+	for(idx = 0; idx < value->number_of_ack_nack; ++idx)
+	{
+		uint8_t result = 0;
+		switch(value->mode)
+		{
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING:
+				result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end);
+				break;
+			case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5:
+				result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end);
+				break;
+			default:
+				// TODO add error message
+				return 0;
+				break;
+		}
+
+		if(result == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv;
+	return (pull8(ppReadPackedMsg, &value->harq_tb1, end) &&
+			pull8(ppReadPackedMsg, &value->harq_tb2, end));
+}
+
+static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->mode, end) &&
+			pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) &&
+			pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end));
+}
+
+static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->mode, end) &&
+			pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) &&
+			pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end));
+}
+
+static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv;
+	
+	return (pull8(ppReadPackedMsg, &value->ul_cqi, end) &&
+			pull8(ppReadPackedMsg, &value->channel, end));
+}
+
+
+
+static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv;
+	uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(harqBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0)
+		return 0;
+
+	if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU);
+		return 0;		
+	}
+
+	value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config);
+	if(value->harq_pdu_list == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs);
+		return 0;
+	}
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_harqs; ++i)
+	{
+		nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]);
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value },
+			{ NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value},
+			{ NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value},
+			{ NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value},
+			{ NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value},
+			{ NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value},
+			{ NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value},
+			{ NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value}
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv;
+	return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) );
+}
+
+static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end,  nfapi_p7_codec_config_t* config)
+{
+	nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv;
+	uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(crcBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0)
+		return 0;
+
+	if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_crcs > 0)
+	{
+		value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config);
+		if(value->crc_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs);
+			return 0;
+		}
+	}
+	else
+	{
+		value->crc_pdu_list = 0;
+	}
+
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_crcs; ++i)
+	{
+		nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]);
+
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value },
+			{ NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value },
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &value->length, end) &&
+			pull16(ppReadPackedMsg, &value->offset, end) &&
+			pull8(ppReadPackedMsg, &value->ul_cqi, end) &&
+			pull16(ppReadPackedMsg, &value->timing_advance, end));
+}
+static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv;
+	return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end));
+}
+
+static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv;
+
+	// the rxBodyEnd points to the end of the cqi PDU's
+	uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length;
+	uint8_t* rxPduEnd = rxBodyEnd;
+
+	uint8_t* numberOfPdusAddress = *ppReadPackedMsg;
+
+	if(rxBodyEnd > end)
+	{
+		// pdu end is past buffer end
+		return 0;
+	}
+
+	if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0)
+		return 0;
+
+	if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_pdus > 0)
+	{
+		value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config);
+		if(value->rx_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus);
+			return 0;
+		}
+	}
+	else
+	{
+		value->rx_pdu_list = 0;
+	}
+	
+	uint8_t i = 0;
+	nfapi_rx_indication_pdu_t* pdu = 0;
+	while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd)
+	{
+		nfapi_tl_t generic_tl;
+		if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+			return 0;
+
+		switch(generic_tl.tag)
+		{
+			case NFAPI_RX_UE_INFORMATION_TAG:
+				{
+					pdu = &(value->rx_pdu_list[i++]);
+					pdu->rx_ue_information.tl = generic_tl;
+					if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0)
+						return 0;
+				}
+				break;
+			case NFAPI_RX_INDICATION_REL8_TAG:
+				{
+					if(pdu != 0)
+					{
+						pdu->rx_indication_rel8.tl = generic_tl;
+						if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0)
+							return 0;
+		
+						if(pdu->rx_indication_rel8.offset > 0)
+						{
+							// Need to check that the data is within the tlv
+							if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd)
+							{
+								// If this the first pdu set the rxPduEnd
+								if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd)
+								{
+									rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset;
+		
+									if(rxPduEnd > end)
+									{
+										// pdu end is past buffer end
+										return 0;
+									}
+								}
+							}
+							else
+							{
+								NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n");
+							}
+						}
+					}
+				}
+				break;
+			case NFAPI_RX_INDICATION_REL9_TAG:
+				{
+					if(pdu != 0)
+					{
+						pdu->rx_indication_rel9.tl = generic_tl;
+						if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0)
+							return 0;
+					}
+				}
+				break;
+			default:
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag );
+				}
+				break;
+		}
+	}
+	
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_pdus; ++idx)
+	{
+		if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG)
+		{
+			uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length;
+			value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config);
+			if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0)
+			{
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) &&
+			pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) &&
+			pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end));
+}
+
+static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv;
+	return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end);
+}
+
+static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv;
+	return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end);
+}
+
+static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv;
+	uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(rachBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0)
+		return 0;
+
+	if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_preambles > 0)
+	{
+		value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config);
+		if(value->preamble_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles);
+			return 0;
+		}
+	}
+	else
+	{
+		value->preamble_list = 0;
+	}
+
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_preambles; ++i)
+	{
+		nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]);
+
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value },
+			{ NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value },
+			{ NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value },
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv;
+	
+	if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) &&
+		 pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) &&
+		 pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) &&
+		 pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) &&
+		 pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end)))
+		return 0;
+	return 1;
+}
+
+static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv;
+	return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end));
+}
+
+static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv;
+	return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end));
+}
+
+static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv;
+	return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end));
+}
+
+static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv;
+	
+	if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) &&
+		 pull8(ppReadPackedMsg, &value->number_of_subbands, end) &&
+		 pull8(ppReadPackedMsg, &value->num_atennas, end)))
+		return 0;
+
+	if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS)
+	{
+		// todo : add error
+		return 0;
+	}
+
+	if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS)
+	{
+		// todo : add error
+		return 0;
+	}
+
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_subbands; ++idx)
+	{
+		if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) &&
+			 pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end)))
+			return 0;
+	}
+
+	return 1;
+}
+
+
+static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv;
+	uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length;
+	
+	if(srsBodyEnd > end)
+		return 0;
+
+	if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0)
+		return 0;
+
+	if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_ues > 0)
+	{
+		value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config);
+		if(value->srs_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues);
+			return 0;
+		}
+	}
+	else
+	{
+		value->srs_pdu_list = 0;
+	}
+
+
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_ues; ++i)
+	{
+		nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]);
+
+		
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value },
+			{ NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value},
+			{ NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value},
+			{ NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value},
+			{ NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value},
+			{ NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value},
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+
+static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv;
+	uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(srBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0)
+		return 0;
+
+	if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_srs > 0)
+	{
+		value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config);
+		if(value->sr_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs);
+			return 0;
+		}
+	}
+	else
+	{
+		value->sr_pdu_list = 0;
+	}
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_srs; ++i)
+	{
+		nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]);
+
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value },
+			{ NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value },
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	}
+
+	return 1;
+
+}
+
+static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) &&
+			pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) &&
+			pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) &&
+			pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) &&
+			pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end));
+
+}
+
+static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv;
+	
+	if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) &&
+		 pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) &&
+		 pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) &&
+		 pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end)))
+		return 0;
+
+	if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n");
+		return 0;
+	}
+	
+	if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) &&
+		 pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) &&
+		 pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end)))
+		return 0;
+
+	return 1;
+}
+
+static uint8_t  unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end,  nfapi_p7_codec_config_t* config)
+{
+	nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv;
+
+	// the cqiBodyEnd points to the end of the cqi PDU's
+	uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	//uint8_t* cqiPduEnd = cqiBodyEnd;
+	//uint8_t* numberOfPdusAddress = *ppReadPackedMsg;
+
+	if(cqiBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0)
+		return 0;
+
+	if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU);
+		return -1;		
+	}
+
+	if(value->number_of_cqis > 0)
+	{
+		value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config);
+		if(value->cqi_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis);
+			return 0;
+		}
+	}
+	else
+	{
+		value->cqi_pdu_list = 0;
+	}
+
+	if(value->number_of_cqis > 0)
+	{
+		value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config);
+		if(value->cqi_raw_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis);
+			return 0;
+		}
+	}
+	else
+	{
+		value->cqi_raw_pdu_list = 0;
+	}
+
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_cqis; ++i)
+	{
+		nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]);
+		memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t));
+
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+
+		while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd)
+		{
+			nfapi_tl_t generic_tl;
+			if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+				return 0;
+
+			switch(generic_tl.tag)
+			{
+				case NFAPI_RX_UE_INFORMATION_TAG:
+					pdu->rx_ue_information.tl = generic_tl;
+					if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0)
+						return 0;
+					break;
+				case NFAPI_CQI_INDICATION_REL8_TAG:
+					pdu->cqi_indication_rel8.tl = generic_tl;
+					if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0)
+						return 0;
+
+					break;
+				case NFAPI_CQI_INDICATION_REL9_TAG:
+					pdu->cqi_indication_rel9.tl = generic_tl;
+					if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0)
+						return 0;
+
+					break;
+				case NFAPI_UL_CQI_INFORMATION_TAG:
+					pdu->ul_cqi_information.tl = generic_tl;
+					if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0)
+						return 0;
+					break;
+				default:
+					{
+						NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag );
+					}
+					break;
+
+			};
+		}
+	}
+
+	uint8_t idx = 0;
+	for(idx = 0; idx < value->number_of_cqis; ++idx)
+	{
+		if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG)
+		{
+			if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0)
+				return 0;
+		}
+		else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG)
+		{
+			if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0)
+				return 0;
+		}
+	}
+
+
+	return 1;
+
+}
+
+static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv;
+
+	return (pull32(ppReadPackedMsg, &value->handle, end) &&
+			pull32(ppReadPackedMsg, &value->mp_cca, end) &&
+			pull32(ppReadPackedMsg, &value->n_cca, end) &&
+			pull32(ppReadPackedMsg, &value->offset, end) &&
+			pull32(ppReadPackedMsg, &value->lte_txop_sf, end) &&
+			pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) &&
+			pull32(ppReadPackedMsg, &value->lbt_mode, end));
+}
+
+static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv;
+
+	return (pull32(ppReadPackedMsg, &value->handle, end) &&
+			pull32(ppReadPackedMsg, &value->offset, end) &&
+			pull16(ppReadPackedMsg, &value->sfn_sf_end, end) &&
+			pull32(ppReadPackedMsg, &value->lbt_mode, end));
+}
+
+
+static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0)
+		return 0;
+
+	if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_pdus)
+	{
+		value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config);
+		if(value->lbt_dl_config_req_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus);
+			return 0;
+		}
+	}
+	else
+	{
+		value->lbt_dl_config_req_pdu_list = 0;
+	}
+
+
+	uint16_t i;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]);
+
+		if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) &&
+			 pull8(ppReadPackedMsg, &pdu->pdu_size, end)))
+			return 0;
+			
+		uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2;
+
+		if(packedPduEnd > end)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			default:
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type);
+				return 0;
+		}
+	}
+
+	return 1;
+}
+static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value},
+	};
+	
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv;
+	
+	return (pull32(ppReadPackedMsg, &value->handle, end) &&
+			pull32(ppReadPackedMsg, &value->result, end) &&
+			pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) &&
+			pull32(ppReadPackedMsg, &value->initial_partial_sf, end));
+	
+}
+static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv;
+	
+	return (pull32(ppReadPackedMsg, &value->handle, end) &&
+			pull32(ppReadPackedMsg, &value->result, end));
+}
+
+static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0)
+		return 0;
+
+	if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU);
+		return 0;		
+	}
+
+	if(value->number_of_pdus > 0)
+	{
+		value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config);
+		if(value->lbt_indication_pdu_list == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus);
+			return 0;
+		}
+	}
+	else
+	{
+		value->lbt_indication_pdu_list = 0;
+	}
+
+	uint16_t i;
+	uint16_t total_number_of_pdus = value->number_of_pdus;
+	for(i = 0; i < total_number_of_pdus; ++i)
+	{
+		nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]);
+
+		if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) &&
+			 pull8(ppReadPackedMsg, &pdu->pdu_size, end)))
+			return 0;
+			
+		uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2;
+
+		if(packedPduEnd > end)
+			return 0;
+
+		switch(pdu->pdu_type)
+		{
+			case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE:
+				{
+					unpack_tlv_t unpack_fns[] =
+					{
+						{ NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value},
+					};
+
+					unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0);
+				}
+				break;
+			default:
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type);
+				return 0;
+		}
+	}
+
+	return 1;
+}
+static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv;
+	return (pull8(ppReadPackedMsg, &value->harq_tb1, end));
+}
+
+
+static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv;
+	uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(nbharqBodyEnd > end)
+		return 0;
+
+	if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0)
+		return 0;
+
+	if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU);
+		return 0;		
+	}
+
+	value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config);
+	if(value->nb_harq_pdu_list == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs);
+		return 0;
+	}
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_harqs; ++i)
+	{
+		nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]);
+		if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0)
+			return 0;
+
+		uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length;
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value },
+			{ NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value},
+			{ NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value}
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+	nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv;
+	
+	return (pull16(ppReadPackedMsg, &value->rnti, end) && 
+			pull8(ppReadPackedMsg, &value->initial_sc, end) &&
+			pull16(ppReadPackedMsg, &value->timing_advance, end) &&
+			pull8(ppReadPackedMsg, &value->nrach_ce_level, end));
+}
+
+
+static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv;
+	uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length;
+
+	if(nrachBodyEnd > end)
+		return 0;
+
+	if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0)
+		return 0;
+
+	if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU);
+		return 0;		
+	}
+
+	value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config);
+	if(value->nrach_pdu_list == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected);
+		return 0;
+	}
+	
+	uint8_t i = 0;
+	for(i = 0; i < value->number_of_initial_scs_detected; ++i)
+	{
+		nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]);
+
+		uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6;
+
+		unpack_tlv_t unpack_fns[] =
+		{
+			{ NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value},
+		};
+
+		if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0)
+			return 0;
+	
+	}
+
+	return 1;
+}
+
+static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+		{ NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value},
+	};
+
+	return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && 
+			pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg;
+
+	unpack_p7_tlv_t unpack_fns[] =
+	{
+	};
+
+	return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) &&
+			pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) &&
+			pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) &&
+			unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension));
+}
+
+
+// unpack length check
+
+static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen)
+{
+	int retLen = 0;
+
+	switch (msgId)
+	{
+		case NFAPI_DL_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t))
+				retLen = sizeof(nfapi_dl_config_request_t);
+			break;
+
+		case NFAPI_UL_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t))
+				retLen = sizeof(nfapi_ul_config_request_t);
+			break;
+
+		case NFAPI_SUBFRAME_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t))
+				retLen = sizeof(nfapi_subframe_indication_t);
+			break;
+
+		case NFAPI_HI_DCI0_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t))
+				retLen = sizeof(nfapi_hi_dci0_request_t);
+			break;
+
+		case NFAPI_TX_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_tx_request_t))
+				retLen = sizeof(nfapi_tx_request_t);
+			break;
+
+		case NFAPI_HARQ_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_harq_indication_t))
+				retLen = sizeof(nfapi_harq_indication_t);
+			break;
+
+		case NFAPI_CRC_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_crc_indication_t))
+				retLen = sizeof(nfapi_crc_indication_t);
+			break;
+
+		case NFAPI_RX_ULSCH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_rx_indication_t))
+				retLen = sizeof(nfapi_rx_indication_t);
+			break;
+
+		case NFAPI_RACH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_rach_indication_t))
+				retLen = sizeof(nfapi_rach_indication_t);
+			break;
+
+		case NFAPI_SRS_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_srs_indication_t))
+				retLen = sizeof(nfapi_srs_indication_t);
+			break;
+
+		case NFAPI_RX_SR_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_sr_indication_t))
+				retLen = sizeof(nfapi_sr_indication_t);
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t))
+				retLen = sizeof(nfapi_cqi_indication_t);
+			break;
+
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t))
+				retLen = sizeof(nfapi_lbt_dl_config_request_t);
+			break;
+
+		case NFAPI_LBT_DL_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t))
+				retLen = sizeof(nfapi_lbt_dl_indication_t);
+			break;
+	
+		case NFAPI_NB_HARQ_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t))
+				retLen = sizeof(nfapi_nb_harq_indication_t);
+			break;
+			
+		case NFAPI_NRACH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t))
+				retLen = sizeof(nfapi_nrach_indication_t);
+			break;			
+			
+		case NFAPI_DL_NODE_SYNC:
+			if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t))
+				retLen = sizeof(nfapi_dl_node_sync_t);
+			break;
+
+		case NFAPI_UL_NODE_SYNC:
+			if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t))
+				retLen = sizeof(nfapi_ul_node_sync_t);
+			break;
+
+		case NFAPI_TIMING_INFO:
+			if (unpackedBufLen >= sizeof(nfapi_timing_info_t))
+				retLen = sizeof(nfapi_timing_info_t);
+			break;
+
+		default:
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId);
+			break;
+	}
+
+	return retLen;
+}
+
+
+// Main unpack functions - public
+
+int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config)
+{
+	nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// process the header
+	if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) &&
+		 pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) &&
+		 pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end)))
+		return -1;
+
+	return 0;
+}
+
+int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config)
+{
+	int result = 0;
+	nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf;
+	uint8_t *pReadPackedMessage = pMessageBuf;
+	uint8_t *end = pMessageBuf + messageBufLen;
+
+	if (pMessageBuf == NULL || pUnpackedBuf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n");
+		return -1;
+	}
+
+	if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
+		return -1;
+	}
+
+	// clean the supplied buffer for - tag value blanking
+	(void)memset(pUnpackedBuf, 0, unpackedBufLen);
+
+	// process the header
+	if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) &&
+		 pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) &&
+		 pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) &&
+		 pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end)))
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n");
+		return -1;
+	}
+
+	if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n");
+		return -1;
+	}
+
+	/*
+	if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n");
+		return -1;
+	}
+	*/
+
+	// look for the specific message
+	switch (pMessageHeader->message_id)
+	{
+		case NFAPI_DL_CONFIG_REQUEST:
+			if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen))
+				result = unpack_dl_config_request(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_UL_CONFIG_REQUEST:
+			if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen))
+				result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_HI_DCI0_REQUEST:
+			if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen))
+				result = unpack_hi_dci0_request(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_TX_REQUEST:
+			if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen))
+				result = unpack_tx_request(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_HARQ_INDICATION:
+			if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen))
+				result = unpack_harq_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_CRC_INDICATION:
+			if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen))
+				result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RX_ULSCH_INDICATION:
+			if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen))
+				result = unpack_rx_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RACH_INDICATION:
+			if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen))
+				result = unpack_rach_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_SRS_INDICATION:
+			if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen))
+				result = unpack_srs_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RX_SR_INDICATION:
+			if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen))
+				result = unpack_sr_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen))
+				result = unpack_cqi_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen))
+				result = unpack_lbt_dl_config_request(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_LBT_DL_INDICATION:
+			if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen))
+				result = unpack_lbt_dl_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+			
+		case NFAPI_NB_HARQ_INDICATION:
+			if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen))
+				result = unpack_nb_harq_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;	
+			
+		case NFAPI_NRACH_INDICATION:
+			if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen))
+				result = unpack_nrach_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+			
+		case NFAPI_DL_NODE_SYNC:
+			if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen))
+				result = unpack_dl_node_sync(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_UL_NODE_SYNC:
+			if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen))
+				result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_TIMING_INFO:
+			if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen))
+				result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		default:
+
+			if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && 
+			   pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+			{
+				if(config && config->unpack_p7_vendor_extension)
+				{
+					result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id);
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
+			}
+			break;
+	}
+
+	if(result == 0)
+		return -1;
+	else 
+		return 0;
+}
+
diff --git a/nfapi/open-nFAPI/nfapi/tests/Makefile.am b/nfapi/open-nFAPI/nfapi/tests/Makefile.am
new file mode 100644
index 0000000000..46785869b0
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/tests/Makefile.am
@@ -0,0 +1,36 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+#nfapi unit test
+AUTOMAKE_OPTIONS=subdir-objects
+
+AM_CPPFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc  -I$(top_srcdir)/common/public_inc -I$(top_srcdir)pnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
+AM_CFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc  -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/pnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
+
+check_PROGRAMS= test_nfapi
+test_nfapi_SOURCES = nfapi_cunit_main.c ../src/nfapi.c ../src/nfapi_p7.c ../../common/src/debug.c ../src/nfapi_p5.c  ../src/nfapi_p4.c 
+test_nfapi_LDADD=$(top_builddir)/pnf/libnfapi_pnf.a  -L$(libdir) -lpthread -lrt -lsctp -lz -lcunit
+
+
+#jTEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh --ingore-exit
+#TEST_ENVIRONMENT = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh
+
+#AM_TESTS_ENVIRONMENT = env AM_TAP_AWK='$(AWK)' $(SHELL);
+LOG_DRIVER = $(top_srcdir)/tap-driver.sh
+#AM_LOG_FLAGS = -- test_nfapi
+
+TESTS=$(check_PROGRAMS)
+EXTRA_DIST = $(TESTS)
diff --git a/nfapi/open-nFAPI/nfapi/tests/nfapi_cunit_main.c b/nfapi/open-nFAPI/nfapi/tests/nfapi_cunit_main.c
new file mode 100644
index 0000000000..daaf65a3ff
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/tests/nfapi_cunit_main.c
@@ -0,0 +1,5511 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "CUnit.h"
+#include "Basic.h"
+#include "Automated.h"
+//#include "CUnit/Console.h"
+
+#include "nfapi_interface.h"
+#include "nfapi.h"
+#include <stdio.h>  // for printf
+#include <stdlib.h>
+#include "debug.h"
+#include "nfapi_interface.h"
+/* Test Suite setup and cleanup functions: */
+
+int init_suite(void) { return 0; }
+int clean_suite(void) { return 0; }
+
+#define MAX_PACKED_MESSAGE_SIZE	8192
+
+#define IN_OUT_ASSERT(_V) { CU_ASSERT_EQUAL(in._V, out._V); }
+
+typedef struct 
+{
+	nfapi_tl_t tl;
+	uint16_t value1;
+	uint32_t value2;
+} my_vendor_extention;
+
+extern void* nfapi_allocate_pdu(size_t size)
+{
+	return malloc(size);
+}
+
+extern int nfapi_test_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, nfapi_p4_p5_codec_config_t* config)
+{
+	printf("nfapi_unpack_vendor_extension_tlv\n");
+
+	if(tl->tag == NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE)
+	{
+		my_vendor_extention* mve = (my_vendor_extention*)malloc(sizeof(my_vendor_extention));
+		mve->tl.tag = NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE;
+		
+		if(!(pull16(ppReadPackedMsg, &mve->value1, end) &&
+		     pull32(ppReadPackedMsg, &mve->value2, end)))
+		{
+			free(mve);
+			return 0;
+		}
+
+		(*ve) = mve;
+
+	}
+
+	return 1;
+}
+
+int nfapi_pack_vendor_extension_tlv_called = 0;
+extern int nfapi_test_pack_vendor_extension_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	printf("nfapi_pack_vendor_extension_tlv\n");
+	nfapi_pack_vendor_extension_tlv_called++;
+
+	my_vendor_extention* mve = (my_vendor_extention*)ve;
+	
+	return (push16(mve->value1, ppWritePackedMsg, end) &&
+			push32(mve->value2, ppWritePackedMsg, end));
+
+}
+
+uint8_t gTestNfapiMessageTx[MAX_PACKED_MESSAGE_SIZE];
+
+
+uint8_t rand8(uint8_t min, uint8_t max)
+{
+	return ((rand() % (max + 1 - min)) + min);
+}
+
+/************* Test case functions ****************/
+
+void test_case_sample(void)
+{
+	/*Sample assert function, use as per your test case scenario.*/
+	CU_ASSERT(CU_TRUE);
+	CU_ASSERT_NOT_EQUAL(2, -1);
+	CU_ASSERT_STRING_EQUAL("string #1", "string #1");
+	CU_ASSERT_STRING_NOT_EQUAL("string #1", "string #2");
+
+	CU_ASSERT(CU_FALSE);
+	CU_ASSERT_EQUAL(2, 3);
+	CU_ASSERT_STRING_NOT_EQUAL("string #1", "string #1");
+	CU_ASSERT_STRING_EQUAL("string #1", "string #2");
+}
+
+
+int nfapi_test_verify_configreq_params(nfapi_pnf_config_request_t pnfConfigRequest_in, nfapi_pnf_config_request_t pnfConfigRequest_out)
+{
+	int i=0;
+	if(memcmp(&pnfConfigRequest_in, &pnfConfigRequest_out, sizeof(nfapi_pnf_config_request_t)) == 0)
+	{	
+		/*packed and unpacked phy config request are matched.*/
+
+		printf("Success: packed and unpacked phy config request are matched\n");
+		return 1;
+	}
+	else
+	{
+		if (pnfConfigRequest_in.header.message_id != pnfConfigRequest_out.header.message_id)
+		{
+			printf("Mismatch: packed message id %d, unpacked message id %d\n",
+					pnfConfigRequest_in.header.message_id, pnfConfigRequest_out.header.message_id);
+		}
+		if (pnfConfigRequest_in.header.message_length != pnfConfigRequest_out.header.message_length)
+		{
+			printf("Mismatch: packed message_length %d, unpacked message_length %d\n",
+					pnfConfigRequest_in.header.message_length, pnfConfigRequest_out.header.message_length);
+		}
+		if (pnfConfigRequest_in.header.phy_id != pnfConfigRequest_out.header.phy_id)
+		{
+			printf("Mismatch: packed phy_id %d, unpacked phy_id %d\n",
+					pnfConfigRequest_in.header.phy_id, pnfConfigRequest_out.header.phy_id);
+		}
+		if (pnfConfigRequest_in.pnf_phy_rf_config.number_phy_rf_config_info != pnfConfigRequest_out.pnf_phy_rf_config.number_phy_rf_config_info)			
+		{
+			printf("Mismatch: packed number_phy_rf_config_info %d, unpacked number_phy_rf_config_info %d\n",
+					pnfConfigRequest_in.pnf_phy_rf_config.number_phy_rf_config_info, pnfConfigRequest_out.pnf_phy_rf_config.number_phy_rf_config_info);
+		}
+
+		for (i=0; i < NFAPI_MAX_PHY_RF_INSTANCES; i++) 
+		{
+			if (pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].phy_id != pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].phy_id)			
+			{
+				printf("Mismatch: rf idx %d, packed phy id %d, unpacked phy id %d\n",
+						i, pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].phy_id, pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].phy_id);
+			}
+			if (pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].phy_config_index!= pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].phy_config_index)			
+			{
+				printf("Mismatch: rf idx %d, packed phy_config_index %d, unpacked phy_config_index %d\n",
+						i, pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].phy_config_index, pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].phy_config_index);
+			}
+			if (pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].rf_config_index != pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].rf_config_index)			
+			{
+				printf("Mismatch: rf idx %d, packed rf_config_index %d, unpacked rf_config_index %d\n",
+						i, pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[i].rf_config_index, pnfConfigRequest_out.pnf_phy_rf_config.phy_rf_config[i].rf_config_index);
+			}
+		}
+		return 0;
+	}
+
+}
+
+
+void nfapi_test_pnf_config_req(void) 
+{
+
+	nfapi_pnf_config_request_t pnfConfigRequest_out;
+	nfapi_pnf_config_request_t pnfConfigRequest_in;
+	int packedMessageLength =0;
+
+	printf(" nfapi_test_pnf_config_req run \n");
+
+	/* Build phy config req */
+	pnfConfigRequest_in.header.phy_id = NFAPI_PHY_ID_NA;
+	pnfConfigRequest_in.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
+	pnfConfigRequest_in.header.message_length = 22;
+	pnfConfigRequest_in.header.spare = 0;
+
+	pnfConfigRequest_in.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
+	pnfConfigRequest_in.pnf_phy_rf_config.tl.length = 0;
+	pnfConfigRequest_in.pnf_phy_rf_config.number_phy_rf_config_info = 2;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[0].phy_id = 4;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[0].phy_config_index = 1;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[0].rf_config_index = 1;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[1].phy_id = 5;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[1].phy_config_index = 2;
+	pnfConfigRequest_in.pnf_phy_rf_config.phy_rf_config[1].rf_config_index = 2;
+
+	/*Pack pnf config req*/
+	packedMessageLength = nfapi_p5_message_pack(&pnfConfigRequest_in, sizeof(nfapi_pnf_config_request_t), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	/*Unpack pnf config request*/
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &pnfConfigRequest_out, sizeof(nfapi_pnf_config_request_t), 0);
+
+	/*Verify unpacked message*/
+	CU_ASSERT_EQUAL(nfapi_test_verify_configreq_params(pnfConfigRequest_in, pnfConfigRequest_out), 1);  
+
+}
+
+void nfapi_test_2(void) {
+	/*Sample test function*/
+	CU_ASSERT_EQUAL( 0, 0);
+}
+
+void nfapi_test_rssi_request_lte()
+{
+	uint16_t idx;
+	nfapi_rssi_request_t in;
+	nfapi_rssi_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.lte_rssi_request.tl.tag = NFAPI_LTE_RSSI_REQUEST_TAG;
+	in.lte_rssi_request.frequency_band_indicator = 0;
+	in.lte_rssi_request.bandwidth = 0;
+	in.lte_rssi_request.timeout = 0;
+	in.lte_rssi_request.number_of_earfcns = 4;
+	in.lte_rssi_request.earfcn[0] = 42;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int upack_result = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, -1);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, 0);
+	CU_ASSERT_NOT_EQUAL(upack_result, 0);
+	CU_ASSERT_NOT_EQUAL(upack_result, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.frequency_band_indicator, out.lte_rssi_request.frequency_band_indicator);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.bandwidth, out.lte_rssi_request.bandwidth);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.timeout, out.lte_rssi_request.timeout);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.number_of_earfcns, out.lte_rssi_request.number_of_earfcns);
+
+	for(idx = 0; idx < out.lte_rssi_request.number_of_earfcns; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_rssi_request.earfcn[idx], out.lte_rssi_request.earfcn[idx]);
+	}
+}
+
+void nfapi_test_rssi_request_lte2()
+{
+	uint16_t idx;
+	nfapi_rssi_request_t in;
+	nfapi_rssi_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.lte_rssi_request.tl.tag = NFAPI_LTE_RSSI_REQUEST_TAG;
+	in.lte_rssi_request.frequency_band_indicator = 0;
+	in.lte_rssi_request.bandwidth = 0;
+	in.lte_rssi_request.timeout = 0;
+	in.lte_rssi_request.number_of_earfcns = 4;
+	in.lte_rssi_request.earfcn[0] = 42;
+
+	// try and pak with a buffer that is too small
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, NFAPI_HEADER_LENGTH + 4, 0);
+	CU_ASSERT_EQUAL(packedMessageLength, -1);
+
+	// pack correctly
+	packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	// unpack with a small bufer
+	int upack_result = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength - 1, &out, sizeof(out), 0);
+
+	upack_result = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, -1);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, 0);
+	CU_ASSERT_NOT_EQUAL(upack_result, 0);
+	CU_ASSERT_NOT_EQUAL(upack_result, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.frequency_band_indicator, out.lte_rssi_request.frequency_band_indicator);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.bandwidth, out.lte_rssi_request.bandwidth);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.timeout, out.lte_rssi_request.timeout);
+	CU_ASSERT_EQUAL(in.lte_rssi_request.number_of_earfcns, out.lte_rssi_request.number_of_earfcns);
+
+	for(idx = 0; idx < out.lte_rssi_request.number_of_earfcns; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_rssi_request.earfcn[idx], out.lte_rssi_request.earfcn[idx]);
+	}
+}
+
+
+
+// Test decoding of message which has a large number if earfcn which could
+// cause a buffer over run if not handled
+void nfapi_test_rssi_request_lte_overrun()
+{
+	nfapi_rssi_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t* end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_RSSI_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_LTE, &p, end);
+	push16(NFAPI_LTE_RSSI_REQUEST_TAG, &p, end);
+	push16(11, &p, end);
+
+	push8(0, &p, end);
+	push16(0, &p, end);
+	push8(0, &p, end);
+	push32(0, &p, end);
+	push8(123, &p, end); // to many EARFCN's
+	push16(16, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, sizeof(buffer), &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_rssi_request_lte_rat_type_mismatch()
+{
+	nfapi_rssi_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_RSSI_REQUEST, &p, end);
+	push16(16, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_GERAN, &p, end);
+
+	push16(NFAPI_LTE_RSSI_REQUEST_TAG, &p, end);
+	push16(11, &p, end);
+
+	push8(0, &p, end);
+	push16(0, &p, end);
+	push8(0, &p, end);
+	push32(0, &p, end);
+	push8(1, &p, end);
+	push16(16, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, sizeof(buffer), &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_rssi_request_utran()
+{
+	uint16_t idx;
+	nfapi_rssi_request_t in;
+	nfapi_rssi_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_UTRAN;
+
+
+	in.utran_rssi_request.tl.tag = NFAPI_UTRAN_RSSI_REQUEST_TAG;
+	in.utran_rssi_request.frequency_band_indicator = 0;
+	in.utran_rssi_request.measurement_period = 0;
+	in.utran_rssi_request.timeout = 0;
+	in.utran_rssi_request.number_of_uarfcns = 3;
+	in.utran_rssi_request.uarfcn[0] = 42;
+	in.utran_rssi_request.uarfcn[1] = 42;
+	in.utran_rssi_request.uarfcn[2] = 42;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.utran_rssi_request.frequency_band_indicator, out.utran_rssi_request.frequency_band_indicator);
+	CU_ASSERT_EQUAL(in.utran_rssi_request.measurement_period, out.utran_rssi_request.measurement_period);
+	CU_ASSERT_EQUAL(in.utran_rssi_request.timeout, out.utran_rssi_request.timeout);
+	CU_ASSERT_EQUAL(in.utran_rssi_request.number_of_uarfcns, out.utran_rssi_request.number_of_uarfcns);
+
+	for(idx = 0; idx < out.utran_rssi_request.number_of_uarfcns; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.utran_rssi_request.uarfcn[idx], out.utran_rssi_request.uarfcn[idx]);
+	}
+
+}
+
+void nfapi_test_rssi_request_geran()
+{
+	uint16_t idx;
+	nfapi_rssi_request_t in;
+	nfapi_rssi_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_GERAN;
+
+	in.geran_rssi_request.tl.tag = NFAPI_GERAN_RSSI_REQUEST_TAG;
+	in.geran_rssi_request.frequency_band_indicator = 0;
+	in.geran_rssi_request.measurement_period = 0;
+	in.geran_rssi_request.timeout = 0;
+	in.geran_rssi_request.number_of_arfcns = 3;
+	in.geran_rssi_request.arfcn[0].arfcn = 42;
+	in.geran_rssi_request.arfcn[0].direction = 0;
+	in.geran_rssi_request.arfcn[1].arfcn = 42;
+	in.geran_rssi_request.arfcn[1].direction = 1;
+	in.geran_rssi_request.arfcn[2].arfcn = 42;
+	in.geran_rssi_request.arfcn[2].direction = 1;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.geran_rssi_request.frequency_band_indicator, out.geran_rssi_request.frequency_band_indicator);
+	CU_ASSERT_EQUAL(in.geran_rssi_request.measurement_period, out.geran_rssi_request.measurement_period);
+	CU_ASSERT_EQUAL(in.geran_rssi_request.timeout, out.geran_rssi_request.timeout);
+	CU_ASSERT_EQUAL(in.geran_rssi_request.number_of_arfcns, out.geran_rssi_request.number_of_arfcns);
+
+	for(idx = 0; idx < out.geran_rssi_request.number_of_arfcns; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.geran_rssi_request.arfcn[idx].arfcn, out.geran_rssi_request.arfcn[idx].arfcn);
+		CU_ASSERT_EQUAL(in.geran_rssi_request.arfcn[idx].direction, out.geran_rssi_request.arfcn[idx].direction);
+	}
+}
+
+void nfapi_test_rssi_request_nb_iot()
+{
+	uint16_t idx, idx2;
+	nfapi_rssi_request_t in;
+	nfapi_rssi_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_NB_IOT;
+
+	in.nb_iot_rssi_request.tl.tag = NFAPI_NB_IOT_RSSI_REQUEST_TAG;
+	in.nb_iot_rssi_request.frequency_band_indicator = 34;
+	in.nb_iot_rssi_request.measurement_period = 900;
+	in.nb_iot_rssi_request.timeout = 4321;
+	in.nb_iot_rssi_request.number_of_earfcns = 3;
+	in.nb_iot_rssi_request.earfcn[0].earfcn = 42;
+	in.nb_iot_rssi_request.earfcn[0].number_of_ro_dl = 1;
+	in.nb_iot_rssi_request.earfcn[0].ro_dl[0] = 2;
+	in.nb_iot_rssi_request.earfcn[1].earfcn = 43;
+	in.nb_iot_rssi_request.earfcn[1].number_of_ro_dl = 0;
+	in.nb_iot_rssi_request.earfcn[2].earfcn = 44;
+	in.nb_iot_rssi_request.earfcn[2].number_of_ro_dl = 2;
+	in.nb_iot_rssi_request.earfcn[2].ro_dl[0] = 0;
+	in.nb_iot_rssi_request.earfcn[2].ro_dl[1] = 4;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	IN_OUT_ASSERT(header.message_id);
+	IN_OUT_ASSERT(rat_type);
+	IN_OUT_ASSERT(nb_iot_rssi_request.frequency_band_indicator);
+	IN_OUT_ASSERT(nb_iot_rssi_request.measurement_period);
+	IN_OUT_ASSERT(nb_iot_rssi_request.timeout);
+	IN_OUT_ASSERT(nb_iot_rssi_request.number_of_earfcns);
+
+	for(idx = 0; idx < out.nb_iot_rssi_request.number_of_earfcns; ++idx)
+	{
+		IN_OUT_ASSERT(nb_iot_rssi_request.earfcn[idx].earfcn);
+		IN_OUT_ASSERT(nb_iot_rssi_request.earfcn[idx].number_of_ro_dl);
+		
+		for(idx2 = 0; idx2 < out.nb_iot_rssi_request.earfcn[idx].number_of_ro_dl; ++idx2)
+			IN_OUT_ASSERT(nb_iot_rssi_request.earfcn[idx].ro_dl[idx2]);
+	}
+}
+
+
+void nfapi_test_rssi_response()
+{
+	nfapi_rssi_response_t in;
+	nfapi_rssi_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+
+}
+
+void nfapi_test_rssi_indication()
+{
+	uint16_t idx = 0;
+	nfapi_rssi_indication_t in;
+	nfapi_rssi_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RSSI_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_OK;
+	in.rssi_indication_body.tl.tag = NFAPI_RSSI_INDICATION_TAG;
+	in.rssi_indication_body.tl.length = 0;
+	in.rssi_indication_body.number_of_rssi = 4;
+	in.rssi_indication_body.rssi[0] = 2;
+	in.rssi_indication_body.rssi[1] = 0;
+	in.rssi_indication_body.rssi[2] = -23;
+	in.rssi_indication_body.rssi[3] = -18000;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.rssi_indication_body.tl.tag, out.rssi_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.rssi_indication_body.number_of_rssi, out.rssi_indication_body.number_of_rssi);
+
+	for(idx = 0; idx < out.rssi_indication_body.number_of_rssi; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.rssi_indication_body.rssi[idx], out.rssi_indication_body.rssi[idx]);
+	}
+
+}
+void nfapi_test_rssi_indication_overrun()
+{
+	nfapi_rssi_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_RSSI_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error code
+
+	push16(NFAPI_RSSI_INDICATION_TAG, &p, end);
+	push16(11, &p, end);
+
+	push16(NFAPI_MAX_RSSI + 23, &p, end); // to many EARFCN's
+	push16(16, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, sizeof(buffer), &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_cell_search_request_lte()
+{
+	uint16_t idx;
+	nfapi_cell_search_request_t in;
+	nfapi_cell_search_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.lte_cell_search_request.tl.tag = NFAPI_LTE_CELL_SEARCH_REQUEST_TAG;
+	in.lte_cell_search_request.earfcn = 213;
+	in.lte_cell_search_request.measurement_bandwidth = 1;
+	in.lte_cell_search_request.exhaustive_search = 0;
+	in.lte_cell_search_request.timeout = 123;
+	in.lte_cell_search_request.number_of_pci = 3;
+	in.lte_cell_search_request.pci[0] = 3;
+	in.lte_cell_search_request.pci[1] = 6;
+	in.lte_cell_search_request.pci[2] = 9;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_cell_search_request.earfcn, out.lte_cell_search_request.earfcn);
+	CU_ASSERT_EQUAL(in.lte_cell_search_request.measurement_bandwidth, out.lte_cell_search_request.measurement_bandwidth);
+	CU_ASSERT_EQUAL(in.lte_cell_search_request.exhaustive_search, out.lte_cell_search_request.exhaustive_search);
+	CU_ASSERT_EQUAL(in.lte_cell_search_request.timeout, out.lte_cell_search_request.timeout);
+	CU_ASSERT_EQUAL(in.lte_cell_search_request.number_of_pci, out.lte_cell_search_request.number_of_pci);
+
+	for(idx = 0; idx < out.lte_cell_search_request.number_of_pci; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_cell_search_request.pci[idx], out.lte_cell_search_request.pci[idx]);
+	}
+}
+
+void nfapi_test_cell_search_request_utran()
+{
+	uint16_t idx;
+	nfapi_cell_search_request_t in;
+	nfapi_cell_search_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_UTRAN;
+
+	in.utran_cell_search_request.tl.tag = NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG;
+	in.utran_cell_search_request.uarfcn = 213;
+	in.utran_cell_search_request.exhaustive_search = 0;
+	in.utran_cell_search_request.timeout = 123;
+	in.utran_cell_search_request.number_of_psc = 3;
+	in.utran_cell_search_request.psc[0] = 3;
+	in.utran_cell_search_request.psc[1] = 6;
+	in.utran_cell_search_request.psc[2] = 9;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.utran_cell_search_request.uarfcn, out.utran_cell_search_request.uarfcn);
+	CU_ASSERT_EQUAL(in.utran_cell_search_request.exhaustive_search, out.utran_cell_search_request.exhaustive_search);
+	CU_ASSERT_EQUAL(in.utran_cell_search_request.timeout, out.utran_cell_search_request.timeout);
+	CU_ASSERT_EQUAL(in.utran_cell_search_request.number_of_psc, out.utran_cell_search_request.number_of_psc);
+
+	for(idx = 0; idx < out.utran_cell_search_request.number_of_psc; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.utran_cell_search_request.psc[idx], out.utran_cell_search_request.psc[idx]);
+	}
+}
+
+void nfapi_test_cell_search_request_geran()
+{
+	uint16_t idx;
+	nfapi_cell_search_request_t in;
+	nfapi_cell_search_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_GERAN;
+
+	in.geran_cell_search_request.tl.tag = NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG;
+	in.geran_cell_search_request.timeout = 123;
+	in.geran_cell_search_request.number_of_arfcn = 3;
+	in.geran_cell_search_request.arfcn[0] = 3;
+	in.geran_cell_search_request.arfcn[1] = 6;
+	in.geran_cell_search_request.arfcn[2] = 9;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.geran_cell_search_request.timeout, out.geran_cell_search_request.timeout);
+	CU_ASSERT_EQUAL(in.geran_cell_search_request.number_of_arfcn, out.geran_cell_search_request.number_of_arfcn);
+
+	for(idx = 0; idx < out.geran_cell_search_request.number_of_arfcn; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.geran_cell_search_request.arfcn[idx], out.geran_cell_search_request.arfcn[idx]);
+	}
+}
+
+void nfapi_test_cell_search_request_nb_iot()
+{
+	uint16_t idx;
+	nfapi_cell_search_request_t in;
+	nfapi_cell_search_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_NB_IOT;
+
+	in.nb_iot_cell_search_request.tl.tag = NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG;
+	in.nb_iot_cell_search_request.earfcn = 54;
+	in.nb_iot_cell_search_request.ro_dl = 3;
+	in.nb_iot_cell_search_request.exhaustive_search = 1;
+	in.nb_iot_cell_search_request.timeout = 123;
+	in.nb_iot_cell_search_request.number_of_pci = 3;
+	in.nb_iot_cell_search_request.pci[0] = 3;
+	in.nb_iot_cell_search_request.pci[1] = 6;
+	in.nb_iot_cell_search_request.pci[2] = 9;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	IN_OUT_ASSERT(header.message_id);
+	IN_OUT_ASSERT(rat_type);
+	IN_OUT_ASSERT(nb_iot_cell_search_request.earfcn);
+	IN_OUT_ASSERT(nb_iot_cell_search_request.ro_dl);
+	IN_OUT_ASSERT(nb_iot_cell_search_request.exhaustive_search);
+	IN_OUT_ASSERT(nb_iot_cell_search_request.timeout);
+	IN_OUT_ASSERT(nb_iot_cell_search_request.number_of_pci);
+
+	for(idx = 0; idx < out.nb_iot_cell_search_request.number_of_pci; ++idx)
+	{
+		IN_OUT_ASSERT(nb_iot_cell_search_request.pci[idx]);
+	}
+}
+
+void nfapi_test_cell_search_response()
+{
+	nfapi_cell_search_response_t in;
+	nfapi_cell_search_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+
+void nfapi_test_cell_search_indication_lte()
+{
+	uint16_t idx = 0;
+	nfapi_cell_search_indication_t in;
+	nfapi_cell_search_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_OK;
+	in.lte_cell_search_indication.tl.tag = NFAPI_LTE_CELL_SEARCH_INDICATION_TAG;
+	in.lte_cell_search_indication.number_of_lte_cells_found = 2;
+	in.lte_cell_search_indication.lte_found_cells[0].pci = 0;
+	in.lte_cell_search_indication.lte_found_cells[0].rsrp = 42;
+	in.lte_cell_search_indication.lte_found_cells[0].rsrq= 11;
+	in.lte_cell_search_indication.lte_found_cells[0].frequency_offset = -100;
+
+	in.lte_cell_search_indication.lte_found_cells[1].pci = 123;
+	in.lte_cell_search_indication.lte_found_cells[1].rsrp = 2;
+	in.lte_cell_search_indication.lte_found_cells[1].rsrq= 17;
+	in.lte_cell_search_indication.lte_found_cells[1].frequency_offset = 123;
+
+	in.utran_cell_search_indication.tl.tag = 0;
+	in.geran_cell_search_indication.tl.tag = 0;
+	in.nb_iot_cell_search_indication.tl.tag = 0;
+	in.pnf_cell_search_state.tl.tag = 0;
+
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_cell_search_indication.tl.tag, out.lte_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_cell_search_indication.number_of_lte_cells_found, out.lte_cell_search_indication.number_of_lte_cells_found);
+
+	for(idx = 0; idx < out.lte_cell_search_indication.number_of_lte_cells_found; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_cell_search_indication.lte_found_cells[idx].pci, out.lte_cell_search_indication.lte_found_cells[idx].pci);
+		CU_ASSERT_EQUAL(in.lte_cell_search_indication.lte_found_cells[idx].rsrp, out.lte_cell_search_indication.lte_found_cells[idx].rsrp);
+		CU_ASSERT_EQUAL(in.lte_cell_search_indication.lte_found_cells[idx].rsrq, out.lte_cell_search_indication.lte_found_cells[idx].rsrq);
+		CU_ASSERT_EQUAL(in.lte_cell_search_indication.lte_found_cells[idx].frequency_offset, out.lte_cell_search_indication.lte_found_cells[idx].frequency_offset);
+	}
+
+
+	CU_ASSERT_EQUAL(in.utran_cell_search_indication.tl.tag, out.utran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_cell_search_indication.tl.tag, out.geran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.tl.tag, out.pnf_cell_search_state.tl.tag);
+}
+void nfapi_test_cell_search_indication_utran()
+{
+	uint16_t idx = 0;
+	nfapi_cell_search_indication_t in;
+	nfapi_cell_search_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_OK;
+	in.utran_cell_search_indication.tl.tag = NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG;
+	in.utran_cell_search_indication.number_of_utran_cells_found = 1;
+	in.utran_cell_search_indication.utran_found_cells[0].psc = 123;
+	in.utran_cell_search_indication.utran_found_cells[0].rscp = 2;
+	in.utran_cell_search_indication.utran_found_cells[0].ecno = 89;
+	in.utran_cell_search_indication.utran_found_cells[0].frequency_offset = -1000;
+
+	in.lte_cell_search_indication.tl.tag = 0;
+	in.geran_cell_search_indication.tl.tag = 0;
+	in.nb_iot_cell_search_indication.tl.tag = 0;
+	in.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	in.pnf_cell_search_state.length = 12;
+	in.pnf_cell_search_state.value[0] = 34;
+	in.pnf_cell_search_state.value[1] = 35;
+	in.pnf_cell_search_state.value[2] = 36;
+	in.pnf_cell_search_state.value[3] = 37;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.utran_cell_search_indication.tl.tag, out.utran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_cell_search_indication.number_of_utran_cells_found, out.utran_cell_search_indication.number_of_utran_cells_found);
+
+	for(idx = 0; idx < out.utran_cell_search_indication.number_of_utran_cells_found; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.utran_cell_search_indication.utran_found_cells[idx].psc, out.utran_cell_search_indication.utran_found_cells[idx].psc);
+		CU_ASSERT_EQUAL(in.utran_cell_search_indication.utran_found_cells[idx].rscp, out.utran_cell_search_indication.utran_found_cells[idx].rscp);
+		CU_ASSERT_EQUAL(in.utran_cell_search_indication.utran_found_cells[idx].ecno, out.utran_cell_search_indication.utran_found_cells[idx].ecno);
+		CU_ASSERT_EQUAL(in.utran_cell_search_indication.utran_found_cells[idx].frequency_offset, out.utran_cell_search_indication.utran_found_cells[idx].frequency_offset);
+	}
+
+	CU_ASSERT_EQUAL(in.lte_cell_search_indication.tl.tag, out.lte_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_cell_search_indication.tl.tag, out.geran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.tl.tag, out.pnf_cell_search_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.length, out.pnf_cell_search_state.length);
+
+	for(idx = 0; idx < out.pnf_cell_search_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_search_state.value[idx], out.pnf_cell_search_state.value[idx]);
+	}
+}
+void nfapi_test_cell_search_indication_geran()
+{
+	uint16_t idx = 0;
+	nfapi_cell_search_indication_t in;
+	nfapi_cell_search_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_OK;
+	in.geran_cell_search_indication.tl.tag = NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG;
+	in.geran_cell_search_indication.number_of_gsm_cells_found = 1;
+	in.geran_cell_search_indication.gsm_found_cells[0].arfcn = 123;
+	in.geran_cell_search_indication.gsm_found_cells[0].bsic = 2;
+	in.geran_cell_search_indication.gsm_found_cells[0].rxlev = 89;
+	in.geran_cell_search_indication.gsm_found_cells[0].rxqual = 12;
+	in.geran_cell_search_indication.gsm_found_cells[0].frequency_offset = 2389;
+	in.geran_cell_search_indication.gsm_found_cells[0].sfn_offset = 23;
+
+	in.lte_cell_search_indication.tl.tag = 0;
+	in.utran_cell_search_indication.tl.tag = 0;
+	in.nb_iot_cell_search_indication.tl.tag = 0;
+	in.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	in.pnf_cell_search_state.length = 63;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.geran_cell_search_indication.tl.tag, out.geran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_cell_search_indication.number_of_gsm_cells_found, out.geran_cell_search_indication.number_of_gsm_cells_found);
+
+	for(idx = 0; idx < out.geran_cell_search_indication.number_of_gsm_cells_found; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].arfcn, out.geran_cell_search_indication.gsm_found_cells[idx].arfcn);
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].bsic, out.geran_cell_search_indication.gsm_found_cells[idx].bsic);
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].rxlev, out.geran_cell_search_indication.gsm_found_cells[idx].rxlev);
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].rxqual, out.geran_cell_search_indication.gsm_found_cells[idx].rxqual);
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].frequency_offset, out.geran_cell_search_indication.gsm_found_cells[idx].frequency_offset);
+		CU_ASSERT_EQUAL(in.geran_cell_search_indication.gsm_found_cells[idx].sfn_offset, out.geran_cell_search_indication.gsm_found_cells[idx].sfn_offset);
+	}
+
+	CU_ASSERT_EQUAL(in.lte_cell_search_indication.tl.tag, out.lte_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_cell_search_indication.tl.tag, out.utran_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_cell_search_indication.tl.tag, out.nb_iot_cell_search_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.tl.tag, out.pnf_cell_search_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.length, out.pnf_cell_search_state.length);
+
+	for(idx = 0; idx < out.pnf_cell_search_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_search_state.value[idx], out.pnf_cell_search_state.value[idx]);
+	}
+}
+
+void nfapi_test_cell_search_indication_nb_iot()
+{
+	uint16_t idx = 0;
+	nfapi_cell_search_indication_t in;
+	nfapi_cell_search_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_OK;
+	in.nb_iot_cell_search_indication.tl.tag = NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG;
+	in.nb_iot_cell_search_indication.number_of_nb_iot_cells_found = 1;
+	in.nb_iot_cell_search_indication.nb_iot_found_cells[0].pci = 123;
+	in.nb_iot_cell_search_indication.nb_iot_found_cells[0].rsrp = 2;
+	in.nb_iot_cell_search_indication.nb_iot_found_cells[0].rsrq = 89;
+	in.nb_iot_cell_search_indication.nb_iot_found_cells[0].frequency_offset = 2389;
+
+	in.lte_cell_search_indication.tl.tag = 0;
+	in.utran_cell_search_indication.tl.tag = 0;
+	in.geran_cell_search_indication.tl.tag = 0;
+	
+	in.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	in.pnf_cell_search_state.length = 63;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	IN_OUT_ASSERT(header.message_id);
+	IN_OUT_ASSERT(error_code);
+	IN_OUT_ASSERT(nb_iot_cell_search_indication.tl.tag);
+	IN_OUT_ASSERT(nb_iot_cell_search_indication.number_of_nb_iot_cells_found);
+
+	for(idx = 0; idx < out.nb_iot_cell_search_indication.number_of_nb_iot_cells_found; ++idx)
+	{
+		IN_OUT_ASSERT(nb_iot_cell_search_indication.nb_iot_found_cells[idx].pci);
+		IN_OUT_ASSERT(nb_iot_cell_search_indication.nb_iot_found_cells[idx].rsrp);
+		IN_OUT_ASSERT(nb_iot_cell_search_indication.nb_iot_found_cells[idx].rsrq);
+		IN_OUT_ASSERT(nb_iot_cell_search_indication.nb_iot_found_cells[idx].frequency_offset);
+	}
+
+	IN_OUT_ASSERT(lte_cell_search_indication.tl.tag);
+	IN_OUT_ASSERT(utran_cell_search_indication.tl.tag);
+	IN_OUT_ASSERT(geran_cell_search_indication.tl.tag);
+	IN_OUT_ASSERT(pnf_cell_search_state.tl.tag);
+	IN_OUT_ASSERT(pnf_cell_search_state.length);
+	
+	for(idx = 0; idx < out.pnf_cell_search_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_search_state.value[idx], out.pnf_cell_search_state.value[idx]);
+	}
+}
+
+void nfapi_test_cell_search_request_lte_overrun()
+{
+	nfapi_cell_search_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(0, &p, end); // rat_type
+
+	push16(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(11, &p, end);
+	push8(11, &p, end);
+	push8(11, &p, end);
+	push32(11, &p, end);
+	push8(NFAPI_MAX_PCI_LIST + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+
+}
+void nfapi_test_cell_search_request_utran_overrun()
+{
+	nfapi_cell_search_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_UTRAN, &p, end); // rat_type
+
+	push16(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(11, &p, end);
+	push8(11, &p, end);
+	push32(11, &p, end);
+	push8(NFAPI_MAX_PSC_LIST + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_cell_search_request_geran_overrun()
+{
+	nfapi_cell_search_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_GERAN, &p, end); // rat_type
+
+	push16(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &p, end);
+	push16(8, &p, end);
+
+	push32(11, &p, end);
+	push8(NFAPI_MAX_ARFCN_LIST + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_cell_search_indication_lte_overrun()
+{
+	nfapi_cell_search_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_LTE_CELLS_FOUND + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_cell_search_indication_utran_overrun()
+{
+	nfapi_cell_search_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_UTRAN_CELLS_FOUND + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_cell_search_indication_geran_overrun()
+{
+	nfapi_cell_search_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_GSM_CELLS_FOUND + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_cell_search_indication_state_overrun()
+{
+	nfapi_cell_search_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_CELL_SEARCH_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &p, end);
+	push16(13, &p, end);
+
+	push16(1, &p, end);
+	if(1)
+	{
+		push16(42, &p, end);
+		push8(42, &p, end);
+		push8(42, &p, end);
+		push8(42, &p, end);
+		pushs16(42, &p, end);
+		push32(42, &p, end);
+	}
+
+	push16(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &p, end);
+	push16(NFAPI_MAX_OPAQUE_DATA + 12, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_broadcast_detect_request_lte()
+{
+	nfapi_broadcast_detect_request_t in;
+	nfapi_broadcast_detect_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.lte_broadcast_detect_request.tl.tag = NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG;
+	in.lte_broadcast_detect_request.earfcn = 123;
+	in.lte_broadcast_detect_request.pci = 12;
+	in.lte_broadcast_detect_request.timeout = 1246;
+
+	in.pnf_cell_search_state.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_request.earfcn, out.lte_broadcast_detect_request.earfcn);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_request.pci, out.lte_broadcast_detect_request.pci);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_request.timeout, out.lte_broadcast_detect_request.timeout);
+
+}
+void nfapi_test_broadcast_detect_request_utran()
+{
+	uint16_t idx;
+	nfapi_broadcast_detect_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_broadcast_detect_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_UTRAN;
+
+	in.utran_broadcast_detect_request.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG;
+	in.utran_broadcast_detect_request.uarfcn = 123;
+	in.utran_broadcast_detect_request.psc = 12;
+	in.utran_broadcast_detect_request.timeout = 1246;
+
+	in.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	in.pnf_cell_search_state.length = 60;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, -1);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_request.uarfcn, out.utran_broadcast_detect_request.uarfcn);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_request.psc, out.utran_broadcast_detect_request.psc);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_request.timeout, out.utran_broadcast_detect_request.timeout);
+
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.length, out.pnf_cell_search_state.length);
+
+	for(idx = 0; idx < out.pnf_cell_search_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_search_state.value[idx], out.pnf_cell_search_state.value[idx]);
+	}
+
+}
+
+void nfapi_test_broadcast_detect_request_nb_iot()
+{
+	uint16_t idx;
+	nfapi_broadcast_detect_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_broadcast_detect_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_NB_IOT;
+
+	in.nb_iot_broadcast_detect_request.tl.tag = NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG;
+	in.nb_iot_broadcast_detect_request.earfcn = 123;
+	in.nb_iot_broadcast_detect_request.ro_dl = 12;
+	in.nb_iot_broadcast_detect_request.pci = 12;
+	in.nb_iot_broadcast_detect_request.timeout = 1246;
+
+	in.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	in.pnf_cell_search_state.length = 60;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, -1);
+
+	int unpackResult = nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, 0);
+	CU_ASSERT_NOT_EQUAL(unpackResult, -1);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_request.earfcn, out.nb_iot_broadcast_detect_request.earfcn);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_request.ro_dl, out.nb_iot_broadcast_detect_request.ro_dl);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_request.pci, out.nb_iot_broadcast_detect_request.pci);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_request.timeout, out.nb_iot_broadcast_detect_request.timeout);
+
+	CU_ASSERT_EQUAL(in.pnf_cell_search_state.length, out.pnf_cell_search_state.length);
+
+	for(idx = 0; idx < out.pnf_cell_search_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_search_state.value[idx], out.pnf_cell_search_state.value[idx]);
+	}
+
+}
+
+
+void nfapi_test_broadcast_detect_request_state_overrun()
+{
+	nfapi_broadcast_detect_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_BROADCAST_DETECT_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_UTRAN, &p, end); // error_code
+
+	push16(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(42, &p, end);
+	push16(42, &p, end);
+	push32(42, &p, end);
+
+	push16(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &p, end);
+	push16(NFAPI_MAX_OPAQUE_DATA + 12, &p, end);
+
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_broadcast_detect_response()
+{
+	nfapi_broadcast_detect_response_t in;
+	nfapi_broadcast_detect_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+
+}
+void nfapi_test_broadcast_detect_indication_lte()
+{
+	uint16_t idx;
+	nfapi_broadcast_detect_indication_t in;
+	nfapi_broadcast_detect_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	in.lte_broadcast_detect_indication.tl.tag = NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG;
+	in.lte_broadcast_detect_indication.number_of_tx_antenna = 1;
+	in.lte_broadcast_detect_indication.mib_length = 8;
+	in.lte_broadcast_detect_indication.sfn_offset = 4;
+	in.utran_broadcast_detect_indication.tl.tag = 0;
+	in.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	in.pnf_cell_broadcast_state.length = 23;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.tl.tag, out.lte_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.number_of_tx_antenna, out.lte_broadcast_detect_indication.number_of_tx_antenna);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.mib_length, out.lte_broadcast_detect_indication.mib_length);
+	for(idx = 0; idx < out.lte_broadcast_detect_indication.mib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.mib[idx], out.lte_broadcast_detect_indication.mib[idx]);
+	}
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.sfn_offset, out.lte_broadcast_detect_indication.sfn_offset);
+
+
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.tl.tag, out.utran_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+	for(idx = 0; idx < out.pnf_cell_broadcast_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.value[idx], out.pnf_cell_broadcast_state.value[idx]);
+	}
+}
+void nfapi_test_broadcast_detect_indication_lte_overrun()
+{
+	nfapi_broadcast_detect_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_BROADCAST_DETECT_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push8(1, &p, end);
+	push16(NFAPI_MAX_MIB_LENGTH + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out) ,0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_broadcast_detect_indication_utran()
+{
+	uint16_t idx;
+	nfapi_broadcast_detect_indication_t in;
+	nfapi_broadcast_detect_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	in.lte_broadcast_detect_indication.tl.tag = 0;
+	in.utran_broadcast_detect_indication.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG;
+	in.utran_broadcast_detect_indication.mib_length = 16;
+	in.utran_broadcast_detect_indication.sfn_offset = 4;
+	in.pnf_cell_broadcast_state.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.tl.tag, out.lte_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.tl.tag, out.utran_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.mib_length, out.utran_broadcast_detect_indication.mib_length);
+	for(idx = 0; idx < out.utran_broadcast_detect_indication.mib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.mib[idx], out.utran_broadcast_detect_indication.mib[idx]);
+	}
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.sfn_offset, out.utran_broadcast_detect_indication.sfn_offset);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+}
+void nfapi_test_broadcast_detect_indication_nb_iot()
+{
+	uint16_t idx;
+	nfapi_broadcast_detect_indication_t in;
+	nfapi_broadcast_detect_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_BROADCAST_DETECT_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	in.lte_broadcast_detect_indication.tl.tag = 0;
+	in.utran_broadcast_detect_indication.tl.tag = 0;
+	in.nb_iot_broadcast_detect_indication.tl.tag = NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG;
+	in.nb_iot_broadcast_detect_indication.number_of_tx_antenna = 2;
+	in.nb_iot_broadcast_detect_indication.mib_length = 16;
+	in.nb_iot_broadcast_detect_indication.sfn_offset = 4;
+	in.pnf_cell_broadcast_state.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_broadcast_detect_indication.tl.tag, out.lte_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_broadcast_detect_indication.tl.tag, out.utran_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_indication.tl.tag, out.nb_iot_broadcast_detect_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_indication.number_of_tx_antenna, out.nb_iot_broadcast_detect_indication.number_of_tx_antenna);
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_indication.mib_length, out.nb_iot_broadcast_detect_indication.mib_length);
+	for(idx = 0; idx < out.nb_iot_broadcast_detect_indication.mib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_indication.mib[idx], out.nb_iot_broadcast_detect_indication.mib[idx]);
+	}
+	CU_ASSERT_EQUAL(in.nb_iot_broadcast_detect_indication.sfn_offset, out.nb_iot_broadcast_detect_indication.sfn_offset);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+}
+void nfapi_test_broadcast_detect_indication_utran_overrun()
+{
+	nfapi_broadcast_detect_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_BROADCAST_DETECT_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error_code
+
+	push16(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_MIB_LENGTH + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_broadcast_detect_indication_state_overrun()
+{
+}
+void nfapi_test_system_information_schedule_request_lte()
+{
+	uint16_t idx;
+	nfapi_system_information_schedule_request_t in;
+	nfapi_system_information_schedule_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.nb_iot_system_information_schedule_request.tl.tag = 0;
+
+	in.lte_system_information_schedule_request.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG;
+	in.lte_system_information_schedule_request.earfcn = 16;
+	in.lte_system_information_schedule_request.pci = 4;
+	in.lte_system_information_schedule_request.downlink_channel_bandwidth = 20;
+	in.lte_system_information_schedule_request.phich_configuration = 1;
+	in.lte_system_information_schedule_request.number_of_tx_antenna = 2;
+	in.lte_system_information_schedule_request.retry_count = 4;
+	in.lte_system_information_schedule_request.timeout = 0;
+	in.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	in.pnf_cell_broadcast_state.length = 7;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.tl.tag, out.lte_system_information_schedule_request.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.earfcn, out.lte_system_information_schedule_request.earfcn);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.pci, out.lte_system_information_schedule_request.pci);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.downlink_channel_bandwidth, out.lte_system_information_schedule_request.downlink_channel_bandwidth);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.downlink_channel_bandwidth, out.lte_system_information_schedule_request.downlink_channel_bandwidth);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.number_of_tx_antenna, out.lte_system_information_schedule_request.number_of_tx_antenna);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.retry_count, out.lte_system_information_schedule_request.retry_count);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.timeout, out.lte_system_information_schedule_request.timeout);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.length, out.pnf_cell_broadcast_state.length);
+	for(idx = 0; idx < out.pnf_cell_broadcast_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.value[idx], out.pnf_cell_broadcast_state.value[idx]);
+	}
+}
+
+void nfapi_test_system_information_schedule_request_nb_iot()
+{
+	uint16_t idx;
+	nfapi_system_information_schedule_request_t in;
+	nfapi_system_information_schedule_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_NB_IOT;
+
+	in.lte_system_information_schedule_request.tl.tag = 0;
+	in.nb_iot_system_information_schedule_request.tl.tag = NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG;
+	in.nb_iot_system_information_schedule_request.earfcn = 16;
+	in.nb_iot_system_information_schedule_request.ro_dl = 4;
+	in.nb_iot_system_information_schedule_request.pci = 4;
+	in.nb_iot_system_information_schedule_request.scheduling_info_sib1_nb = 4;
+	in.nb_iot_system_information_schedule_request.timeout = 0;
+	in.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	in.pnf_cell_broadcast_state.length = 7;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_system_information_schedule_request.tl.tag, out.lte_system_information_schedule_request.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.tl.tag, out.nb_iot_system_information_schedule_request.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.earfcn, out.nb_iot_system_information_schedule_request.earfcn);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.ro_dl, out.nb_iot_system_information_schedule_request.ro_dl);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.pci, out.nb_iot_system_information_schedule_request.pci);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.scheduling_info_sib1_nb, out.nb_iot_system_information_schedule_request.scheduling_info_sib1_nb);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_schedule_request.timeout, out.nb_iot_system_information_schedule_request.timeout);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.length, out.pnf_cell_broadcast_state.length);
+	for(idx = 0; idx < out.pnf_cell_broadcast_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.value[idx], out.pnf_cell_broadcast_state.value[idx]);
+	}
+}
+
+void nfapi_test_system_information_schedule_request_state_overrun()
+{
+	nfapi_system_information_schedule_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(0, &p, end); // rat type
+
+	push16(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &p, end);
+	push16(13, &p, end);
+
+	push16(1, &p, end);
+	push16(1, &p, end);
+	push16(1, &p, end);
+	push8(142, &p, end);
+	push8(142, &p, end);
+	push8(142, &p, end);
+	push32(42, &p, end);
+
+	push16(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &p, end);
+	push16(NFAPI_MAX_OPAQUE_DATA + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+
+}
+void nfapi_test_system_information_schedule_response()
+{
+	nfapi_system_information_schedule_response_t in;
+	nfapi_system_information_schedule_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_system_information_schedule_indication_lte()
+{
+	uint16_t idx;
+	nfapi_system_information_schedule_indication_t in;
+	nfapi_system_information_schedule_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = 0;
+
+	in.nb_iot_system_information_indication.tl.tag = 0;
+	in.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.lte_system_information_indication.sib_type = 16;
+	in.lte_system_information_indication.sib_length = 4;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.sib_type, out.lte_system_information_indication.sib_type);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.sib_length, out.lte_system_information_indication.sib_length);
+
+	for(idx = 0; idx < out.lte_system_information_indication.sib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_system_information_indication.sib[idx], out.lte_system_information_indication.sib[idx]);
+	}
+}
+void nfapi_test_system_information_schedule_indication_nb_iot()
+{
+	uint16_t idx;
+	nfapi_system_information_schedule_indication_t in;
+	nfapi_system_information_schedule_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = 0;
+
+	in.lte_system_information_indication.tl.tag = 0;
+	in.nb_iot_system_information_indication.tl.tag = NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.nb_iot_system_information_indication.sib_type = 16;
+	in.nb_iot_system_information_indication.sib_length = 4;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.tl.tag, out.nb_iot_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib_type, out.nb_iot_system_information_indication.sib_type);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib_length, out.nb_iot_system_information_indication.sib_length);
+
+	for(idx = 0; idx < out.nb_iot_system_information_indication.sib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib[idx], out.nb_iot_system_information_indication.sib[idx]);
+	}
+}
+void nfapi_test_system_information_request_lte()
+{
+	uint16_t idx;
+	nfapi_system_information_request_t in;
+	nfapi_system_information_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_LTE;
+
+	in.lte_system_information_request.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG;
+	in.lte_system_information_request.earfcn = 16;
+	in.lte_system_information_request.pci = 4;
+	in.lte_system_information_request.downlink_channel_bandwidth = 20;
+	in.lte_system_information_request.phich_configuration = 1;
+	in.lte_system_information_request.number_of_tx_antenna = 2;
+	in.lte_system_information_request.number_of_si_periodicity = 1;
+	in.lte_system_information_request.si_periodicity[0].si_periodicity = 3;
+	in.lte_system_information_request.si_periodicity[0].si_index = 0;
+	in.lte_system_information_request.si_window_length = 0;
+	in.lte_system_information_request.timeout = 2000;
+
+	in.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	in.pnf_cell_broadcast_state.length = 7;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.tl.tag, out.lte_system_information_request.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.earfcn, out.lte_system_information_request.earfcn);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.pci, out.lte_system_information_request.pci);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.downlink_channel_bandwidth, out.lte_system_information_request.downlink_channel_bandwidth);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.downlink_channel_bandwidth, out.lte_system_information_request.downlink_channel_bandwidth);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.number_of_tx_antenna, out.lte_system_information_request.number_of_tx_antenna);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.number_of_si_periodicity, out.lte_system_information_request.number_of_si_periodicity);
+	for(idx = 0; idx < in.lte_system_information_request.number_of_si_periodicity; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_system_information_request.si_periodicity[idx].si_periodicity, out.lte_system_information_request.si_periodicity[idx].si_periodicity);
+		CU_ASSERT_EQUAL(in.lte_system_information_request.si_periodicity[idx].si_index, out.lte_system_information_request.si_periodicity[idx].si_index);
+	}
+
+	CU_ASSERT_EQUAL(in.lte_system_information_request.si_window_length, out.lte_system_information_request.si_window_length);
+	CU_ASSERT_EQUAL(in.lte_system_information_request.timeout, out.lte_system_information_request.timeout);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.length, out.pnf_cell_broadcast_state.length);
+	for(idx = 0; idx < out.pnf_cell_broadcast_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.value[idx], out.pnf_cell_broadcast_state.value[idx]);
+	}
+}
+void nfapi_test_system_information_request_lte_overrun()
+{
+	nfapi_system_information_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_LTE, &p, end); 
+
+	push16(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(8, &p, end);
+	push16(8, &p, end);
+	push16(8, &p, end);
+	push8(8, &p, end);
+	push8(8, &p, end);
+	push8(NFAPI_MAX_SI_PERIODICITY + 1, &p, end);
+
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_system_information_request_utran()
+{
+	nfapi_system_information_request_t in;
+	nfapi_system_information_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_UTRAN;
+
+	in.utran_system_information_request.tl.tag = NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG;
+	in.utran_system_information_request.uarfcn = 16;
+	in.utran_system_information_request.psc = 4;
+	in.utran_system_information_request.timeout = 2000;
+
+	in.pnf_cell_broadcast_state.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.utran_system_information_request.tl.tag, out.utran_system_information_request.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_system_information_request.uarfcn, out.utran_system_information_request.uarfcn);
+	CU_ASSERT_EQUAL(in.utran_system_information_request.psc, out.utran_system_information_request.psc);
+	CU_ASSERT_EQUAL(in.utran_system_information_request.timeout, out.utran_system_information_request.timeout);
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+}
+void nfapi_test_system_information_request_geran()
+{
+	nfapi_system_information_request_t in;
+	nfapi_system_information_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_GERAN;
+
+	in.geran_system_information_request.tl.tag = NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG;
+	in.geran_system_information_request.arfcn = 16;
+	in.geran_system_information_request.bsic = 4;
+	in.geran_system_information_request.timeout = 2000;
+
+	in.pnf_cell_broadcast_state.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rat_type, out.rat_type);
+	CU_ASSERT_EQUAL(in.geran_system_information_request.tl.tag, out.geran_system_information_request.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_system_information_request.arfcn, out.geran_system_information_request.arfcn);
+	CU_ASSERT_EQUAL(in.geran_system_information_request.bsic, out.geran_system_information_request.bsic);
+	CU_ASSERT_EQUAL(in.geran_system_information_request.timeout, out.geran_system_information_request.timeout);
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+}
+void nfapi_test_system_information_request_state_overrun()
+{
+	nfapi_system_information_request_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_REQUEST, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push8(NFAPI_RAT_TYPE_LTE, &p, end); 
+
+	push16(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &p, end);
+	push16(16, &p, end);
+
+	push16(8, &p, end);
+	push16(8, &p, end);
+	push16(8, &p, end);
+	push8(8, &p, end);
+	push8(8, &p, end);
+	push8(1, &p, end);
+	{
+		push8(1, &p, end);
+		push8(1, &p, end);
+	}
+	push8(1, &p, end);
+	push32(1, &p, end);
+
+	push16(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &p, end);
+	push16(NFAPI_MAX_OPAQUE_DATA + 1, &p, end);
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_system_information_request_nb_iot()
+{
+	uint16_t idx, idx2;
+	nfapi_system_information_request_t in;
+	nfapi_system_information_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.rat_type = NFAPI_RAT_TYPE_NB_IOT;
+
+	in.nb_iot_system_information_request.tl.tag = NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG;
+	in.nb_iot_system_information_request.earfcn = 16;
+	in.nb_iot_system_information_request.ro_dl = 1;
+	in.nb_iot_system_information_request.pci = 4;
+	in.nb_iot_system_information_request.number_of_si_periodicity = 1;
+	in.nb_iot_system_information_request.si_periodicity[0].si_periodicity = 3;
+	in.nb_iot_system_information_request.si_periodicity[0].si_repetition_pattern = 0;
+	in.nb_iot_system_information_request.si_periodicity[0].si_tb_size = 0;
+	in.nb_iot_system_information_request.si_periodicity[0].number_of_si_index = 2;
+	in.nb_iot_system_information_request.si_periodicity[0].si_index[0] = 2;
+	in.nb_iot_system_information_request.si_periodicity[0].si_index[1] = 20;
+	in.nb_iot_system_information_request.si_window_length = 0;
+	in.nb_iot_system_information_request.timeout = 2000;
+
+	in.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	in.pnf_cell_broadcast_state.length = 7;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	IN_OUT_ASSERT(header.message_id);
+	IN_OUT_ASSERT(rat_type);
+	IN_OUT_ASSERT(nb_iot_system_information_request.tl.tag);
+	IN_OUT_ASSERT(nb_iot_system_information_request.earfcn);
+	IN_OUT_ASSERT(nb_iot_system_information_request.ro_dl);
+	IN_OUT_ASSERT(nb_iot_system_information_request.pci);
+	IN_OUT_ASSERT(nb_iot_system_information_request.number_of_si_periodicity);
+	
+	for(idx = 0; idx < in.nb_iot_system_information_request.number_of_si_periodicity; ++idx)
+	{
+		IN_OUT_ASSERT(nb_iot_system_information_request.si_periodicity[idx].si_periodicity);
+		IN_OUT_ASSERT(nb_iot_system_information_request.si_periodicity[idx].si_repetition_pattern);
+		IN_OUT_ASSERT(nb_iot_system_information_request.si_periodicity[idx].si_tb_size);
+		IN_OUT_ASSERT(nb_iot_system_information_request.si_periodicity[idx].number_of_si_index);
+		
+		for(idx2 = 0; idx2 < in.nb_iot_system_information_request.si_periodicity[idx].number_of_si_index; ++idx2)
+			IN_OUT_ASSERT(nb_iot_system_information_request.si_periodicity[idx].si_index[idx2]);
+	}
+
+	IN_OUT_ASSERT(nb_iot_system_information_request.si_window_length);
+	IN_OUT_ASSERT(nb_iot_system_information_request.timeout);
+
+
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.tl.tag, out.pnf_cell_broadcast_state.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.length, out.pnf_cell_broadcast_state.length);
+	for(idx = 0; idx < out.pnf_cell_broadcast_state.length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_cell_broadcast_state.value[idx], out.pnf_cell_broadcast_state.value[idx]);
+	}
+}
+
+
+void nfapi_test_system_information_response()
+{
+	nfapi_system_information_response_t in;
+	nfapi_system_information_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_system_information_indication_lte()
+{
+	uint16_t idx;
+	nfapi_system_information_indication_t in;
+	nfapi_system_information_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+	in.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.lte_system_information_indication.sib_type = 2;
+	in.lte_system_information_indication.sib_length = 15;
+
+	in.utran_system_information_indication.tl.tag = 0;
+	in.geran_system_information_indication.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.sib_type, out.lte_system_information_indication.sib_type);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.sib_length, out.lte_system_information_indication.sib_length);
+
+	for(idx = 0; idx < out.lte_system_information_indication.sib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.lte_system_information_indication.sib[idx], out.lte_system_information_indication.sib[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.utran_system_information_indication.tl.tag, out.utran_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_system_information_indication.tl.tag, out.geran_system_information_indication.tl.tag);
+
+}
+void nfapi_test_system_information_indication_lte_overrun()
+{
+	nfapi_system_information_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error code
+
+	push16(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push8(1, &p, end);
+	push16(NFAPI_MAX_SIB_LENGTH + 1, &p, end);
+
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_system_information_indication_utran()
+{
+	uint16_t idx;
+	nfapi_system_information_indication_t in;
+	nfapi_system_information_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+	in.lte_system_information_indication.tl.tag = 0;
+
+	in.utran_system_information_indication.tl.tag = NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.utran_system_information_indication.sib_length = 25;
+
+	in.geran_system_information_indication.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_system_information_indication.tl.tag, out.utran_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_system_information_indication.sib_length, out.utran_system_information_indication.sib_length);
+
+	for(idx = 0; idx < out.utran_system_information_indication.sib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.utran_system_information_indication.sib[idx], out.utran_system_information_indication.sib[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.geran_system_information_indication.tl.tag, out.geran_system_information_indication.tl.tag);
+
+}
+void nfapi_test_system_information_indication_utran_overrun()
+{
+	nfapi_system_information_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error code
+
+	push16(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_SIB_LENGTH + 1, &p, end);
+
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+void nfapi_test_system_information_indication_geran()
+{
+	uint16_t idx;
+	nfapi_system_information_indication_t in;
+	nfapi_system_information_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+	in.lte_system_information_indication.tl.tag = 0;
+	in.utran_system_information_indication.tl.tag = 0;
+
+	in.geran_system_information_indication.tl.tag = NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.geran_system_information_indication.si_length = 25;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_system_information_indication.tl.tag, out.utran_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_system_information_indication.tl.tag, out.geran_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_system_information_indication.si_length, out.geran_system_information_indication.si_length);
+
+	for(idx = 0; idx < out.geran_system_information_indication.si_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.geran_system_information_indication.si[idx], out.geran_system_information_indication.si[idx]);
+	}
+
+}
+void nfapi_test_system_information_indication_geran_overrun()
+{
+	nfapi_system_information_indication_t out;
+
+	uint8_t buffer[1024];
+	uint8_t* p = &buffer[0];
+	uint8_t *end = p + 1024;
+	push16(0, &p, end);
+	push16(NFAPI_SYSTEM_INFORMATION_INDICATION, &p, end);
+	push16(64, &p, end);
+	push16(0, &p, end);
+
+	push32(0, &p, end); // error code
+
+	push16(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &p, end);
+	push16(8, &p, end);
+
+	push16(NFAPI_MAX_SI_LENGTH + 1, &p, end);
+
+
+	int result = nfapi_p4_message_unpack(buffer, 34, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void nfapi_test_system_information_indication_nb_iot()
+{
+	uint16_t idx;
+	nfapi_system_information_indication_t in;
+	nfapi_system_information_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+	in.nb_iot_system_information_indication.tl.tag = NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG;
+	in.nb_iot_system_information_indication.sib_type = 2;
+	in.nb_iot_system_information_indication.sib_length = 15;
+
+	in.lte_system_information_indication.tl.tag = 0;
+	in.utran_system_information_indication.tl.tag = 0;
+	in.geran_system_information_indication.tl.tag = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.tl.tag, out.nb_iot_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib_type, out.nb_iot_system_information_indication.sib_type);
+	CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib_length, out.nb_iot_system_information_indication.sib_length);
+
+	for(idx = 0; idx < out.nb_iot_system_information_indication.sib_length; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nb_iot_system_information_indication.sib[idx], out.nb_iot_system_information_indication.sib[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.lte_system_information_indication.tl.tag, out.lte_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.utran_system_information_indication.tl.tag, out.utran_system_information_indication.tl.tag);
+	CU_ASSERT_EQUAL(in.geran_system_information_indication.tl.tag, out.geran_system_information_indication.tl.tag);
+
+}
+
+void nfapi_test_nmm_stop_request()
+{
+	nfapi_nmm_stop_request_t in;
+	nfapi_nmm_stop_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_NMM_STOP_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+void nfapi_test_nmm_stop_response()
+{
+	nfapi_nmm_stop_response_t in;
+	nfapi_nmm_stop_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_NMM_STOP_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_P4_MSG_RAT_NOT_SUPPORTED;
+
+	int packedMessageLength = nfapi_p4_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p4_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+
+
+void nfapi_test_pnf_param_request()
+{
+	nfapi_pnf_param_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_param_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+void nfapi_test_pnf_param_request_ve()
+{
+	nfapi_pnf_param_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_param_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	my_vendor_extention ve;
+	ve.tl.tag = NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE;
+	ve.value1 = 56;
+	ve.value2 = 1234;
+	in.vendor_extension = (void*)&ve;
+
+	nfapi_p4_p5_codec_config_t codec;
+	memset(&codec, 0, sizeof(codec));
+	codec.unpack_vendor_extension_tlv = &nfapi_test_unpack_vendor_extension_tlv; 
+	codec.pack_vendor_extension_tlv = &nfapi_test_pack_vendor_extension_tlv;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, &codec);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), &codec);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+	CU_ASSERT_NOT_EQUAL(in.vendor_extension, 0);
+	CU_ASSERT_EQUAL(((my_vendor_extention*)(out.vendor_extension))->tl.tag, ve.tl.tag);
+	CU_ASSERT_EQUAL(((my_vendor_extention*)(out.vendor_extension))->value1, ve.value1);
+	CU_ASSERT_EQUAL(((my_vendor_extention*)(out.vendor_extension))->value2, ve.value2);
+
+	free(out.vendor_extension);
+}
+void nfapi_test_pnf_param_response()
+{
+	uint16_t idx = 0;
+	uint16_t idx2 = 0;
+	nfapi_pnf_param_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_param_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = 0;
+	in.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG;
+	in.pnf_param_general.nfapi_sync_mode = 2;
+	in.pnf_param_general.location_mode = 1;
+	in.pnf_param_general.location_coordinates_length = 1;
+	in.pnf_param_general.location_coordinates[0] = 123;
+	in.pnf_param_general.dl_config_timing = 12;
+	in.pnf_param_general.tx_timing = 12;
+	in.pnf_param_general.ul_config_timing = 12;
+	in.pnf_param_general.hi_dci0_timing = 12;
+	in.pnf_param_general.maximum_number_phys = 2;
+	in.pnf_param_general.maximum_total_bandwidth = 100;
+	in.pnf_param_general.maximum_total_number_dl_layers = 2;
+	in.pnf_param_general.maximum_total_number_ul_layers = 2;
+	in.pnf_param_general.shared_bands = 0;
+	in.pnf_param_general.shared_pa = 0;
+	in.pnf_param_general.maximum_total_power = -190;
+	in.pnf_param_general.oui[0] = 88;
+
+	in.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG;
+	in.pnf_phy.number_of_phys = 2;
+	in.pnf_phy.phy[0].phy_config_index = 0;
+	in.pnf_phy.phy[0].number_of_rfs = 2;
+	in.pnf_phy.phy[0].rf_config[0].rf_config_index = 0;
+	in.pnf_phy.phy[0].number_of_rf_exclusions = 1;
+	in.pnf_phy.phy[0].rf_config[0].rf_config_index = 1;
+	in.pnf_phy.phy[0].downlink_channel_bandwidth_supported = 20;
+	in.pnf_phy.phy[0].uplink_channel_bandwidth_supported = 20;
+	in.pnf_phy.phy[0].number_of_dl_layers_supported = 2;
+	in.pnf_phy.phy[0].number_of_ul_layers_supported = 1;
+	in.pnf_phy.phy[0].maximum_3gpp_release_supported = 3;
+	in.pnf_phy.phy[0].nmm_modes_supported = 2;
+
+	in.pnf_rf.tl.tag = NFAPI_PNF_RF_TAG;
+	in.pnf_rf.number_of_rfs = 2;
+	in.pnf_rf.rf[0].rf_config_index = 0;
+	in.pnf_rf.rf[0].band = 1;
+	in.pnf_rf.rf[0].maximum_transmit_power = -100; 
+	in.pnf_rf.rf[0].minimum_transmit_power = -90; 
+	in.pnf_rf.rf[0].number_of_antennas_suppported = 4;
+	in.pnf_rf.rf[0].minimum_downlink_frequency = 100;
+	in.pnf_rf.rf[0].maximum_downlink_frequency = 2132;
+	in.pnf_rf.rf[0].minimum_uplink_frequency = 1231;
+	in.pnf_rf.rf[0].maximum_uplink_frequency = 123;
+
+
+	in.pnf_phy_rel10.tl.tag = NFAPI_PNF_PHY_REL10_TAG;
+	in.pnf_phy_rel10.number_of_phys = 2;
+	in.pnf_phy_rel10.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel10.phy[0].transmission_mode_7_supported = 1;
+	in.pnf_phy_rel10.phy[0].transmission_mode_8_supported = 2;
+	in.pnf_phy_rel10.phy[0].two_antenna_ports_for_pucch = 3;
+	in.pnf_phy_rel10.phy[0].transmission_mode_9_supported = 4;
+	in.pnf_phy_rel10.phy[0].simultaneous_pucch_pusch = 5;
+	in.pnf_phy_rel10.phy[0].four_layer_tx_with_tm3_and_tm4 = 6;
+
+	in.pnf_phy_rel11.tl.tag = NFAPI_PNF_PHY_REL11_TAG;
+	in.pnf_phy_rel11.number_of_phys = 2;
+	in.pnf_phy_rel11.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel11.phy[0].edpcch_supported = 1;
+	in.pnf_phy_rel11.phy[0].multi_ack_csi_reporting = 2;
+	in.pnf_phy_rel11.phy[0].pucch_tx_diversity = 3;
+	in.pnf_phy_rel11.phy[0].ul_comp_supported = 4;
+	in.pnf_phy_rel11.phy[0].transmission_mode_5_supported = 5;
+
+	in.pnf_phy_rel12.tl.tag = NFAPI_PNF_PHY_REL12_TAG;
+	in.pnf_phy_rel12.number_of_phys = 2;
+	in.pnf_phy_rel12.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel12.phy[0].csi_subframe_set = 1;
+	in.pnf_phy_rel12.phy[0].enhanced_4tx_codebook = 2;
+	in.pnf_phy_rel12.phy[0].drs_supported = 3;
+	in.pnf_phy_rel12.phy[0].ul_64qam_supported = 4;
+	in.pnf_phy_rel12.phy[0].transmission_mode_10_supported = 5;
+	in.pnf_phy_rel12.phy[0].alternative_bts_indices = 6;
+
+	in.pnf_phy_rel13.tl.tag = NFAPI_PNF_PHY_REL13_TAG;
+	in.pnf_phy_rel13.number_of_phys = 2;
+	in.pnf_phy_rel13.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel13.phy[0].pucch_format4_supported = 1;
+	in.pnf_phy_rel13.phy[0].pucch_format5_supported = 2;
+	in.pnf_phy_rel13.phy[0].more_than_5_ca_support = 3;
+	in.pnf_phy_rel13.phy[0].laa_supported = 4;
+	in.pnf_phy_rel13.phy[0].laa_ending_in_dwpts_supported = 5;
+	in.pnf_phy_rel13.phy[0].laa_starting_in_second_slot_supported = 6;
+	in.pnf_phy_rel13.phy[0].beamforming_supported = 7;
+	in.pnf_phy_rel13.phy[0].csi_rs_enhancement_supported = 8;
+	in.pnf_phy_rel13.phy[0].drms_enhancement_supported = 9;
+	in.pnf_phy_rel13.phy[0].srs_enhancement_supported = 10;
+	
+	in.pnf_phy_rel13_nb_iot.tl.tag = NFAPI_PNF_PHY_REL13_NB_IOT_TAG;
+	in.pnf_phy_rel13_nb_iot.number_of_phys = 2;
+	in.pnf_phy_rel13_nb_iot.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel13_nb_iot.phy[0].number_of_rfs = 2;
+	in.pnf_phy_rel13_nb_iot.phy[0].rf_config[0].rf_config_index = 0;
+	in.pnf_phy_rel13_nb_iot.phy[0].number_of_rf_exclusions = 1;
+	in.pnf_phy_rel13_nb_iot.phy[0].rf_config[0].rf_config_index = 1;
+	in.pnf_phy_rel13_nb_iot.phy[0].number_of_dl_layers_supported = 2;
+	in.pnf_phy_rel13_nb_iot.phy[0].number_of_ul_layers_supported = 1;
+	in.pnf_phy_rel13_nb_iot.phy[0].maximum_3gpp_release_supported = 3;
+	in.pnf_phy_rel13_nb_iot.phy[0].nmm_modes_supported = 2;
+
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpack_result = nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(unpack_result, 1);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.pnf_param_general.tl.tag, out.pnf_param_general.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_param_general.nfapi_sync_mode, out.pnf_param_general.nfapi_sync_mode);
+	CU_ASSERT_EQUAL(in.pnf_param_general.location_mode, out.pnf_param_general.location_mode);
+
+	for(idx = 0; idx < NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH; ++idx)
+		CU_ASSERT_EQUAL(in.pnf_param_general.location_coordinates[idx], out.pnf_param_general.location_coordinates[idx]);
+
+	CU_ASSERT_EQUAL(in.pnf_param_general.dl_config_timing, out.pnf_param_general.dl_config_timing);
+	CU_ASSERT_EQUAL(in.pnf_param_general.tx_timing, out.pnf_param_general.tx_timing);
+	CU_ASSERT_EQUAL(in.pnf_param_general.ul_config_timing, out.pnf_param_general.ul_config_timing);
+	CU_ASSERT_EQUAL(in.pnf_param_general.hi_dci0_timing, out.pnf_param_general.hi_dci0_timing);
+	CU_ASSERT_EQUAL(in.pnf_param_general.maximum_number_phys, out.pnf_param_general.maximum_number_phys);
+	CU_ASSERT_EQUAL(in.pnf_param_general.maximum_total_bandwidth, out.pnf_param_general.maximum_total_bandwidth);
+	CU_ASSERT_EQUAL(in.pnf_param_general.maximum_total_number_dl_layers, out.pnf_param_general.maximum_total_number_dl_layers);
+	CU_ASSERT_EQUAL(in.pnf_param_general.maximum_total_number_ul_layers, out.pnf_param_general.maximum_total_number_ul_layers);
+	CU_ASSERT_EQUAL(in.pnf_param_general.shared_bands, out.pnf_param_general.shared_bands);
+	CU_ASSERT_EQUAL(in.pnf_param_general.shared_pa, out.pnf_param_general.shared_pa);
+	CU_ASSERT_EQUAL(in.pnf_param_general.maximum_total_power, out.pnf_param_general.maximum_total_power);
+	for(idx = 0; idx < NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH; ++idx)
+		CU_ASSERT_EQUAL(in.pnf_param_general.oui[idx], out.pnf_param_general.oui[idx]);
+
+	CU_ASSERT_EQUAL(in.pnf_phy.tl.tag, out.pnf_phy.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy.number_of_phys, out.pnf_phy.number_of_phys);
+	
+	for(idx = 0; idx < out.pnf_phy.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].phy_config_index, out.pnf_phy.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].number_of_rfs, out.pnf_phy.phy[idx].number_of_rfs);
+
+	
+		for(idx2 = 0; idx2 < out.pnf_phy.phy[idx].number_of_rfs; ++idx2)
+		{
+			CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].rf_config[idx2].rf_config_index, out.pnf_phy.phy[idx].rf_config[idx2].rf_config_index);
+		}
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].number_of_rf_exclusions, out.pnf_phy.phy[idx].number_of_rf_exclusions);
+
+		for(idx2 = 0; idx2 < out.pnf_phy.phy[idx].number_of_rf_exclusions; ++idx2)
+		{
+			CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].excluded_rf_config[idx2].rf_config_index, out.pnf_phy.phy[idx].excluded_rf_config[idx2].rf_config_index);
+		}
+
+
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].downlink_channel_bandwidth_supported, out.pnf_phy.phy[idx].downlink_channel_bandwidth_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].uplink_channel_bandwidth_supported, out.pnf_phy.phy[idx].uplink_channel_bandwidth_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].number_of_dl_layers_supported, out.pnf_phy.phy[idx].number_of_dl_layers_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].number_of_ul_layers_supported, out.pnf_phy.phy[idx].number_of_ul_layers_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].maximum_3gpp_release_supported, out.pnf_phy.phy[idx].maximum_3gpp_release_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy.phy[idx].nmm_modes_supported, out.pnf_phy.phy[idx].nmm_modes_supported);
+	}
+
+	CU_ASSERT_EQUAL(in.pnf_rf.tl.tag, out.pnf_rf.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_rf.number_of_rfs, out.pnf_rf.number_of_rfs);
+	for(idx = 0; idx < out.pnf_rf.number_of_rfs; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].rf_config_index, out.pnf_rf.rf[idx].rf_config_index);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].band, out.pnf_rf.rf[idx].band);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].maximum_transmit_power, out.pnf_rf.rf[idx].maximum_transmit_power);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].minimum_transmit_power, out.pnf_rf.rf[idx].minimum_transmit_power);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].number_of_antennas_suppported, out.pnf_rf.rf[idx].number_of_antennas_suppported);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].minimum_downlink_frequency, out.pnf_rf.rf[idx].minimum_downlink_frequency);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].maximum_downlink_frequency, out.pnf_rf.rf[idx].maximum_downlink_frequency);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].minimum_uplink_frequency, out.pnf_rf.rf[idx].minimum_uplink_frequency);
+		CU_ASSERT_EQUAL(in.pnf_rf.rf[idx].maximum_uplink_frequency, out.pnf_rf.rf[idx].maximum_uplink_frequency);
+	}
+
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rel10.tl.tag, out.pnf_phy_rel10.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rel10.number_of_phys, out.pnf_phy_rel10.number_of_phys);
+	for(idx = 0; idx < out.pnf_phy_rel10.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].phy_config_index, out.pnf_phy_rel10.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].transmission_mode_7_supported, out.pnf_phy_rel10.phy[idx].transmission_mode_7_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].transmission_mode_8_supported, out.pnf_phy_rel10.phy[idx].transmission_mode_8_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].two_antenna_ports_for_pucch, out.pnf_phy_rel10.phy[idx].two_antenna_ports_for_pucch);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].transmission_mode_9_supported, out.pnf_phy_rel10.phy[idx].transmission_mode_9_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].simultaneous_pucch_pusch, out.pnf_phy_rel10.phy[idx].simultaneous_pucch_pusch);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel10.phy[idx].four_layer_tx_with_tm3_and_tm4, out.pnf_phy_rel10.phy[idx].four_layer_tx_with_tm3_and_tm4);
+	}
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rel11.tl.tag, out.pnf_phy_rel11.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rel11.number_of_phys, out.pnf_phy_rel11.number_of_phys);
+	for(idx = 0; idx < out.pnf_phy_rel11.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].phy_config_index, out.pnf_phy_rel11.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].edpcch_supported, out.pnf_phy_rel11.phy[idx].edpcch_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].multi_ack_csi_reporting, out.pnf_phy_rel11.phy[idx].multi_ack_csi_reporting);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].pucch_tx_diversity, out.pnf_phy_rel11.phy[idx].pucch_tx_diversity);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].ul_comp_supported, out.pnf_phy_rel11.phy[idx].ul_comp_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel11.phy[idx].transmission_mode_5_supported, out.pnf_phy_rel11.phy[idx].transmission_mode_5_supported);
+	}
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rel12.tl.tag, out.pnf_phy_rel12.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rel12.number_of_phys, out.pnf_phy_rel12.number_of_phys);
+	for(idx = 0; idx < out.pnf_phy_rel12.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].phy_config_index, out.pnf_phy_rel12.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].csi_subframe_set, out.pnf_phy_rel12.phy[idx].csi_subframe_set);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].enhanced_4tx_codebook, out.pnf_phy_rel12.phy[idx].enhanced_4tx_codebook);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].drs_supported, out.pnf_phy_rel12.phy[idx].drs_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].ul_64qam_supported, out.pnf_phy_rel12.phy[idx].ul_64qam_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].transmission_mode_10_supported, out.pnf_phy_rel12.phy[idx].transmission_mode_10_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel12.phy[idx].alternative_bts_indices, out.pnf_phy_rel12.phy[idx].alternative_bts_indices);
+	}
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rel13.tl.tag, out.pnf_phy_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rel13.number_of_phys, out.pnf_phy_rel13.number_of_phys);
+	for(idx = 0; idx < out.pnf_phy_rel13.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].phy_config_index, out.pnf_phy_rel13.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].pucch_format4_supported, out.pnf_phy_rel13.phy[idx].pucch_format4_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].pucch_format5_supported, out.pnf_phy_rel13.phy[idx].pucch_format5_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].more_than_5_ca_support, out.pnf_phy_rel13.phy[idx].more_than_5_ca_support);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].laa_supported, out.pnf_phy_rel13.phy[idx].laa_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].laa_ending_in_dwpts_supported, out.pnf_phy_rel13.phy[idx].laa_ending_in_dwpts_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].laa_starting_in_second_slot_supported, out.pnf_phy_rel13.phy[idx].laa_starting_in_second_slot_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].beamforming_supported, out.pnf_phy_rel13.phy[idx].beamforming_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].csi_rs_enhancement_supported, out.pnf_phy_rel13.phy[idx].csi_rs_enhancement_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].drms_enhancement_supported, out.pnf_phy_rel13.phy[idx].drms_enhancement_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13.phy[idx].srs_enhancement_supported, out.pnf_phy_rel13.phy[idx].srs_enhancement_supported);
+	}
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.tl.tag, out.pnf_phy_rel13_nb_iot.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.number_of_phys, out.pnf_phy_rel13_nb_iot.number_of_phys);
+	
+	for(idx = 0; idx < out.pnf_phy_rel13_nb_iot.number_of_phys; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].phy_config_index, out.pnf_phy_rel13_nb_iot.phy[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].number_of_rfs, out.pnf_phy_rel13_nb_iot.phy[idx].number_of_rfs);
+
+	
+		for(idx2 = 0; idx2 < out.pnf_phy_rel13_nb_iot.phy[idx].number_of_rfs; ++idx2)
+		{
+			CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].rf_config[idx2].rf_config_index, out.pnf_phy_rel13_nb_iot.phy[idx].rf_config[idx2].rf_config_index);
+		}
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].number_of_rf_exclusions, out.pnf_phy_rel13_nb_iot.phy[idx].number_of_rf_exclusions);
+
+		for(idx2 = 0; idx2 < out.pnf_phy_rel13_nb_iot.phy[idx].number_of_rf_exclusions; ++idx2)
+		{
+			CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].excluded_rf_config[idx2].rf_config_index, out.pnf_phy_rel13_nb_iot.phy[idx].excluded_rf_config[idx2].rf_config_index);
+		}
+
+
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].number_of_dl_layers_supported, out.pnf_phy_rel13_nb_iot.phy[idx].number_of_dl_layers_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].number_of_ul_layers_supported, out.pnf_phy_rel13_nb_iot.phy[idx].number_of_ul_layers_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].maximum_3gpp_release_supported, out.pnf_phy_rel13_nb_iot.phy[idx].maximum_3gpp_release_supported);
+		CU_ASSERT_EQUAL(in.pnf_phy_rel13_nb_iot.phy[idx].nmm_modes_supported, out.pnf_phy_rel13_nb_iot.phy[idx].nmm_modes_supported);
+	}
+
+
+}
+
+void nfapi_test_pnf_config_request()
+{
+	uint16_t idx;
+	nfapi_pnf_config_request_t in;
+	nfapi_pnf_config_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
+	in.pnf_phy_rf_config.number_phy_rf_config_info = 2;
+	in.pnf_phy_rf_config.phy_rf_config[0].phy_id = 0;
+	in.pnf_phy_rf_config.phy_rf_config[0].phy_config_index = 0;
+	in.pnf_phy_rf_config.phy_rf_config[0].rf_config_index = 0;
+
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpack_result = nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(unpack_result, 1);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	//CU_ASSERT_EQUAL(in.error_code, out.error_code);
+
+	CU_ASSERT_EQUAL(in.pnf_phy_rf_config.tl.tag, out.pnf_phy_rf_config.tl.tag);
+	CU_ASSERT_EQUAL(in.pnf_phy_rf_config.number_phy_rf_config_info, out.pnf_phy_rf_config.number_phy_rf_config_info);
+
+	for(idx = 0; idx < out.pnf_phy_rf_config.number_phy_rf_config_info; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.pnf_phy_rf_config.phy_rf_config[idx].phy_id, out.pnf_phy_rf_config.phy_rf_config[idx].phy_id);
+		CU_ASSERT_EQUAL(in.pnf_phy_rf_config.phy_rf_config[idx].phy_config_index, out.pnf_phy_rf_config.phy_rf_config[idx].phy_config_index);
+		CU_ASSERT_EQUAL(in.pnf_phy_rf_config.phy_rf_config[idx].rf_config_index, out.pnf_phy_rf_config.phy_rf_config[idx].rf_config_index);
+	}
+}
+
+
+
+void nfapi_test_pnf_config_response()
+{
+	nfapi_pnf_config_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_config_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_pnf_config_response1()
+{
+	uint8_t buffer[NFAPI_HEADER_LENGTH  + 1];
+
+	nfapi_pnf_config_response_t in;
+	memset(&in, 0, sizeof(in));
+	//nfapi_pnf_config_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), buffer, sizeof(buffer), 0);
+	CU_ASSERT_EQUAL(packedMessageLength, -1);
+
+	//nfapi_p5_message_unpack(buffer, sizeof(buffer), &out, sizeof(out), 0);
+	//CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	//CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_pnf_start_request()
+{
+	nfapi_pnf_start_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_start_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_START_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+
+void nfapi_test_pnf_start_response()
+{
+	nfapi_pnf_start_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_start_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_START_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_pnf_stop_request()
+{
+	nfapi_pnf_stop_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_stop_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_STOP_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+void nfapi_test_pnf_stop_response()
+{
+	nfapi_pnf_stop_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_pnf_stop_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PNF_STOP_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+
+void nfapi_test_param_request()
+{
+	nfapi_param_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_param_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PARAM_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+void nfapi_test_param_response()
+{
+	#define SET_TLV(_TLV, _TAG, _VALUE) { _TLV.tl.tag = _TAG; _TLV.value = _VALUE; num_tlv++;	}
+	#define ASSERT_TLV(IN_TLV, OUT_TLV) { CU_ASSERT_EQUAL(IN_TLV.tl.tag, OUT_TLV.tl.tag); CU_ASSERT_EQUAL(IN_TLV.value, OUT_TLV.value);}
+
+	nfapi_param_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_param_response_t out;
+	memset(&out, 0, sizeof(out));
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_PARAM_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	uint16_t idx = 0;
+	uint16_t num_tlv = 0; // Bit of a hack, it is incremented in the SET_UINT16_TLV macro
+
+	SET_TLV(in.l1_status.phy_state, NFAPI_L1_STATUS_PHY_STATE_TAG, 1);
+	SET_TLV(in.phy_capabilities.dl_bandwidth_support, NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, 63);
+	SET_TLV(in.phy_capabilities.ul_bandwidth_support, NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, 63);
+	SET_TLV(in.phy_capabilities.dl_modulation_support, NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, 3);
+	SET_TLV(in.phy_capabilities.ul_modulation_support, NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, 3);
+	SET_TLV(in.phy_capabilities.phy_antenna_capability, NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, 8);
+	SET_TLV(in.phy_capabilities.release_capability, NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, 63);
+	SET_TLV(in.phy_capabilities.mbsfn_capability, NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, 0);
+	
+	SET_TLV(in.laa_capability.laa_support, NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, 1);
+	SET_TLV(in.laa_capability.pd_sensing_lbt_support, NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, 0);
+	SET_TLV(in.laa_capability.multi_carrier_lbt_support, NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, 3);
+	SET_TLV(in.laa_capability.partial_sf_support, NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, 2);
+
+	SET_TLV(in.subframe_config.duplex_mode, NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, 1);
+	SET_TLV(in.subframe_config.pcfich_power_offset, NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, 1000);
+	SET_TLV(in.subframe_config.pb, NFAPI_SUBFRAME_CONFIG_PB_TAG, 1);
+	SET_TLV(in.subframe_config.dl_cyclic_prefix_type, NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, 0);
+	SET_TLV(in.subframe_config.ul_cyclic_prefix_type, NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, 0);
+
+	SET_TLV(in.rf_config.dl_channel_bandwidth, NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, 50);
+	SET_TLV(in.rf_config.ul_channel_bandwidth, NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, 50);
+	SET_TLV(in.rf_config.reference_signal_power, NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, 120);
+	SET_TLV(in.rf_config.tx_antenna_ports, NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, 2);
+	SET_TLV(in.rf_config.rx_antenna_ports, NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, 2);
+
+	SET_TLV(in.phich_config.phich_resource, NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, 3);
+	SET_TLV(in.phich_config.phich_duration, NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, 0);
+	SET_TLV(in.phich_config.phich_power_offset, NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, 500);
+
+	SET_TLV(in.sch_config.primary_synchronization_signal_epre_eprers, NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, 1000);
+	SET_TLV(in.sch_config.secondary_synchronization_signal_epre_eprers, NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, 2000);
+	SET_TLV(in.sch_config.physical_cell_id, NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, 12344);
+
+
+	SET_TLV(in.prach_config.configuration_index, NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, 63);
+	SET_TLV(in.prach_config.root_sequence_index, NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, 800);
+	SET_TLV(in.prach_config.zero_correlation_zone_configuration, NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, 14);
+	SET_TLV(in.prach_config.high_speed_flag, NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, 0);
+	SET_TLV(in.prach_config.frequency_offset, NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, 23);
+
+	SET_TLV(in.pusch_config.hopping_mode, NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, 0);
+	SET_TLV(in.pusch_config.hopping_offset, NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, 55);
+	SET_TLV(in.pusch_config.number_of_subbands, NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, 1);
+
+	SET_TLV(in.pucch_config.delta_pucch_shift, NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, 2);
+	SET_TLV(in.pucch_config.n_cqi_rb, NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, 88);
+	SET_TLV(in.pucch_config.n_an_cs, NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, 3);
+	SET_TLV(in.pucch_config.n1_pucch_an, NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, 2015);
+
+	SET_TLV(in.srs_config.bandwidth_configuration, NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, 3);
+	SET_TLV(in.srs_config.max_up_pts, NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, 0);
+	SET_TLV(in.srs_config.srs_subframe_configuration, NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, 11);
+	SET_TLV(in.srs_config.srs_acknack_srs_simultaneous_transmission, NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, 1);
+
+	SET_TLV(in.uplink_reference_signal_config.uplink_rs_hopping, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, 2);
+	SET_TLV(in.uplink_reference_signal_config.group_assignment, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, 22);
+	SET_TLV(in.uplink_reference_signal_config.cyclic_shift_1_for_drms, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, 2);
+
+	SET_TLV(in.tdd_frame_structure_config.subframe_assignment, NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, 5);
+	SET_TLV(in.tdd_frame_structure_config.special_subframe_patterns, NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, 3);
+
+	SET_TLV(in.l23_config.data_report_mode, NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, 1);
+	SET_TLV(in.l23_config.sfnsf, NFAPI_L23_CONFIG_SFNSF_TAG, 12354);
+
+	in.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+	num_tlv++;
+
+	in.nfapi_config.p7_vnf_address_ipv6.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.p7_vnf_port, NFAPI_NFAPI_P7_VNF_PORT_TAG, 1111);
+	
+	in.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
+	num_tlv++;
+
+	in.nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.p7_pnf_port, NFAPI_NFAPI_P7_PNF_PORT_TAG, 9999);
+	SET_TLV(in.nfapi_config.dl_ue_per_sf, NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, 4);
+	SET_TLV(in.nfapi_config.ul_ue_per_sf, NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, 4);
+
+	in.nfapi_config.rf_bands.tl.tag = NFAPI_PHY_RF_BANDS_TAG;
+	in.nfapi_config.rf_bands.number_rf_bands = 2;
+	in.nfapi_config.rf_bands.rf_band[0] = 783;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.timing_window, NFAPI_NFAPI_TIMING_WINDOW_TAG, 29);
+	SET_TLV(in.nfapi_config.timing_info_mode, NFAPI_NFAPI_TIMING_INFO_MODE_TAG, 2);
+	SET_TLV(in.nfapi_config.timing_info_period, NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, 23);
+	SET_TLV(in.nfapi_config.max_transmit_power, NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, 123);
+	SET_TLV(in.nfapi_config.earfcn, NFAPI_NFAPI_EARFCN_TAG, 1800);
+
+	in.nfapi_config.nmm_gsm_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands = 2;
+	num_tlv++;
+
+	in.nfapi_config.nmm_umts_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands = 3;
+	num_tlv++;
+
+	in.nfapi_config.nmm_lte_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands = 1;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.nmm_uplink_rssi_supported, NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, 1);
+
+
+	in.num_tlv = num_tlv;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+	CU_ASSERT_EQUAL(in.num_tlv, out.num_tlv);
+
+	ASSERT_TLV(in.l1_status.phy_state, out.l1_status.phy_state);
+	ASSERT_TLV(in.phy_capabilities.dl_bandwidth_support, out.phy_capabilities.dl_bandwidth_support);
+	ASSERT_TLV(in.phy_capabilities.ul_bandwidth_support, out.phy_capabilities.ul_bandwidth_support);
+	ASSERT_TLV(in.phy_capabilities.dl_modulation_support, out.phy_capabilities.dl_modulation_support);
+	ASSERT_TLV(in.phy_capabilities.ul_modulation_support, out.phy_capabilities.ul_modulation_support);
+	ASSERT_TLV(in.phy_capabilities.phy_antenna_capability, out.phy_capabilities.phy_antenna_capability);
+	ASSERT_TLV(in.phy_capabilities.release_capability, out.phy_capabilities.release_capability);
+	ASSERT_TLV(in.phy_capabilities.mbsfn_capability, out.phy_capabilities.mbsfn_capability);
+
+	ASSERT_TLV(in.laa_capability.laa_support, in.laa_capability.laa_support);
+	ASSERT_TLV(in.laa_capability.pd_sensing_lbt_support, in.laa_capability.pd_sensing_lbt_support);
+	ASSERT_TLV(in.laa_capability.multi_carrier_lbt_support, in.laa_capability.multi_carrier_lbt_support);
+	ASSERT_TLV(in.laa_capability.partial_sf_support, in.laa_capability.partial_sf_support);
+
+	ASSERT_TLV(in.subframe_config.duplex_mode, out.subframe_config.duplex_mode);
+	ASSERT_TLV(in.subframe_config.pcfich_power_offset, out.subframe_config.pcfich_power_offset);
+	ASSERT_TLV(in.subframe_config.pb, out.subframe_config.pb);
+	ASSERT_TLV(in.subframe_config.dl_cyclic_prefix_type, out.subframe_config.dl_cyclic_prefix_type);
+	ASSERT_TLV(in.subframe_config.ul_cyclic_prefix_type, out.subframe_config.ul_cyclic_prefix_type);
+
+	ASSERT_TLV(in.rf_config.dl_channel_bandwidth, out.rf_config.dl_channel_bandwidth);
+	ASSERT_TLV(in.rf_config.ul_channel_bandwidth, out.rf_config.ul_channel_bandwidth);
+	ASSERT_TLV(in.rf_config.reference_signal_power, out.rf_config.reference_signal_power);
+	ASSERT_TLV(in.rf_config.tx_antenna_ports, out.rf_config.tx_antenna_ports);
+	ASSERT_TLV(in.rf_config.rx_antenna_ports, out.rf_config.rx_antenna_ports);
+
+	ASSERT_TLV(in.phich_config.phich_resource, out.phich_config.phich_resource);
+	ASSERT_TLV(in.phich_config.phich_duration, out.phich_config.phich_duration);
+	ASSERT_TLV(in.phich_config.phich_power_offset, out.phich_config.phich_power_offset);
+
+	ASSERT_TLV(in.sch_config.primary_synchronization_signal_epre_eprers, out.sch_config.primary_synchronization_signal_epre_eprers);
+	ASSERT_TLV(in.sch_config.secondary_synchronization_signal_epre_eprers, out.sch_config.secondary_synchronization_signal_epre_eprers);
+	ASSERT_TLV(in.sch_config.physical_cell_id, out.sch_config.physical_cell_id);
+
+
+	ASSERT_TLV(in.prach_config.configuration_index, out.prach_config.configuration_index);
+	ASSERT_TLV(in.prach_config.root_sequence_index, out.prach_config.root_sequence_index);
+	ASSERT_TLV(in.prach_config.zero_correlation_zone_configuration, out.prach_config.zero_correlation_zone_configuration);
+	ASSERT_TLV(in.prach_config.high_speed_flag, out.prach_config.high_speed_flag);
+	ASSERT_TLV(in.prach_config.frequency_offset, out.prach_config.frequency_offset);
+	
+	ASSERT_TLV(in.pusch_config.hopping_mode, in.pusch_config.hopping_mode);
+	ASSERT_TLV(in.pusch_config.hopping_offset, in.pusch_config.hopping_offset);
+	ASSERT_TLV(in.pusch_config.number_of_subbands, in.pusch_config.number_of_subbands);
+
+	ASSERT_TLV(in.pucch_config.delta_pucch_shift, out.pucch_config.delta_pucch_shift);
+	ASSERT_TLV(in.pucch_config.n_cqi_rb, out.pucch_config.n_cqi_rb);
+	ASSERT_TLV(in.pucch_config.n_an_cs, out.pucch_config.n_an_cs);
+	ASSERT_TLV(in.pucch_config.n1_pucch_an, out.pucch_config.n1_pucch_an);
+
+	ASSERT_TLV(in.srs_config.bandwidth_configuration, out.srs_config.bandwidth_configuration);
+	ASSERT_TLV(in.srs_config.max_up_pts, out.srs_config.max_up_pts);
+	ASSERT_TLV(in.srs_config.srs_subframe_configuration, out.srs_config.srs_subframe_configuration);
+	ASSERT_TLV(in.srs_config.srs_acknack_srs_simultaneous_transmission, out.srs_config.srs_acknack_srs_simultaneous_transmission);
+
+	ASSERT_TLV(in.uplink_reference_signal_config.uplink_rs_hopping, out.uplink_reference_signal_config.uplink_rs_hopping);
+	ASSERT_TLV(in.uplink_reference_signal_config.group_assignment, out.uplink_reference_signal_config.group_assignment);
+	ASSERT_TLV(in.uplink_reference_signal_config.cyclic_shift_1_for_drms, out.uplink_reference_signal_config.cyclic_shift_1_for_drms);
+
+	ASSERT_TLV(in.tdd_frame_structure_config.subframe_assignment, out.tdd_frame_structure_config.subframe_assignment);
+	ASSERT_TLV(in.tdd_frame_structure_config.special_subframe_patterns, out.tdd_frame_structure_config.special_subframe_patterns);
+
+	ASSERT_TLV(in.l23_config.data_report_mode, out.l23_config.data_report_mode);
+	ASSERT_TLV(in.l23_config.sfnsf, out.l23_config.sfnsf);
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv4.tl.tag, out.nfapi_config.p7_vnf_address_ipv4.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV4_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv4.address[idx], out.nfapi_config.p7_vnf_address_ipv4.address[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv6.tl.tag, out.nfapi_config.p7_vnf_address_ipv6.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV6_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv6.address[idx], out.nfapi_config.p7_vnf_address_ipv6.address[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.p7_vnf_port, out.nfapi_config.p7_vnf_port);
+	
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv4.tl.tag, out.nfapi_config.p7_pnf_address_ipv4.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV4_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv4.address[idx], out.nfapi_config.p7_pnf_address_ipv4.address[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv6.tl.tag, out.nfapi_config.p7_pnf_address_ipv6.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV6_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv6.address[idx], out.nfapi_config.p7_pnf_address_ipv6.address[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.p7_pnf_port, out.nfapi_config.p7_pnf_port);
+	ASSERT_TLV(in.nfapi_config.dl_ue_per_sf, out.nfapi_config.dl_ue_per_sf);
+	ASSERT_TLV(in.nfapi_config.ul_ue_per_sf, out.nfapi_config.ul_ue_per_sf);
+
+	CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.tl.tag, out.nfapi_config.rf_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.number_rf_bands, out.nfapi_config.rf_bands.number_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.rf_bands.number_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.rf_band[idx], out.nfapi_config.rf_bands.rf_band[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.timing_window, out.nfapi_config.timing_window);
+	ASSERT_TLV(in.nfapi_config.timing_info_mode, out.nfapi_config.timing_info_mode);
+	ASSERT_TLV(in.nfapi_config.timing_info_period, out.nfapi_config.timing_info_period);
+	ASSERT_TLV(in.nfapi_config.max_transmit_power, out.nfapi_config.max_transmit_power);
+	ASSERT_TLV(in.nfapi_config.earfcn, out.nfapi_config.earfcn); 
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.tl.tag, out.nfapi_config.nmm_gsm_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.bands[idx], out.nfapi_config.nmm_gsm_frequency_bands.bands[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.tl.tag, out.nfapi_config.nmm_umts_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.bands[idx], out.nfapi_config.nmm_umts_frequency_bands.bands[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.tl.tag, out.nfapi_config.nmm_lte_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.bands[idx], out.nfapi_config.nmm_lte_frequency_bands.bands[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.nmm_uplink_rssi_supported, out.nfapi_config.nmm_uplink_rssi_supported); 
+}
+void nfapi_test_config_request()
+{
+	#define SET_TLV(_TLV, _TAG, _VALUE) { _TLV.tl.tag = _TAG; _TLV.value = _VALUE; num_tlv++;	}
+	#define ASSERT_TLV(IN_TLV, OUT_TLV) { CU_ASSERT_EQUAL(IN_TLV.tl.tag, OUT_TLV.tl.tag); CU_ASSERT_EQUAL(IN_TLV.value, OUT_TLV.value);}
+
+	nfapi_config_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_config_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CONFIG_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+
+	uint16_t idx = 0;
+	uint16_t num_tlv = 0; // Bit of a hack, it is incremented in the SET_UINT16_TLV macro
+
+	SET_TLV(in.subframe_config.duplex_mode, NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, 1);
+	SET_TLV(in.subframe_config.pcfich_power_offset, NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, 1000);
+	SET_TLV(in.subframe_config.pb, NFAPI_SUBFRAME_CONFIG_PB_TAG, 1);
+	SET_TLV(in.subframe_config.dl_cyclic_prefix_type, NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, 0);
+	SET_TLV(in.subframe_config.ul_cyclic_prefix_type, NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, 0);
+
+	SET_TLV(in.rf_config.dl_channel_bandwidth, NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, 50);
+	SET_TLV(in.rf_config.ul_channel_bandwidth, NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, 50);
+	SET_TLV(in.rf_config.reference_signal_power, NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, 120);
+	SET_TLV(in.rf_config.tx_antenna_ports, NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, 2);
+	SET_TLV(in.rf_config.rx_antenna_ports, NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, 2);
+
+	SET_TLV(in.phich_config.phich_resource, NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, 3);
+	SET_TLV(in.phich_config.phich_duration, NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, 0);
+	SET_TLV(in.phich_config.phich_power_offset, NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, 500);
+
+	SET_TLV(in.sch_config.primary_synchronization_signal_epre_eprers, NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, 1000);
+	SET_TLV(in.sch_config.secondary_synchronization_signal_epre_eprers, NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, 2000);
+	SET_TLV(in.sch_config.physical_cell_id, NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, 12344);
+
+
+	SET_TLV(in.prach_config.configuration_index, NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, 63);
+	SET_TLV(in.prach_config.root_sequence_index, NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, 800);
+	SET_TLV(in.prach_config.zero_correlation_zone_configuration, NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, 14);
+	SET_TLV(in.prach_config.high_speed_flag, NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, 0);
+	SET_TLV(in.prach_config.frequency_offset, NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, 23);
+
+	SET_TLV(in.pusch_config.hopping_mode, NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, 0);
+	SET_TLV(in.pusch_config.hopping_offset, NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, 55);
+	SET_TLV(in.pusch_config.number_of_subbands, NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, 1);
+
+	SET_TLV(in.pucch_config.delta_pucch_shift, NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, 2);
+	SET_TLV(in.pucch_config.n_cqi_rb, NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, 88);
+	SET_TLV(in.pucch_config.n_an_cs, NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, 3);
+	SET_TLV(in.pucch_config.n1_pucch_an, NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, 2015);
+
+	SET_TLV(in.srs_config.bandwidth_configuration, NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, 3);
+	SET_TLV(in.srs_config.max_up_pts, NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, 0);
+	SET_TLV(in.srs_config.srs_subframe_configuration, NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, 11);
+	SET_TLV(in.srs_config.srs_acknack_srs_simultaneous_transmission, NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, 1);
+
+	SET_TLV(in.uplink_reference_signal_config.uplink_rs_hopping, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, 2);
+	SET_TLV(in.uplink_reference_signal_config.group_assignment, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, 22);
+	SET_TLV(in.uplink_reference_signal_config.cyclic_shift_1_for_drms, NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, 2);
+
+
+	// laa config
+	SET_TLV(in.laa_config.ed_threshold_lbt_pdsch, NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, 45);
+	SET_TLV(in.laa_config.ed_threshold_lbt_drs, NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, 69);
+	SET_TLV(in.laa_config.pd_threshold, NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, 65535);
+	SET_TLV(in.laa_config.multi_carrier_type, NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, 3);
+	SET_TLV(in.laa_config.multi_carrier_tx, NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, 1);
+	SET_TLV(in.laa_config.multi_carrier_freeze, NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, 0);
+	SET_TLV(in.laa_config.tx_antenna_ports_drs, NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, 4);
+	SET_TLV(in.laa_config.tx_power_drs, NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, 10000);
+	//
+	// emtc config
+	SET_TLV(in.emtc_config.pbch_repetitions_enable_r13, NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, 1);
+	SET_TLV(in.emtc_config.prach_catm_root_sequence_index, NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, 837); 
+	SET_TLV(in.emtc_config.prach_catm_zero_correlation_zone_configuration, NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, 15); 
+	SET_TLV(in.emtc_config.prach_catm_high_speed_flag, NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, 15); 
+	SET_TLV(in.emtc_config.prach_ce_level_0_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, 1); 
+	SET_TLV(in.emtc_config.prach_ce_level_0_configuration_index, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, 60);
+	SET_TLV(in.emtc_config.prach_ce_level_0_frequency_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, 90);
+	SET_TLV(in.emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, 128);
+	SET_TLV(in.emtc_config.prach_ce_level_0_starting_subframe_periodicity, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, 256);
+	SET_TLV(in.emtc_config.prach_ce_level_0_hopping_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, 1);
+	SET_TLV(in.emtc_config.prach_ce_level_0_hopping_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, 0);
+	SET_TLV(in.emtc_config.prach_ce_level_1_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, 1);
+	SET_TLV(in.emtc_config.prach_ce_level_1_configuration_index, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, 45);
+	SET_TLV(in.emtc_config.prach_ce_level_1_frequency_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, 88);
+	SET_TLV(in.emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, 64);
+	SET_TLV(in.emtc_config.prach_ce_level_1_starting_subframe_periodicity, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, 0xFFFF);
+	SET_TLV(in.emtc_config.prach_ce_level_1_hopping_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, 1);
+	SET_TLV(in.emtc_config.prach_ce_level_1_hopping_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, 22);
+	SET_TLV(in.emtc_config.prach_ce_level_2_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, 1);
+	SET_TLV(in.emtc_config.prach_ce_level_2_configuration_index, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, 63);
+	SET_TLV(in.emtc_config.prach_ce_level_2_frequency_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, 22);
+	SET_TLV(in.emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, 8);
+	SET_TLV(in.emtc_config.prach_ce_level_2_starting_subframe_periodicity, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, 64)
+	SET_TLV(in.emtc_config.prach_ce_level_2_hopping_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, 1);
+	SET_TLV(in.emtc_config.prach_ce_level_2_hopping_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, 45);
+	SET_TLV(in.emtc_config.prach_ce_level_3_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, 0);
+	SET_TLV(in.emtc_config.prach_ce_level_3_configuration_index, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, 45);
+	SET_TLV(in.emtc_config.prach_ce_level_3_frequency_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, 22);
+	SET_TLV(in.emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, 4); 
+	SET_TLV(in.emtc_config.prach_ce_level_3_starting_subframe_periodicity, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, 4);
+	SET_TLV(in.emtc_config.prach_ce_level_3_hopping_enable, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, 0); 
+	SET_TLV(in.emtc_config.prach_ce_level_3_hopping_offset, NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, 0);
+	SET_TLV(in.emtc_config.pucch_interval_ulhoppingconfigcommonmodea, NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, 8);
+	SET_TLV(in.emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, 8);
+
+
+	SET_TLV(in.tdd_frame_structure_config.subframe_assignment, NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, 5);
+	SET_TLV(in.tdd_frame_structure_config.special_subframe_patterns, NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, 3);
+
+	SET_TLV(in.l23_config.data_report_mode, NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, 1);
+	SET_TLV(in.l23_config.sfnsf, NFAPI_L23_CONFIG_SFNSF_TAG, 12354);
+
+	in.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+	num_tlv++;
+
+	in.nfapi_config.p7_vnf_address_ipv6.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.p7_vnf_port, NFAPI_NFAPI_P7_VNF_PORT_TAG, 1111);
+	
+	in.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
+	num_tlv++;
+
+	in.nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG;
+	for(idx = 0; idx < NFAPI_IPV6_ADDRESS_LENGTH; ++idx)
+	{
+		in.nfapi_config.p7_pnf_address_ipv6.address[idx] = idx;
+	}
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.p7_pnf_port, NFAPI_NFAPI_P7_PNF_PORT_TAG, 9999);
+	SET_TLV(in.nfapi_config.dl_ue_per_sf, NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, 4);
+	SET_TLV(in.nfapi_config.ul_ue_per_sf, NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, 4);
+
+	in.nfapi_config.rf_bands.tl.tag = NFAPI_PHY_RF_BANDS_TAG;
+	in.nfapi_config.rf_bands.number_rf_bands = 2;
+	in.nfapi_config.rf_bands.rf_band[0] = 783;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.timing_window, NFAPI_NFAPI_TIMING_WINDOW_TAG, 29);
+	SET_TLV(in.nfapi_config.timing_info_mode, NFAPI_NFAPI_TIMING_INFO_MODE_TAG, 2);
+	SET_TLV(in.nfapi_config.timing_info_period, NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, 23);
+	SET_TLV(in.nfapi_config.max_transmit_power, NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, 123);
+	SET_TLV(in.nfapi_config.earfcn, NFAPI_NFAPI_EARFCN_TAG, 1800);
+
+	in.nfapi_config.nmm_gsm_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands = 2;
+	num_tlv++;
+
+	in.nfapi_config.nmm_umts_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands = 3;
+	num_tlv++;
+
+	in.nfapi_config.nmm_lte_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG;
+	in.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands = 1;
+	num_tlv++;
+
+	SET_TLV(in.nfapi_config.nmm_uplink_rssi_supported, NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, 1);
+
+
+	in.num_tlv = num_tlv;
+
+	in.vendor_extension = 0;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.num_tlv, out.num_tlv);
+
+	ASSERT_TLV(in.subframe_config.duplex_mode, out.subframe_config.duplex_mode);
+	ASSERT_TLV(in.subframe_config.pcfich_power_offset, out.subframe_config.pcfich_power_offset);
+	ASSERT_TLV(in.subframe_config.pb, out.subframe_config.pb);
+	ASSERT_TLV(in.subframe_config.dl_cyclic_prefix_type, out.subframe_config.dl_cyclic_prefix_type);
+	ASSERT_TLV(in.subframe_config.ul_cyclic_prefix_type, out.subframe_config.ul_cyclic_prefix_type);
+
+	ASSERT_TLV(in.rf_config.dl_channel_bandwidth, out.rf_config.dl_channel_bandwidth);
+	ASSERT_TLV(in.rf_config.ul_channel_bandwidth, out.rf_config.ul_channel_bandwidth);
+	ASSERT_TLV(in.rf_config.reference_signal_power, out.rf_config.reference_signal_power);
+	ASSERT_TLV(in.rf_config.tx_antenna_ports, out.rf_config.tx_antenna_ports);
+	ASSERT_TLV(in.rf_config.rx_antenna_ports, out.rf_config.rx_antenna_ports);
+
+	ASSERT_TLV(in.phich_config.phich_resource, out.phich_config.phich_resource);
+	ASSERT_TLV(in.phich_config.phich_duration, out.phich_config.phich_duration);
+	ASSERT_TLV(in.phich_config.phich_power_offset, out.phich_config.phich_power_offset);
+
+	ASSERT_TLV(in.sch_config.primary_synchronization_signal_epre_eprers, out.sch_config.primary_synchronization_signal_epre_eprers);
+	ASSERT_TLV(in.sch_config.secondary_synchronization_signal_epre_eprers, out.sch_config.secondary_synchronization_signal_epre_eprers);
+	ASSERT_TLV(in.sch_config.physical_cell_id, out.sch_config.physical_cell_id);
+
+
+	ASSERT_TLV(in.prach_config.configuration_index, out.prach_config.configuration_index);
+	ASSERT_TLV(in.prach_config.root_sequence_index, out.prach_config.root_sequence_index);
+	ASSERT_TLV(in.prach_config.zero_correlation_zone_configuration, out.prach_config.zero_correlation_zone_configuration);
+	ASSERT_TLV(in.prach_config.high_speed_flag, out.prach_config.high_speed_flag);
+	ASSERT_TLV(in.prach_config.frequency_offset, out.prach_config.frequency_offset);
+	
+	ASSERT_TLV(in.pusch_config.hopping_mode, in.pusch_config.hopping_mode);
+	ASSERT_TLV(in.pusch_config.hopping_offset, in.pusch_config.hopping_offset);
+	ASSERT_TLV(in.pusch_config.number_of_subbands, in.pusch_config.number_of_subbands);
+
+	ASSERT_TLV(in.pucch_config.delta_pucch_shift, out.pucch_config.delta_pucch_shift);
+	ASSERT_TLV(in.pucch_config.n_cqi_rb, out.pucch_config.n_cqi_rb);
+	ASSERT_TLV(in.pucch_config.n_an_cs, out.pucch_config.n_an_cs);
+	ASSERT_TLV(in.pucch_config.n1_pucch_an, out.pucch_config.n1_pucch_an);
+
+	ASSERT_TLV(in.srs_config.bandwidth_configuration, out.srs_config.bandwidth_configuration);
+	ASSERT_TLV(in.srs_config.max_up_pts, out.srs_config.max_up_pts);
+	ASSERT_TLV(in.srs_config.srs_subframe_configuration, out.srs_config.srs_subframe_configuration);
+	ASSERT_TLV(in.srs_config.srs_acknack_srs_simultaneous_transmission, out.srs_config.srs_acknack_srs_simultaneous_transmission);
+
+	ASSERT_TLV(in.uplink_reference_signal_config.uplink_rs_hopping, out.uplink_reference_signal_config.uplink_rs_hopping);
+	ASSERT_TLV(in.uplink_reference_signal_config.group_assignment, out.uplink_reference_signal_config.group_assignment);
+	ASSERT_TLV(in.uplink_reference_signal_config.cyclic_shift_1_for_drms, out.uplink_reference_signal_config.cyclic_shift_1_for_drms);
+
+	ASSERT_TLV(in.tdd_frame_structure_config.subframe_assignment, out.tdd_frame_structure_config.subframe_assignment);
+	ASSERT_TLV(in.tdd_frame_structure_config.special_subframe_patterns, out.tdd_frame_structure_config.special_subframe_patterns);
+
+	// laa config
+	ASSERT_TLV(in.laa_config.ed_threshold_lbt_pdsch, out.laa_config.ed_threshold_lbt_pdsch);
+	ASSERT_TLV(in.laa_config.ed_threshold_lbt_drs, out.laa_config.ed_threshold_lbt_drs);
+	ASSERT_TLV(in.laa_config.pd_threshold, out.laa_config.pd_threshold);
+	ASSERT_TLV(in.laa_config.multi_carrier_type, out.laa_config.multi_carrier_type);
+	ASSERT_TLV(in.laa_config.multi_carrier_tx, out.laa_config.multi_carrier_tx);
+	ASSERT_TLV(in.laa_config.multi_carrier_freeze, out.laa_config.multi_carrier_freeze);
+	ASSERT_TLV(in.laa_config.tx_antenna_ports_drs, out.laa_config.tx_antenna_ports_drs);
+	ASSERT_TLV(in.laa_config.tx_power_drs, out.laa_config.tx_power_drs);
+	// emtc config
+	ASSERT_TLV(in.emtc_config.pbch_repetitions_enable_r13, out.emtc_config.pbch_repetitions_enable_r13);
+	ASSERT_TLV(in.emtc_config.prach_catm_root_sequence_index, out.emtc_config.prach_catm_root_sequence_index);
+	ASSERT_TLV(in.emtc_config.prach_catm_zero_correlation_zone_configuration, out.emtc_config.prach_catm_zero_correlation_zone_configuration);
+	ASSERT_TLV(in.emtc_config.prach_catm_high_speed_flag, out.emtc_config.prach_catm_high_speed_flag);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_enable, out.emtc_config.prach_ce_level_0_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_configuration_index, out.emtc_config.prach_ce_level_0_configuration_index);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_frequency_offset, out.emtc_config.prach_ce_level_0_frequency_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, out.emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_starting_subframe_periodicity, out.emtc_config.prach_ce_level_0_starting_subframe_periodicity);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_hopping_enable, out.emtc_config.prach_ce_level_0_hopping_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_0_hopping_offset, out.emtc_config.prach_ce_level_0_hopping_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_enable, out.emtc_config.prach_ce_level_1_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_configuration_index, out.emtc_config.prach_ce_level_1_configuration_index);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_frequency_offset, out.emtc_config.prach_ce_level_1_frequency_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, out.emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_starting_subframe_periodicity, out.emtc_config.prach_ce_level_1_starting_subframe_periodicity);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_hopping_enable, out.emtc_config.prach_ce_level_1_hopping_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_1_hopping_offset, out.emtc_config.prach_ce_level_1_hopping_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_enable, out.emtc_config.prach_ce_level_2_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_configuration_index, out.emtc_config.prach_ce_level_2_configuration_index);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_frequency_offset, out.emtc_config.prach_ce_level_2_frequency_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, out.emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_starting_subframe_periodicity, out.emtc_config.prach_ce_level_2_starting_subframe_periodicity);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_hopping_enable, out.emtc_config.prach_ce_level_2_hopping_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_2_hopping_offset, out.emtc_config.prach_ce_level_2_hopping_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_enable, out.emtc_config.prach_ce_level_3_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_configuration_index, out.emtc_config.prach_ce_level_3_configuration_index);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_frequency_offset, out.emtc_config.prach_ce_level_3_frequency_offset);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, out.emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_starting_subframe_periodicity, out.emtc_config.prach_ce_level_3_starting_subframe_periodicity);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_hopping_enable, out.emtc_config.prach_ce_level_3_hopping_enable);
+	ASSERT_TLV(in.emtc_config.prach_ce_level_3_hopping_offset, out.emtc_config.prach_ce_level_3_hopping_offset);
+	ASSERT_TLV(in.emtc_config.pucch_interval_ulhoppingconfigcommonmodea, out.emtc_config.pucch_interval_ulhoppingconfigcommonmodea);
+	ASSERT_TLV(in.emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, out.emtc_config.pucch_interval_ulhoppingconfigcommonmodeb);
+
+	ASSERT_TLV(in.l23_config.data_report_mode, out.l23_config.data_report_mode);
+	ASSERT_TLV(in.l23_config.sfnsf, out.l23_config.sfnsf);
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv4.tl.tag, out.nfapi_config.p7_vnf_address_ipv4.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV4_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv4.address[idx], out.nfapi_config.p7_vnf_address_ipv4.address[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv6.tl.tag, out.nfapi_config.p7_vnf_address_ipv6.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV6_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_vnf_address_ipv6.address[idx], out.nfapi_config.p7_vnf_address_ipv6.address[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.p7_vnf_port, out.nfapi_config.p7_vnf_port);
+	
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv4.tl.tag, out.nfapi_config.p7_pnf_address_ipv4.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV4_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv4.address[idx], out.nfapi_config.p7_pnf_address_ipv4.address[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv6.tl.tag, out.nfapi_config.p7_pnf_address_ipv6.tl.tag);
+	for(idx = 0; idx < NFAPI_IPV6_ADDRESS_LENGTH; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.p7_pnf_address_ipv6.address[idx], out.nfapi_config.p7_pnf_address_ipv6.address[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.p7_pnf_port, out.nfapi_config.p7_pnf_port);
+	ASSERT_TLV(in.nfapi_config.dl_ue_per_sf, out.nfapi_config.dl_ue_per_sf);
+	ASSERT_TLV(in.nfapi_config.ul_ue_per_sf, out.nfapi_config.ul_ue_per_sf);
+
+	CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.tl.tag, out.nfapi_config.rf_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.number_rf_bands, out.nfapi_config.rf_bands.number_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.rf_bands.number_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.rf_bands.rf_band[idx], out.nfapi_config.rf_bands.rf_band[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.timing_window, out.nfapi_config.timing_window);
+	ASSERT_TLV(in.nfapi_config.timing_info_mode, out.nfapi_config.timing_info_mode);
+	ASSERT_TLV(in.nfapi_config.timing_info_period, out.nfapi_config.timing_info_period);
+	ASSERT_TLV(in.nfapi_config.max_transmit_power, out.nfapi_config.max_transmit_power);
+	ASSERT_TLV(in.nfapi_config.earfcn, out.nfapi_config.earfcn); 
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.tl.tag, out.nfapi_config.nmm_gsm_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_gsm_frequency_bands.bands[idx], out.nfapi_config.nmm_gsm_frequency_bands.bands[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.tl.tag, out.nfapi_config.nmm_umts_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_umts_frequency_bands.bands[idx], out.nfapi_config.nmm_umts_frequency_bands.bands[idx]);
+	}
+
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.tl.tag, out.nfapi_config.nmm_lte_frequency_bands.tl.tag);
+	CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands, out.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands);
+	for(idx = 0; idx < out.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands; ++idx)
+	{
+		CU_ASSERT_EQUAL(in.nfapi_config.nmm_lte_frequency_bands.bands[idx], out.nfapi_config.nmm_lte_frequency_bands.bands[idx]);
+	}
+
+	ASSERT_TLV(in.nfapi_config.nmm_uplink_rssi_supported, out.nfapi_config.nmm_uplink_rssi_supported); 
+}
+void nfapi_test_config_response()
+{
+	nfapi_config_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_config_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CONFIG_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_start_request()
+{
+	nfapi_start_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_start_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_START_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+}
+void nfapi_test_start_response()
+{
+	nfapi_start_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_start_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_START_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_stop_request()
+{
+	nfapi_stop_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_stop_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_STOP_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+}
+void nfapi_test_stop_response()
+{
+	nfapi_stop_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_stop_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_STOP_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+}
+void nfapi_test_measurement_request()
+{
+//	#define SET_TLV(_TLV, _TAG, _VALUE) { _TLV.tl.tag = _TAG; _TLV.value = _VALUE; }
+//	#define ASSERT_TLV(IN_TLV, OUT_TLV) { CU_ASSERT_EQUAL(IN_TLV.tl.tag, OUT_TLV.tl.tag); CU_ASSERT_EQUAL(IN_TLV.value, OUT_TLV.value);}
+	uint16_t num_tlv = 0;
+	nfapi_measurement_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_measurement_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_MEASUREMENT_REQUEST;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	SET_TLV(in.dl_rs_tx_power, NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, 1);
+	SET_TLV(in.received_interference_power, NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, 123);
+	SET_TLV(in.thermal_noise_power, NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, 255);
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+
+	ASSERT_TLV(in.dl_rs_tx_power, out.dl_rs_tx_power);
+	ASSERT_TLV(in.received_interference_power, out.received_interference_power);
+	ASSERT_TLV(in.thermal_noise_power, out.thermal_noise_power);
+}
+void nfapi_test_measurement_response()
+{
+	uint16_t num_tlv = 0;
+	nfapi_measurement_response_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_measurement_response_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
+	in.header.message_length = 0;
+	in.header.spare = 0;
+
+	in.error_code = NFAPI_MSG_OK;
+
+	SET_TLV(in.dl_rs_tx_power_measurement, NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, -400);
+
+	in.received_interference_power_measurement.tl.tag = NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG;
+	in.received_interference_power_measurement.number_of_resource_blocks = 100;
+	in.received_interference_power_measurement.received_interference_power[0] = -8767;
+
+	SET_TLV(in.thermal_noise_power_measurement, NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, -8900);
+
+	int packedMessageLength = nfapi_p5_message_pack(&in, sizeof(in), gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p5_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.error_code, out.error_code);
+
+	ASSERT_TLV(in.dl_rs_tx_power_measurement, out.dl_rs_tx_power_measurement);
+	CU_ASSERT_EQUAL(in.received_interference_power_measurement.tl.tag, out.received_interference_power_measurement.tl.tag);
+	CU_ASSERT_EQUAL(in.received_interference_power_measurement.number_of_resource_blocks, out.received_interference_power_measurement.number_of_resource_blocks);
+	// check array
+	ASSERT_TLV(in.thermal_noise_power_measurement, out.thermal_noise_power_measurement);
+}
+
+void nfapi_test_dl_config_request()
+{
+
+
+	uint16_t idx = 0;
+	nfapi_dl_config_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_dl_config_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 0x3FFF;
+
+	in.dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+	in.dl_config_request_body.number_pdcch_ofdm_symbols = 4;
+	in.dl_config_request_body.number_dci = 255;
+	in.dl_config_request_body.number_pdu = 0;
+	in.dl_config_request_body.number_pdsch_rnti = 0;
+	in.dl_config_request_body.transmission_power_pcfich = 10000;
+
+	in.dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)(malloc(sizeof(nfapi_dl_config_request_pdu_t) * 12));
+	
+	in.dl_config_request_body.dl_config_pdu_list[0].pdu_type = 0;
+	in.dl_config_request_body.dl_config_pdu_list[0].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.primary_cell_type = rand8(0, 2);
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_flag = rand8(0, 1);
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.number_ul_dl_configurations = rand8(0, 5);
+	for(idx = 0; idx <in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.number_ul_dl_configurations; ++idx)
+	{
+		in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_indication[idx] = rand8(1, 5);
+	}
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm_struct_flag = 1; //rand8(0, 1);
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_prb_per_subband = 3;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.number_of_subbands = 2;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_antennas = 2;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].subband_index = 1;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].scheduled_ues = 2;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].precoding_value[0][0] = 0x321;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].precoding_value[0][1] = 0x321;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].precoding_value[1][0] = 0x321;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[0].precoding_value[1][1] = 0x321;
+	
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[1].subband_index = 2;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[1].scheduled_ues = 1;	
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[1].precoding_value[0][0] = 0x32A;
+	in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[1].precoding_value[1][0] = 0x32A;
+
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[1].pdu_type = 1;
+	in.dl_config_request_body.dl_config_pdu_list[1].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[1].bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[2].pdu_type = 2;
+	in.dl_config_request_body.dl_config_pdu_list[2].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[2].mch_pdu.mch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[3].pdu_type = 3;
+	in.dl_config_request_body.dl_config_pdu_list[3].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[4].pdu_type = 4;
+	in.dl_config_request_body.dl_config_pdu_list[4].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[4].pch_pdu.pch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[4].pch_pdu.pch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[5].pdu_type = 5;
+	in.dl_config_request_body.dl_config_pdu_list[5].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[5].prs_pdu.prs_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[6].pdu_type = 6;
+	in.dl_config_request_body.dl_config_pdu_list[6].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[6].csi_rs_pdu.csi_rs_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[6].csi_rs_pdu.csi_rs_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[7].pdu_type = 7;
+	in.dl_config_request_body.dl_config_pdu_list[7].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_params_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG;
+	in.dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_params_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[8].pdu_type = 8;
+	in.dl_config_request_body.dl_config_pdu_list[8].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[8].mpdcch_pdu.mpdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+
+	in.dl_config_request_body.dl_config_pdu_list[9].pdu_type = 9;
+	in.dl_config_request_body.dl_config_pdu_list[9].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+	
+	in.dl_config_request_body.dl_config_pdu_list[10].pdu_type = 10;
+	in.dl_config_request_body.dl_config_pdu_list[10].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+	
+	in.dl_config_request_body.dl_config_pdu_list[11].pdu_type = 11;
+	in.dl_config_request_body.dl_config_pdu_list[11].pdu_size = 123;
+	in.dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG;
+	in.dl_config_request_body.number_pdu++;
+	
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, 0);
+	CU_ASSERT_NOT_EQUAL(packedMessageLength, -1);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.tl.tag, out.dl_config_request_body.tl.tag);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.number_pdcch_ofdm_symbols, out.dl_config_request_body.number_pdcch_ofdm_symbols);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.number_dci, out.dl_config_request_body.number_dci);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.number_pdu, out.dl_config_request_body.number_pdu);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.number_pdsch_rnti, out.dl_config_request_body.number_pdsch_rnti);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.transmission_power_pcfich, out.dl_config_request_body.transmission_power_pcfich);
+
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].pdu_type, out.dl_config_request_body.dl_config_pdu_list[0].pdu_type);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].pdu_size, out.dl_config_request_body.dl_config_pdu_list[0].pdu_size);
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.dci_format);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.rnti);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.mcs_1);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.transport_block_to_codeword_swap_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.mcs_2);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_2);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.harq_process);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.tpmi);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.pmi);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.precoding_information);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.tpc);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.ngap);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.transport_block_size_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.downlink_power_offset);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.allocate_prach_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.preamble_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.prach_mask_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel8.transmission_power);
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.mcch_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.mcch_change_notification);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel9.scrambling_identity);
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.cross_carrier_scheduling_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.carrier_indicator);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.srs_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.srs_request);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.antenna_ports_scrambling_and_layers);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.total_dci_length_including_padding);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel10.n_dl_rb);
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel11.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel11.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel11.harq_ack_resource_offset);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel11.pdsch_re_mapping_quasi_co_location_indicator);
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.primary_cell_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.number_ul_dl_configurations);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_indication[NFAPI_MAX_UL_DL_CONFIGURATIONS -1]);
+
+	CU_ASSERT_EQUAL(in.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tl.tag, out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.laa_end_partial_sf_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.laa_end_partial_sf_configuration);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.initial_lbt_sf);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.codebook_size_determination);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.drms_table_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm_struct_flag);
+	if(out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm_struct_flag)
+	{
+		
+		IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_prb_per_subband);
+		IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.number_of_subbands);
+		IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_antennas);
+		
+		uint8_t sb_idx;
+		for(sb_idx = 0; sb_idx < out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.number_of_subbands; ++sb_idx)
+		{
+			IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[sb_idx].subband_index);
+			IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[sb_idx].scheduled_ues);
+			
+			uint8_t a_idx;
+			uint8_t su_idx;
+			
+			for(a_idx = 0; a_idx < out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_antennas ; ++a_idx)
+			{
+				for(su_idx = 0; su_idx < out.dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[sb_idx].scheduled_ues; ++su_idx)
+				{
+					IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[0].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[sb_idx].precoding_value[a_idx][su_idx]);
+				}
+			}
+		}
+	}
+
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[1].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[1].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[1].bch_pdu.bch_pdu_rel8.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[2].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[2].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[2].mch_pdu.mch_pdu_rel8.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel8.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel9.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel10.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel11.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel12.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[3].dlsch_pdu.dlsch_pdu_rel13.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[4].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[4].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[4].pch_pdu.pch_pdu_rel8.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[4].pch_pdu.pch_pdu_rel13.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[5].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[5].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[5].prs_pdu.prs_pdu_rel9.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[6].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[6].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[6].csi_rs_pdu.csi_rs_pdu_rel10.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[6].csi_rs_pdu.csi_rs_pdu_rel13.tl.tag);
+
+	
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel8.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel9.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel10.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel11.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel12.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_params_rel11.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[7].epdcch_pdu.epdcch_params_rel13.tl.tag);
+
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[8].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[8].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[8].mpdcch_pdu.mpdcch_pdu_rel13.tl.tag);
+	
+	//in.dl_config_request_body.dl_config_pdu_list[8].mpdcch_pdu;
+	//
+	
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.length);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.pdu_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.transmission_power);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[9].nbch_pdu.nbch_pdu_rel13.hyper_sfn_2_lsbs);
+	
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.length);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.pdu_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.ncce_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.aggregation_level);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.start_symbol);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.rnti_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.rnti);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.scrambling_reinitialization_batch_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.dci_format);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.scheduling_delay);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.resource_assignment);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.repetition_number);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.mcs);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.new_data_indicator);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.starting_number_of_nprach_repetitions);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.subcarrier_indication_of_nprach);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.paging_direct_indication_differentation_flag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.direct_indication);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[10].npdcch_pdu.npdcch_pdu_rel13.total_dci_length_including_padding);
+	
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].pdu_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].pdu_size);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.length);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.pdu_index);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.start_symbol);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.rnti_type);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.rnti);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.repetition_number);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.modulation);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.scrambling_sequence_initialization_cinit);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.sf_idx);
+	IN_OUT_ASSERT(dl_config_request_body.dl_config_pdu_list[11].ndlsch_pdu.ndlsch_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue);
+	
+	
+	free(in.dl_config_request_body.dl_config_pdu_list);
+	free(out.dl_config_request_body.dl_config_pdu_list);
+}
+void nfapi_test_ul_config_request()
+{
+	nfapi_ul_config_request_t in;
+	//memset(&in, 0, sizeof(in));
+	nfapi_ul_config_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 0x3FFF;
+
+	in.ul_config_request_body.tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
+	in.ul_config_request_body.number_of_pdus = 0;
+	in.ul_config_request_body.rach_prach_frequency_resources = 34;
+	in.ul_config_request_body.srs_present = 1;
+	
+	nfapi_ul_config_request_pdu_t ul_config_pdu_list[24];
+	memset(&ul_config_pdu_list[0], 0, sizeof(ul_config_pdu_list));
+	in.ul_config_request_body.ul_config_pdu_list = &ul_config_pdu_list[0];
+	
+	in.ul_config_request_body.ul_config_pdu_list[0].pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[0].ulsch_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[1].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[1].ulsch_cqi_ri_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[2].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[2].ulsch_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[3].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[3].ulsch_cqi_harq_ri_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[4].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[4].uci_cqi_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+
+	in.ul_config_request_body.ul_config_pdu_list[5].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[5].uci_sr_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[6].pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[6].uci_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[7].pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[7].uci_sr_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[8].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[8].uci_cqi_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[9].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[9].uci_cqi_sr_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[10].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[10].uci_cqi_sr_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[11].pdu_type = NFAPI_UL_CONFIG_SRS_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[11].srs_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[12].pdu_type = NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[12].harq_buffer_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[13].pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[13].ulsch_uci_csi_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[14].pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[14].ulsch_uci_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[15].pdu_type = NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE;
+	//in.ul_config_request_body.ul_config_pdu_list[15].ulsch_csi_uci_harq_pdu;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[16].pdu_type = NFAPI_UL_CONFIG_NULSCH_PDU_TYPE;
+	in.ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG;
+	in.ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
+	in.ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG;
+	in.ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG;
+	in.ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.tl.tag = NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG;
+	in.ul_config_request_body.number_of_pdus++;
+	
+	in.ul_config_request_body.ul_config_pdu_list[17].pdu_type = NFAPI_UL_CONFIG_NRACH_PDU_TYPE;
+	in.ul_config_request_body.ul_config_pdu_list[17].nrach_pdu.nrach_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG;
+	in.ul_config_request_body.number_of_pdus++;
+	
+
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	IN_OUT_ASSERT(header.message_id);
+	IN_OUT_ASSERT(sfn_sf);
+	IN_OUT_ASSERT(ul_config_request_body.rach_prach_frequency_resources);
+	IN_OUT_ASSERT(ul_config_request_body.srs_present);
+	IN_OUT_ASSERT(ul_config_request_body.number_of_pdus);
+	
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[0].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[1].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[2].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[3].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[4].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[5].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[6].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[7].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[8].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[9].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[10].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[11].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[12].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[13].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[14].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[15].pdu_type);
+	
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].pdu_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.nulsch_format);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.handle);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.size);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.rnti);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.resource_assignment);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.mcs);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.redudancy_version);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.repetition_number);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.new_data_indication);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.n_srs);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.scrambling_sequence_initialization_cinit);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.sf_idx);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.handle);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.rnti);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.virtual_cell_id_enabled_flag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.npusch_identity);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.ue_type);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.empty_symbols);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.total_number_of_repetitions);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.repetition_number);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[16].nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.harq_ack_resource);
+	
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[17].nrach_pdu.nrach_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[17].nrach_pdu.nrach_pdu_rel13.nprach_config_0);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[17].nrach_pdu.nrach_pdu_rel13.nprach_config_1);
+	IN_OUT_ASSERT(ul_config_request_body.ul_config_pdu_list[17].nrach_pdu.nrach_pdu_rel13.nprach_config_2);
+	
+
+	free(out.ul_config_request_body.ul_config_pdu_list);
+	
+}
+void nfapi_test_hi_dci0_request()
+{
+	nfapi_hi_dci0_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_hi_dci0_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_HI_DCI0_REQUEST;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 9999;
+	in.hi_dci0_request_body.tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG;
+	in.hi_dci0_request_body.sfnsf = 123;
+	in.hi_dci0_request_body.number_of_dci = 0;
+	in.hi_dci0_request_body.number_of_hi = 0;
+
+	in.hi_dci0_request_body.hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)malloc(sizeof(nfapi_hi_dci0_request_pdu_t) * 8);
+
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.resource_block_start = 2;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 23;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.hi_value = 0;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.i_phich = 2;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.transmission_power = 12312;;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel10.flag_tb2 = 1;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel10.hi_value_2 = 2;
+
+	in.hi_dci0_request_body.number_of_hi++;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
+	/*
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.dci_format;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.cce_index;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.aggregation_level;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.rnti;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.resource_block_start;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.number_of_resource_block;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.mcs_1;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.frequency_hopping_bits;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.new_data_indication_1;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.ue_tx_antenna_seleciton;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.tpc;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.cqi_csi_request;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.ul_index;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.dl_assignment_index;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.tpc_bitmap;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.transmission_power;
+	*/
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG;
+	/*
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.cross_carrier_scheduling_flag;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.carrier_indicator;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.size_of_cqi_csi_feild;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.srs_flag;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.srs_request;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.resource_allocation_flag;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.resource_allocation_type;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.resource_block_coding;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.mcs_2;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.new_data_indication_2;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.number_of_antenna_ports;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.tpmi;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.total_dci_length_including_padding;
+	*/
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel12.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG;
+	/*
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel12.pscch_resource;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel12.time_resource_pattern;
+	*/
+
+	in.hi_dci0_request_body.number_of_dci++;
+
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].pdu_type = NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].epdcch_dci_pdu.epdcch_parameters_rel11.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG;
+	/*
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].edpcch_dci_pdu.edpcch_dci_pdu_rel8;
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_block;
+	uint8_t mcs_1;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication_1;
+	uint8_t ue_tx_antenna_seleciton;
+	uint8_t tpc;
+	uint8_t cqi_csi_request;
+	uint8_t ul_index;
+	uint8_t dl_assignment_index;
+	uint32_t tpc_bitmap;
+	uint16_t transmission_power;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].edpcch_dci_pdu.edpcch_dci_pdu_rel10.cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t size_of_cqi_csi_feild;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t resource_allocation_flag;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t mcs_2;
+	uint8_t new_data_indication_2;
+	uint8_t number_of_antenna_ports;
+	uint8_t tpmi;
+	uint8_t total_dci_length_including_padding;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[2].edpcch_dci_pdu.edpcch_parameters_rel11.edpcch_resource_assigenment_flag;
+	uint16_t edpcch_id;
+	uint8_t epdcch_start_symbol;
+	uint8_t epdcch_num_prb;
+	uint8_t epdcch_prb_index[NFAPI_MAX_EPDCCH_PRB];
+	nfapi_bf_vector_t bf_vector;
+	*/
+	in.hi_dci0_request_body.number_of_dci++;
+	
+	in.hi_dci0_request_body.hi_dci0_pdu_list[3].pdu_type = NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[3].mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tl.tag = NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG;
+	/*
+	in.hi_dci0_request_body.hi_dci0_pdu_list[3].mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.mpdcch_narrowband;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_transmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggreagation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t mcs;
+	uint8_t pusch_repetition_levels;
+	uint8_t frequency_hopping_flag;
+	uint8_t new_data_indication;
+	uint8_t harq_process;
+	uint8_t redudency_version;
+	uint8_t tpc;
+	uint8_t csi_request;
+	uint8_t ul_inex;
+	uint8_t dai_presence_flag;
+	uint8_t dl_assignment_index;
+	uint8_t srs_request;
+	uint8_t dci_subframe_repetition_number;
+	uint32_t tcp_bitmap;
+	uint8_t total_dci_length_include_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[NFAPI_MAX_ANTENNA_PORT_COUNT];
+	*/
+	in.hi_dci0_request_body.number_of_dci++;
+
+	in.hi_dci0_request_body.hi_dci0_pdu_list[4].pdu_type = NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE;
+	in.hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.tl.tag = NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG;
+	in.hi_dci0_request_body.number_of_dci++;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.tl.tag, out.hi_dci0_request_body.tl.tag);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.sfnsf, out.hi_dci0_request_body.sfnsf);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.number_of_dci, out.hi_dci0_request_body.number_of_dci);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.number_of_hi, out.hi_dci0_request_body.number_of_hi);
+
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[0].pdu_type, out.hi_dci0_request_body.hi_dci0_pdu_list[0].pdu_type);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.tl.tag, out.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel10.tl.tag, out.hi_dci0_request_body.hi_dci0_pdu_list[0].hi_pdu.hi_pdu_rel10.tl.tag);
+
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[1].pdu_type, out.hi_dci0_request_body.hi_dci0_pdu_list[1].pdu_type);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.tl.tag, out.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.tl.tag, out.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel10.tl.tag);
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel12.tl.tag, out.hi_dci0_request_body.hi_dci0_pdu_list[1].dci_pdu.dci_pdu_rel12.tl.tag);
+
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[2].pdu_type, out.hi_dci0_request_body.hi_dci0_pdu_list[2].pdu_type);
+
+	CU_ASSERT_EQUAL(in.hi_dci0_request_body.hi_dci0_pdu_list[3].pdu_type, out.hi_dci0_request_body.hi_dci0_pdu_list[3].pdu_type);
+	
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].pdu_type);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.tl.tag);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.ncce_index);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.scrambling_reinitialization_batch_index);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.resource_assignment);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator);
+	IN_OUT_ASSERT(hi_dci0_request_body.hi_dci0_pdu_list[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number);
+
+	free(in.hi_dci0_request_body.hi_dci0_pdu_list);
+	free(out.hi_dci0_request_body.hi_dci0_pdu_list);
+}
+void nfapi_test_tx_request()
+{
+	nfapi_tx_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_tx_request_t out;
+
+	nfapi_p7_codec_config_t config;
+	config.allocate = &nfapi_allocate_pdu;
+	//config.deallocate = &nfapi_deallocate_pdu;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_TX_REQUEST;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	uint8_t pdu1_seg1[16];
+	uint8_t pdu1_seg2[16];
+	uint8_t pdu2[8];
+
+	in.sfn_sf = 10230;
+	in.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+	in.tx_request_body.number_of_pdus = 2;
+
+	in.tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)(malloc(sizeof(nfapi_tx_request_pdu_t) * in.tx_request_body.number_of_pdus));
+
+	in.tx_request_body.tx_pdu_list[0].pdu_length = sizeof(pdu1_seg1) + sizeof(pdu1_seg2);
+	in.tx_request_body.tx_pdu_list[0].pdu_index = 0;
+	in.tx_request_body.tx_pdu_list[0].num_segments = 2;
+	in.tx_request_body.tx_pdu_list[0].segments[0].segment_length = sizeof(pdu1_seg1);
+	in.tx_request_body.tx_pdu_list[0].segments[0].segment_data = pdu1_seg1;
+	in.tx_request_body.tx_pdu_list[0].segments[1].segment_length = sizeof(pdu1_seg2);
+	in.tx_request_body.tx_pdu_list[0].segments[1].segment_data = pdu1_seg2;
+
+	in.tx_request_body.tx_pdu_list[1].pdu_length = sizeof(pdu2);
+	in.tx_request_body.tx_pdu_list[1].pdu_index = 0;
+	in.tx_request_body.tx_pdu_list[1].num_segments = 1;
+	in.tx_request_body.tx_pdu_list[1].segments[0].segment_length = sizeof(pdu2);
+	in.tx_request_body.tx_pdu_list[1].segments[0].segment_data = pdu2;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, &config);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), &config);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	CU_ASSERT_EQUAL(in.tx_request_body.tl.tag, out.tx_request_body.tl.tag);
+	CU_ASSERT_EQUAL(in.tx_request_body.number_of_pdus, out.tx_request_body.number_of_pdus);
+	CU_ASSERT_EQUAL(in.tx_request_body.tx_pdu_list[0].pdu_length, out.tx_request_body.tx_pdu_list[0].pdu_length);
+	CU_ASSERT_EQUAL(1, out.tx_request_body.tx_pdu_list[0].num_segments);
+
+	CU_ASSERT_EQUAL(in.tx_request_body.tx_pdu_list[1].pdu_length, out.tx_request_body.tx_pdu_list[1].pdu_length);
+	CU_ASSERT_EQUAL(1, out.tx_request_body.tx_pdu_list[1].num_segments);
+
+	CU_ASSERT_EQUAL(0, memcmp(pdu2, out.tx_request_body.tx_pdu_list[1].segments[0].segment_data, sizeof(pdu2)));
+
+	free(out.tx_request_body.tx_pdu_list[0].segments[0].segment_data);
+	free(out.tx_request_body.tx_pdu_list[1].segments[0].segment_data);
+
+	free(in.tx_request_body.tx_pdu_list);
+	free(out.tx_request_body.tx_pdu_list);
+}
+void nfapi_test_harq_indication()
+{
+	nfapi_harq_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_harq_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_HARQ_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10230;
+	in.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+	in.harq_indication_body.number_of_harqs = 6;
+
+	in.harq_indication_body.harq_pdu_list = (nfapi_harq_indication_pdu_t*)(calloc(1, sizeof(nfapi_harq_indication_pdu_t) * in.harq_indication_body.number_of_harqs));
+
+	in.harq_indication_body.harq_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL8_TAG;
+	in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.mode = 0;
+	in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.number_of_ack_nack = 2;
+	in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.harq_data.bundling.value_0 = 6;
+	in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.harq_data.bundling.value_1 = 6;
+
+	in.harq_indication_body.harq_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL9_TAG;
+	in.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.mode = 0;
+	in.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.number_of_ack_nack = 2;
+	in.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.harq_data[0].bundling.value_0 = 2;
+
+	in.harq_indication_body.harq_pdu_list[2].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
+	in.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.mode = 2;
+	in.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.number_of_ack_nack = 2;
+	in.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.harq_data[0].special_bundling.value_0 = 2;
+
+	in.harq_indication_body.harq_pdu_list[3].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[3].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[3].ul_cqi_information.ul_cqi = 9;
+	in.harq_indication_body.harq_pdu_list[3].ul_cqi_information.channel = 3;
+	in.harq_indication_body.harq_pdu_list[3].harq_indication_fdd_rel8.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL8_TAG;
+	in.harq_indication_body.harq_pdu_list[3].harq_indication_fdd_rel8.harq_tb1 = 1;
+	in.harq_indication_body.harq_pdu_list[3].harq_indication_fdd_rel8.harq_tb2 = 2;
+
+
+	in.harq_indication_body.harq_pdu_list[4].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL9_TAG;
+	in.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.mode = 0;
+	in.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.number_of_ack_nack = 3;
+	in.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.harq_tb_n[0] = 45;
+
+	in.harq_indication_body.harq_pdu_list[5].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
+	in.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.mode = 1;
+	in.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.number_of_ack_nack = 22;
+	in.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.harq_tb_n[0] = 123;
+
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+
+	CU_ASSERT_EQUAL(in.harq_indication_body.tl.tag,out.harq_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.number_of_harqs,out.harq_indication_body.number_of_harqs);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[0].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.tl.tag,out.harq_indication_body.harq_pdu_list[0].harq_indication_tdd_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[1].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[1].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.tl.tag,out.harq_indication_body.harq_pdu_list[1].harq_indication_tdd_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[2].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[2].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.tl.tag,out.harq_indication_body.harq_pdu_list[2].harq_indication_tdd_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[3].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[3].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[3].ul_cqi_information.tl.tag,out.harq_indication_body.harq_pdu_list[3].ul_cqi_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[3].harq_indication_fdd_rel8.tl.tag,out.harq_indication_body.harq_pdu_list[3].harq_indication_fdd_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[4].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[4].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.tl.tag,out.harq_indication_body.harq_pdu_list[4].harq_indication_fdd_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[5].rx_ue_information.tl.tag,out.harq_indication_body.harq_pdu_list[5].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.tl.tag,out.harq_indication_body.harq_pdu_list[5].harq_indication_fdd_rel13.tl.tag);
+
+	free(in.harq_indication_body.harq_pdu_list);
+	free(out.harq_indication_body.harq_pdu_list);
+}
+void nfapi_test_crc_indication()
+{
+	nfapi_crc_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_crc_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_CRC_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10230;
+	in.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG;
+	in.crc_indication_body.number_of_crcs = 2;
+	in.crc_indication_body.crc_pdu_list = (nfapi_crc_indication_pdu_t*)malloc(sizeof(nfapi_crc_indication_pdu_t) * in.crc_indication_body.number_of_crcs);
+	in.crc_indication_body.crc_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.crc_indication_body.crc_pdu_list[0].rx_ue_information.handle = 0x4567;
+	in.crc_indication_body.crc_pdu_list[0].rx_ue_information.rnti = 42;
+	in.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG;
+	in.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.crc_flag = 0;
+
+
+	in.crc_indication_body.crc_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.crc_indication_body.crc_pdu_list[1].rx_ue_information.handle = 0x4568;
+	in.crc_indication_body.crc_pdu_list[1].rx_ue_information.rnti = 43;
+	in.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG;
+	in.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.crc_flag = 1;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.crc_indication_body.tl.tag, out.crc_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.crc_indication_body.number_of_crcs, out.crc_indication_body.number_of_crcs);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[0].rx_ue_information.tl.tag, out.crc_indication_body.crc_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[0].rx_ue_information.handle, out.crc_indication_body.crc_pdu_list[0].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[0].rx_ue_information.rnti, out.crc_indication_body.crc_pdu_list[0].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.tl.tag, out.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.crc_flag, out.crc_indication_body.crc_pdu_list[0].crc_indication_rel8.crc_flag);
+
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[1].rx_ue_information.tl.tag, out.crc_indication_body.crc_pdu_list[1].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[1].rx_ue_information.handle, out.crc_indication_body.crc_pdu_list[1].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[1].rx_ue_information.rnti, out.crc_indication_body.crc_pdu_list[1].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.tl.tag, out.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.crc_flag, out.crc_indication_body.crc_pdu_list[1].crc_indication_rel8.crc_flag);
+
+	free(in.crc_indication_body.crc_pdu_list);
+	free(out.crc_indication_body.crc_pdu_list);
+}
+void nfapi_test_rx_ulsch_indication()
+{
+	nfapi_rx_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_rx_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RX_ULSCH_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	uint8_t pdu1[32];
+	uint8_t pdu2[8];
+
+	in.sfn_sf = 12354;
+	in.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
+	in.rx_indication_body.number_of_pdus = 3;
+
+	in.rx_indication_body.rx_pdu_list = (nfapi_rx_indication_pdu_t*)(calloc(1, sizeof(nfapi_rx_indication_pdu_t) * in.rx_indication_body.number_of_pdus));
+	
+	in.rx_indication_body.rx_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.rx_indication_body.rx_pdu_list[0].rx_ue_information.handle = 0xFEDC;
+	in.rx_indication_body.rx_pdu_list[0].rx_ue_information.rnti = 42;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.length = sizeof(pdu1);
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.offset = 1;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.ul_cqi = 1;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.timing_advance = 23;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.tl.tag = NFAPI_RX_INDICATION_REL9_TAG;
+	in.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.timing_advance_r9 = 1;
+	in.rx_indication_body.rx_pdu_list[0].data = pdu1;
+
+	in.rx_indication_body.rx_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.rx_indication_body.rx_pdu_list[1].rx_ue_information.handle = 0xFEDC;
+	in.rx_indication_body.rx_pdu_list[1].rx_ue_information.rnti = 43;
+	in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
+	in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.length = 0;
+	in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.offset = 1;
+	in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.ul_cqi = 1;
+	in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.timing_advance = 23;
+	in.rx_indication_body.rx_pdu_list[1].data = 0;
+
+	in.rx_indication_body.rx_pdu_list[2].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.rx_indication_body.rx_pdu_list[2].rx_ue_information.handle = 0xFEDC;
+	in.rx_indication_body.rx_pdu_list[2].rx_ue_information.rnti = 43;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.length = sizeof(pdu2);
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.offset = 1;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.ul_cqi = 1;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.timing_advance = 23;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.tl.tag = NFAPI_RX_INDICATION_REL9_TAG;
+	in.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.timing_advance_r9 = 34;
+	in.rx_indication_body.rx_pdu_list[2].data = pdu2;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	CU_ASSERT_EQUAL(in.rx_indication_body.tl.tag, out.rx_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.number_of_pdus, out.rx_indication_body.number_of_pdus);
+	
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_ue_information.tl.tag, out.rx_indication_body.rx_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_ue_information.handle, out.rx_indication_body.rx_pdu_list[0].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_ue_information.rnti, out.rx_indication_body.rx_pdu_list[0].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.tl.tag, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.length, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.length);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.offset, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.offset);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.ul_cqi, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.ul_cqi);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.timing_advance, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel8.timing_advance);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.tl.tag, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.timing_advance_r9, out.rx_indication_body.rx_pdu_list[0].rx_indication_rel9.timing_advance_r9);
+	CU_ASSERT_EQUAL(0, memcmp(in.rx_indication_body.rx_pdu_list[0].data, out.rx_indication_body.rx_pdu_list[0].data, sizeof(pdu1)));
+
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_ue_information.tl.tag, out.rx_indication_body.rx_pdu_list[1].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_ue_information.handle, out.rx_indication_body.rx_pdu_list[1].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_ue_information.rnti, out.rx_indication_body.rx_pdu_list[1].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.tl.tag, out.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.length, out.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.length);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.offset, out.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.offset);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.ul_cqi, out.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.ul_cqi);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.timing_advance, out.rx_indication_body.rx_pdu_list[1].rx_indication_rel8.timing_advance);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[1].data, 0);
+
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_ue_information.tl.tag, out.rx_indication_body.rx_pdu_list[2].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_ue_information.handle, out.rx_indication_body.rx_pdu_list[2].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_ue_information.rnti, out.rx_indication_body.rx_pdu_list[2].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.tl.tag, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.length, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.length);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.offset, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.offset);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.ul_cqi, in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.ul_cqi);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.timing_advance, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel8.timing_advance);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.tl.tag, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.timing_advance_r9, out.rx_indication_body.rx_pdu_list[2].rx_indication_rel9.timing_advance_r9);
+	CU_ASSERT_EQUAL(0, memcmp(in.rx_indication_body.rx_pdu_list[2].data, out.rx_indication_body.rx_pdu_list[2].data, sizeof(pdu2)));
+
+	free(in.rx_indication_body.rx_pdu_list);
+	free(out.rx_indication_body.rx_pdu_list);
+
+}
+void nfapi_test_rach_indication()
+{
+	nfapi_rach_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_rach_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RACH_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10230;
+	in.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG;
+	in.rach_indication_body.number_of_preambles = 2;
+	in.rach_indication_body.preamble_list = (nfapi_preamble_pdu_t*)(malloc(sizeof(nfapi_preamble_pdu_t)*in.rach_indication_body.number_of_preambles));
+	in.rach_indication_body.preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG;
+	in.rach_indication_body.preamble_list[0].preamble_rel9.tl.tag = NFAPI_PREAMBLE_REL9_TAG;
+	in.rach_indication_body.preamble_list[0].preamble_rel13.tl.tag = NFAPI_PREAMBLE_REL13_TAG;
+
+	in.rach_indication_body.preamble_list[1].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG;
+	in.rach_indication_body.preamble_list[1].preamble_rel9.tl.tag = NFAPI_PREAMBLE_REL9_TAG;
+	in.rach_indication_body.preamble_list[1].preamble_rel13.tl.tag = NFAPI_PREAMBLE_REL13_TAG;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.rach_indication_body.tl.tag, out.rach_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.number_of_preambles, out.rach_indication_body.number_of_preambles);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[0].preamble_rel8.tl.tag, out.rach_indication_body.preamble_list[0].preamble_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[0].preamble_rel9.tl.tag, out.rach_indication_body.preamble_list[0].preamble_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[0].preamble_rel13.tl.tag, out.rach_indication_body.preamble_list[0].preamble_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[1].preamble_rel8.tl.tag, out.rach_indication_body.preamble_list[1].preamble_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[1].preamble_rel9.tl.tag, out.rach_indication_body.preamble_list[1].preamble_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.rach_indication_body.preamble_list[1].preamble_rel13.tl.tag, out.rach_indication_body.preamble_list[1].preamble_rel13.tl.tag);
+
+	free(in.rach_indication_body.preamble_list);
+	free(out.rach_indication_body.preamble_list);
+}
+void nfapi_test_srs_indication()
+{
+	nfapi_srs_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_srs_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_SRS_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10230;
+	in.srs_indication_body.tl.tag = NFAPI_SRS_INDICATION_BODY_TAG;
+	in.srs_indication_body.number_of_ues = 2;
+	in.srs_indication_body.srs_pdu_list = (nfapi_srs_indication_pdu_t*)(malloc(sizeof(nfapi_srs_indication_pdu_t) * in.srs_indication_body.number_of_ues));
+	in.srs_indication_body.srs_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.srs_indication_body.srs_pdu_list[0].rx_ue_information.handle = 0x4567;
+	in.srs_indication_body.srs_pdu_list[0].rx_ue_information.rnti = 42;
+
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.tl.tag = NFAPI_SRS_INDICATION_FDD_REL8_TAG;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.doppler_estimation = 244;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.timing_advance = 45;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.number_of_resource_blocks = 100;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.rb_start = 0;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.snr[0] = 255;
+	//...
+	
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.tl.tag = NFAPI_SRS_INDICATION_FDD_REL9_TAG;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.timing_advance_r9 = 7690;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.tl.tag = NFAPI_SRS_INDICATION_TDD_REL10_TAG;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.uppts_symbol = 1;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.tl.tag = NFAPI_SRS_INDICATION_FDD_REL11_TAG;
+	in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.ul_rtoa = 4800;
+
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.tl.tag = NFAPI_TDD_CHANNEL_MEASUREMENT_TAG;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_prb_per_subband = 4;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.number_of_subbands = 2;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_atennas = 2;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].subband_index = 4;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].channel[0] = 0xEEEE;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].subband_index = 6;
+	in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].channel[0] = 0xAAAA;
+
+	in.srs_indication_body.srs_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.srs_indication_body.srs_pdu_list[1].rx_ue_information.handle = 0x4567;
+	in.srs_indication_body.srs_pdu_list[1].rx_ue_information.rnti = 42;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+	CU_ASSERT_EQUAL(in.srs_indication_body.tl.tag, out.srs_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].rx_ue_information.tl.tag, out.srs_indication_body.srs_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].rx_ue_information.handle, out.srs_indication_body.srs_pdu_list[0].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].rx_ue_information.rnti, out.srs_indication_body.srs_pdu_list[0].rx_ue_information.rnti);
+
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.tl.tag, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.doppler_estimation, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.doppler_estimation);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.timing_advance, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.timing_advance);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.number_of_resource_blocks, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.number_of_resource_blocks);
+	CU_ASSERT_EQUAL(memcmp(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.snr, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.snr, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.number_of_resource_blocks), 0);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.rb_start, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel8.rb_start);
+
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.tl.tag, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.timing_advance_r9, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel9.timing_advance_r9);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.tl.tag, out.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.uppts_symbol, out.srs_indication_body.srs_pdu_list[0].srs_indication_tdd_rel10.uppts_symbol);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.tl.tag, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.ul_rtoa, out.srs_indication_body.srs_pdu_list[0].srs_indication_fdd_rel11.ul_rtoa);
+
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.tl.tag, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_prb_per_subband, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_prb_per_subband);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.number_of_subbands, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.number_of_subbands);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_atennas, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.num_atennas);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].subband_index, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].subband_index) 
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].channel[0], out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[0].channel[0]);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].subband_index, out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].subband_index);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].channel[0], out.srs_indication_body.srs_pdu_list[0].tdd_channel_measurement.subands[1].channel[0]);
+
+
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[1].rx_ue_information.tl.tag, out.srs_indication_body.srs_pdu_list[1].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[1].rx_ue_information.handle, out.srs_indication_body.srs_pdu_list[1].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.srs_indication_body.srs_pdu_list[1].rx_ue_information.rnti, out.srs_indication_body.srs_pdu_list[1].rx_ue_information.rnti);
+
+	free(in.srs_indication_body.srs_pdu_list);
+	free(out.srs_indication_body.srs_pdu_list);
+}
+void nfapi_test_rx_sr_indication()
+{
+	nfapi_sr_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_sr_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RX_SR_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10230;
+	in.sr_indication_body.tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
+	in.sr_indication_body.number_of_srs = 2;
+	in.sr_indication_body.sr_pdu_list = (nfapi_sr_indication_pdu_t*)(malloc(sizeof(nfapi_sr_indication_pdu_t) * in.sr_indication_body.number_of_srs));
+	in.sr_indication_body.sr_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.sr_indication_body.sr_pdu_list[0].rx_ue_information.handle = 0x4567;
+	in.sr_indication_body.sr_pdu_list[0].rx_ue_information.rnti = 42;
+
+	in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.ul_cqi = 34;
+	in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.channel = 38;
+
+	in.sr_indication_body.sr_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.sr_indication_body.sr_pdu_list[1].rx_ue_information.handle = 0x9876;
+	in.sr_indication_body.sr_pdu_list[1].rx_ue_information.rnti = 24;
+
+	in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.ul_cqi = 24;
+	in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.channel = 28;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+	CU_ASSERT_EQUAL(in.sr_indication_body.tl.tag, out.sr_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].rx_ue_information.tl.tag, out.sr_indication_body.sr_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].rx_ue_information.handle, out.sr_indication_body.sr_pdu_list[0].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].rx_ue_information.rnti, out.sr_indication_body.sr_pdu_list[0].rx_ue_information.rnti);
+
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.tl.tag, out.sr_indication_body.sr_pdu_list[0].ul_cqi_information.tl.tag);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.ul_cqi, out.sr_indication_body.sr_pdu_list[0].ul_cqi_information.ul_cqi);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[0].ul_cqi_information.channel, out.sr_indication_body.sr_pdu_list[0].ul_cqi_information.channel);
+
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].rx_ue_information.tl.tag, out.sr_indication_body.sr_pdu_list[1].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].rx_ue_information.handle, out.sr_indication_body.sr_pdu_list[1].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].rx_ue_information.rnti, out.sr_indication_body.sr_pdu_list[1].rx_ue_information.rnti);
+
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.tl.tag, out.sr_indication_body.sr_pdu_list[1].ul_cqi_information.tl.tag);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.ul_cqi, out.sr_indication_body.sr_pdu_list[1].ul_cqi_information.ul_cqi);
+	CU_ASSERT_EQUAL(in.sr_indication_body.sr_pdu_list[1].ul_cqi_information.channel, out.sr_indication_body.sr_pdu_list[1].ul_cqi_information.channel);
+
+	free(in.sr_indication_body.sr_pdu_list);
+	free(out.sr_indication_body.sr_pdu_list);
+
+}
+void nfapi_test_rx_cqi_indication()
+{
+	uint8_t cqi_1[] = { 0, 2, 4, 8, 10};
+	uint8_t cqi_2[] = { 100, 101, 102, 103, 104, 105, 106};
+
+	nfapi_cqi_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_cqi_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_RX_CQI_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 10240;
+	in.cqi_indication_body.tl.tag = NFAPI_CQI_INDICATION_BODY_TAG;
+	in.cqi_indication_body.number_of_cqis = 3;
+
+	in.cqi_indication_body.cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)(calloc(1, sizeof(nfapi_cqi_indication_pdu_t)*in.cqi_indication_body.number_of_cqis));
+	in.cqi_indication_body.cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)(calloc(1, sizeof(nfapi_cqi_indication_raw_pdu_t)*in.cqi_indication_body.number_of_cqis));
+
+	in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.handle = 0x4567;
+	in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.rnti = 42;
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.tl.tag = NFAPI_CQI_INDICATION_REL8_TAG;
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.length = sizeof(cqi_1);
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.data_offset = 1;
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ul_cqi = 4;
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ri = 4;
+	in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.timing_advance = 63;
+	in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.ul_cqi = 34;
+	in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.channel = 38;
+
+	in.cqi_indication_body.cqi_pdu_list[1].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.cqi_indication_body.cqi_pdu_list[1].rx_ue_information.handle = 0x4567;
+	in.cqi_indication_body.cqi_pdu_list[1].rx_ue_information.rnti = 42;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.tl.tag = NFAPI_CQI_INDICATION_REL8_TAG;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.length = 0;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.data_offset = 0;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.ul_cqi = 0;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.ri = 0;
+	in.cqi_indication_body.cqi_pdu_list[1].cqi_indication_rel8.timing_advance = 0;
+
+
+	in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.handle = 0x4567;
+	in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.rnti = 42;
+	
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.tl.tag = NFAPI_CQI_INDICATION_REL9_TAG;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.length = sizeof(cqi_2);
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.data_offset = 1;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ul_cqi = 4;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.number_of_cc_reported = 4;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[0] = 6;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[1] = 7;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[2] = 8;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[3] = 1;
+	in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.timing_advance = 63;
+	in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.ul_cqi = 44;
+	in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.channel = 48;
+
+
+	memcpy(in.cqi_indication_body.cqi_raw_pdu_list[0].pdu, cqi_1, sizeof(cqi_1));
+	memcpy(in.cqi_indication_body.cqi_raw_pdu_list[1].pdu, cqi_2, sizeof(cqi_2));
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.tl.tag, out.cqi_indication_body.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.tl.tag, out.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.handle, out.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.rnti, out.cqi_indication_body.cqi_pdu_list[0].rx_ue_information.rnti);
+
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.tl.tag, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.length, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.length);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.data_offset, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.data_offset);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ul_cqi, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ul_cqi);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ri, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.ri);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.timing_advance, out.cqi_indication_body.cqi_pdu_list[0].cqi_indication_rel8.timing_advance);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.tl.tag, out.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.ul_cqi, out.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.ul_cqi);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.channel, out.cqi_indication_body.cqi_pdu_list[0].ul_cqi_information.channel);
+
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.tl.tag, out.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.handle, out.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.handle);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.rnti, out.cqi_indication_body.cqi_pdu_list[2].rx_ue_information.rnti);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.tl.tag, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.length, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.length);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.data_offset, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.data_offset);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ul_cqi, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ul_cqi);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.number_of_cc_reported, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.number_of_cc_reported);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[0], out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[0]);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[1], out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[1]);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[2], out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[2]);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[3], out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.ri[3]);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.timing_advance, out.cqi_indication_body.cqi_pdu_list[2].cqi_indication_rel9.timing_advance);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.tl.tag, out.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.tl.tag);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.ul_cqi, out.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.ul_cqi);
+	CU_ASSERT_EQUAL(in.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.channel, out.cqi_indication_body.cqi_pdu_list[2].ul_cqi_information.channel);
+
+
+	CU_ASSERT_EQUAL(memcmp(in.cqi_indication_body.cqi_raw_pdu_list[0].pdu, out.cqi_indication_body.cqi_raw_pdu_list[0].pdu, sizeof(cqi_1)), 0);
+	CU_ASSERT_EQUAL(memcmp(in.cqi_indication_body.cqi_raw_pdu_list[2].pdu, out.cqi_indication_body.cqi_raw_pdu_list[2].pdu, sizeof(cqi_2)), 0);
+
+	free(in.cqi_indication_body.cqi_pdu_list);
+	free(in.cqi_indication_body.cqi_raw_pdu_list);
+	free(out.cqi_indication_body.cqi_pdu_list);
+	free(out.cqi_indication_body.cqi_raw_pdu_list);
+}
+
+void nfapi_test_lbt_dl_config_request()
+{
+	nfapi_lbt_dl_config_request_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_lbt_dl_config_request_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_LBT_DL_CONFIG_REQUEST;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	//in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 1234;
+	in.lbt_dl_config_request_body.tl.tag = NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG;
+	in.lbt_dl_config_request_body.number_of_pdus = 2;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)(malloc(sizeof(nfapi_lbt_dl_config_request_pdu_t) * in.lbt_dl_config_request_body.number_of_pdus));
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_type = NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_size = 32;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.tl.tag = NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.handle = 0x1234;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.mp_cca = 22;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.n_cca = 23;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.offset = 24;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lte_txop_sf = 25;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.txop_sfn_sf_end = 26;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lbt_mode = 27;
+
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_type = NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_size = 32;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.tl.tag = NFAPI_LBT_DRS_REQ_PDU_REL13_TAG;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.handle = 0x4567;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.offset = 1;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.sfn_sf_end = 2;
+	in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.lbt_mode = 3;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.phy_id, out.header.phy_id);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.header.message_length, out.header.message_length);
+	CU_ASSERT_EQUAL(in.header.m_segment_sequence, out.header.m_segment_sequence);
+	CU_ASSERT_EQUAL(in.header.checksum, out.header.checksum);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.number_of_pdus, out.lbt_dl_config_request_body.number_of_pdus);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_type, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_type);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_size, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].pdu_size);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.tl.tag, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.handle, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.handle);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.mp_cca, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.mp_cca);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.n_cca, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.n_cca);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.offset, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.offset);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lte_txop_sf, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lte_txop_sf);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.txop_sfn_sf_end, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.txop_sfn_sf_end);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lbt_mode, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[0].lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13.lbt_mode);
+
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_type, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_type);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_size, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].pdu_size);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.tl.tag, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.handle, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.handle);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.offset, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.offset);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.sfn_sf_end, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.sfn_sf_end);
+	CU_ASSERT_EQUAL(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.lbt_mode, out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list[1].lbt_drs_req_pdu.lbt_drs_req_pdu_rel13.lbt_mode);
+
+	free(in.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list);
+	free(out.lbt_dl_config_request_body.lbt_dl_config_req_pdu_list);
+}
+
+void nfapi_test_lbt_dl_indication()
+{
+	nfapi_lbt_dl_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_lbt_dl_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_LBT_DL_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	//in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 1234;
+	in.lbt_dl_indication_body.tl.tag = NFAPI_LBT_DL_INDICATION_BODY_TAG;
+	in.lbt_dl_indication_body.number_of_pdus = 2;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)(malloc(sizeof(nfapi_lbt_dl_indication_pdu_t) * in.lbt_dl_indication_body.number_of_pdus));
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_type = NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_size = 32;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.tl.tag = NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.handle = 0x1234;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.result = 22;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.lte_txop_symbols = 23;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.initial_partial_sf = 24;
+
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_type = NFAPI_LBT_DL_RSP_DRS_PDU_TYPE;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_size = 32;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.tl.tag = NFAPI_LBT_DRS_RSP_PDU_REL13_TAG;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.handle = 0x4567;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.result = 1;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.phy_id, out.header.phy_id);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.header.message_length, out.header.message_length);
+	CU_ASSERT_EQUAL(in.header.m_segment_sequence, out.header.m_segment_sequence);
+	CU_ASSERT_EQUAL(in.header.checksum, out.header.checksum);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.number_of_pdus, out.lbt_dl_indication_body.number_of_pdus);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_type, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_type);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_size, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_size);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.tl.tag, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.handle, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.handle);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.result, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.result);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.lte_txop_symbols, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.lte_txop_symbols);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.initial_partial_sf, out.lbt_dl_indication_body.lbt_indication_pdu_list[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.initial_partial_sf);
+
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_type, out.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_type);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_size, out.lbt_dl_indication_body.lbt_indication_pdu_list[1].pdu_size);
+
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.tl.tag, out.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.tl.tag);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.handle, out.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.handle);
+	CU_ASSERT_EQUAL(in.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.result, out.lbt_dl_indication_body.lbt_indication_pdu_list[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.result);
+
+	free(in.lbt_dl_indication_body.lbt_indication_pdu_list);
+	free(out.lbt_dl_indication_body.lbt_indication_pdu_list);
+
+}
+void nfapi_test_lbt_dl_indication_invalid_pdu_type()
+{
+	nfapi_lbt_dl_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_lbt_dl_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_LBT_DL_INDICATION;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	//in.header.checksum = 0xEEEEEEEE;
+
+	in.sfn_sf = 1234;
+	in.lbt_dl_indication_body.tl.tag = NFAPI_LBT_DL_INDICATION_BODY_TAG;
+	in.lbt_dl_indication_body.number_of_pdus = 1;
+	in.lbt_dl_indication_body.lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)(malloc(sizeof(nfapi_lbt_dl_indication_pdu_t) * in.lbt_dl_indication_body.number_of_pdus));
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_type = 44; // Invalid pdu type
+	in.lbt_dl_indication_body.lbt_indication_pdu_list[0].pdu_size = 32;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	int unpack_result = nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(unpack_result, -1);
+	CU_ASSERT_EQUAL(in.header.phy_id, out.header.phy_id);
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.header.message_length, out.header.message_length);
+	CU_ASSERT_EQUAL(in.header.m_segment_sequence, out.header.m_segment_sequence);
+	CU_ASSERT_EQUAL(in.header.checksum, out.header.checksum);
+	CU_ASSERT_EQUAL(in.sfn_sf, out.sfn_sf);
+	free(in.lbt_dl_indication_body.lbt_indication_pdu_list);
+	free(out.lbt_dl_indication_body.lbt_indication_pdu_list);
+}
+
+void nfapi_test_nb_harq_indication()
+{
+	nfapi_nb_harq_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_nb_harq_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_NB_HARQ_INDICATION;
+	in.header.message_length = 0;
+
+	in.sfn_sf = 1234;
+	in.nb_harq_indication_body.tl.tag = NFAPI_NB_HARQ_INDICATION_BODY_TAG;
+	in.nb_harq_indication_body.number_of_harqs = 1;
+	
+	nfapi_nb_harq_indication_pdu_t nb_harq_pdu[1];
+	in.nb_harq_indication_body.nb_harq_pdu_list = &nb_harq_pdu[0];
+	in.nb_harq_indication_body.nb_harq_pdu_list[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+	in.nb_harq_indication_body.nb_harq_pdu_list[0].nb_harq_indication_fdd_rel13.tl.tag = NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG;
+	in.nb_harq_indication_body.nb_harq_pdu_list[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+	
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	IN_OUT_ASSERT(sfn_sf);
+	IN_OUT_ASSERT(nb_harq_indication_body.tl.tag);
+	IN_OUT_ASSERT(nb_harq_indication_body.number_of_harqs);
+	
+	IN_OUT_ASSERT(nb_harq_indication_body.nb_harq_pdu_list[0].rx_ue_information.tl.tag);
+	IN_OUT_ASSERT(nb_harq_indication_body.nb_harq_pdu_list[0].nb_harq_indication_fdd_rel13.tl.tag);
+	IN_OUT_ASSERT(nb_harq_indication_body.nb_harq_pdu_list[0].ul_cqi_information.tl.tag);
+	
+}
+
+void nfapi_test_nrach_indication()
+{
+	nfapi_nrach_indication_t in;
+	memset(&in, 0, sizeof(in));
+	nfapi_nrach_indication_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_NRACH_INDICATION;
+	in.header.message_length = 0;
+
+	in.sfn_sf = 1234;
+	
+	in.nrach_indication_body.tl.tag = NFAPI_NRACH_INDICATION_BODY_TAG;
+	in.nrach_indication_body.number_of_initial_scs_detected = 1;
+	
+	nfapi_nrach_indication_pdu_t nrach_pdu[1];
+	in.nrach_indication_body.nrach_pdu_list = &nrach_pdu[0];
+	
+	in.nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.tl.tag = NFAPI_NRACH_INDICATION_REL13_TAG;
+	
+	
+
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	IN_OUT_ASSERT(sfn_sf);
+	IN_OUT_ASSERT(nrach_indication_body.tl.tag);
+	IN_OUT_ASSERT(nrach_indication_body.number_of_initial_scs_detected);
+	IN_OUT_ASSERT(nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.tl.tag);
+	IN_OUT_ASSERT(nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.rnti);
+	IN_OUT_ASSERT(nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.initial_sc);
+	IN_OUT_ASSERT(nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.timing_advance);
+	IN_OUT_ASSERT(nrach_indication_body.nrach_pdu_list[0].nrach_indication_rel13.nrach_ce_level);	
+	
+}
+
+void nfapi_test_dl_node_sync()
+{
+	nfapi_dl_node_sync_t in;
+	nfapi_dl_node_sync_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_DL_NODE_SYNC;
+	in.header.message_length = 0;
+
+	in.t1 = 10239999;
+	in.delta_sfn_sf = -987;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.t1, out.t1);
+	CU_ASSERT_EQUAL(in.delta_sfn_sf, out.delta_sfn_sf);
+}
+void nfapi_test_ul_node_sync()
+{
+	nfapi_ul_node_sync_t in;
+	nfapi_ul_node_sync_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_UL_NODE_SYNC;
+	in.header.message_length = 0;
+
+	in.t1 = 10239999;
+	in.t2 = 10239999;
+	in.t2 = 10239999;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+	
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.t1, out.t1);
+	CU_ASSERT_EQUAL(in.t2, out.t2);
+	CU_ASSERT_EQUAL(in.t3, out.t3);
+}
+void nfapi_test_timing_info()
+{
+	nfapi_timing_info_t in;
+	nfapi_timing_info_t out;
+
+	in.header.phy_id = NFAPI_PHY_ID_NA;
+	in.header.message_id = NFAPI_TIMING_INFO;
+	in.header.message_length = 0;
+	in.header.m_segment_sequence = 0xDDDD;
+	in.header.checksum = 0xEEEEEEEE;
+
+	in.last_sfn_sf = 0xDEAD; //10239999;
+	in.time_since_last_timing_info = 4294967295u;
+	in.dl_config_jitter = 4294967295u;
+	in.tx_request_jitter = 4294967295u;
+	in.ul_config_jitter = 4294967295u;
+	in.hi_dci0_jitter = 4294967295u;
+	in.dl_config_latest_delay = 0; //-2147483648L;
+	in.tx_request_latest_delay = 2147483647u;
+	in.ul_config_latest_delay = 0; //-2147483648L ;
+	in.hi_dci0_latest_delay =  0; //2147483647u;
+	in.dl_config_earliest_arrival = 0; //-2147483648L;
+	in.tx_request_earliest_arrival = 0; //2147483647u;
+	in.ul_config_earliest_arrival = 0; //2147483648L;
+	in.hi_dci0_earliest_arrival = -0; //2147483647u;
+
+	int packedMessageLength = nfapi_p7_message_pack(&in, gTestNfapiMessageTx, MAX_PACKED_MESSAGE_SIZE, 0);
+
+	nfapi_p7_message_unpack(gTestNfapiMessageTx, packedMessageLength, &out, sizeof(out), 0);
+
+	CU_ASSERT_EQUAL(in.header.message_id, out.header.message_id);
+	CU_ASSERT_EQUAL(in.last_sfn_sf, out.last_sfn_sf);
+	CU_ASSERT_EQUAL(in.time_since_last_timing_info, out.time_since_last_timing_info);
+	CU_ASSERT_EQUAL(in.dl_config_jitter, out.dl_config_jitter);
+	CU_ASSERT_EQUAL(in.tx_request_jitter, out.tx_request_jitter);
+	CU_ASSERT_EQUAL(in.ul_config_jitter, out.ul_config_jitter);
+	CU_ASSERT_EQUAL(in.hi_dci0_jitter, out.hi_dci0_jitter);
+	CU_ASSERT_EQUAL(in.dl_config_latest_delay, out.dl_config_latest_delay);
+	CU_ASSERT_EQUAL(in.tx_request_latest_delay, out.tx_request_latest_delay);
+	CU_ASSERT_EQUAL(in.ul_config_latest_delay, out.ul_config_latest_delay);
+	CU_ASSERT_EQUAL(in.hi_dci0_latest_delay, out.hi_dci0_latest_delay);
+	CU_ASSERT_EQUAL(in.dl_config_earliest_arrival, out.dl_config_earliest_arrival);
+	CU_ASSERT_EQUAL(in.tx_request_earliest_arrival, out.tx_request_earliest_arrival);
+	CU_ASSERT_EQUAL(in.ul_config_earliest_arrival, out.ul_config_earliest_arrival);
+	CU_ASSERT_EQUAL(in.hi_dci0_earliest_arrival, out.hi_dci0_earliest_arrival);
+}
+
+void nfapi_struct_sizes()
+{
+
+	
+	printf("P5\n");
+	printf("nfapi_pnf_param_request %zu\n", sizeof(nfapi_pnf_param_request_t));
+	printf("nfapi_pnf_param_response %zu\n", sizeof(nfapi_pnf_param_response_t));
+	printf("nfapi_pnf_config_request %zu\n", sizeof(nfapi_pnf_config_request_t));
+	printf("nfapi_pnf_config_response %zu\n", sizeof(nfapi_pnf_config_response_t));
+	printf("nfapi_pnf_start_request %zu\n", sizeof(nfapi_pnf_start_request_t));
+	printf("nfapi_pnf_start_response %zu\n", sizeof(nfapi_pnf_start_response_t));
+	printf("nfapi_pnf_stop_request %zu\n", sizeof(nfapi_pnf_stop_request_t));
+	printf("nfapi_pnf_stop_request %zu\n", sizeof(nfapi_pnf_stop_response_t));
+	printf("nfapi_param_request %zu\n", sizeof(nfapi_param_request_t));
+	printf("nfapi_param_response %zu\n", sizeof(nfapi_param_response_t));
+	printf("nfapi_config_request %zu\n", sizeof(nfapi_config_request_t));
+	printf("nfapi_config_response %zu\n", sizeof(nfapi_config_response_t));
+	printf("nfapi_start_request %zu\n", sizeof(nfapi_start_request_t));
+	printf("nfapi_start_response %zu\n", sizeof(nfapi_start_response_t));
+	printf("nfapi_stop_request %zu\n", sizeof(nfapi_stop_request_t));
+	printf("nfapi_stop_response %zu\n", sizeof(nfapi_stop_response_t));
+	printf("nfapi_measurement_request %zu\n", sizeof(nfapi_measurement_request_t));
+	printf("nfapi_measurement_response %zu\n", sizeof(nfapi_measurement_response_t));
+
+	printf("P7\n");
+	printf("nfapi_timing_info_t %zu\n", sizeof(nfapi_timing_info_t));
+	printf("nfapi_dl_config_request_t %zu\n", sizeof(nfapi_dl_config_request_t));
+	printf("nfapi_ul_config_request_t %zu\n", sizeof(nfapi_ul_config_request_t));
+	printf("nfapi_hi_dci0_request_t %zu\n", sizeof(nfapi_hi_dci0_request_t));
+	printf("nfapi_tx_request_t %zu\n", sizeof(nfapi_tx_request_t));
+	printf("nfapi_crc_indication_t %zu\n", sizeof(nfapi_crc_indication_t));
+	printf("nfapi_sr_indication_t %zu\n", sizeof(nfapi_sr_indication_t));
+	printf("nfapi_srs_indication_t %zu\n", sizeof(nfapi_srs_indication_t));
+	printf("nfapi_harq_indication_t %zu\n", sizeof(nfapi_harq_indication_t));
+	printf("nfapi_rx_indication_t %zu\n", sizeof(nfapi_rx_indication_t));
+	printf("nfapi_rach_indication_t %zu\n", sizeof(nfapi_rach_indication_t));
+	printf("nfapi_cqi_indication_t %zu\n", sizeof(nfapi_cqi_indication_t));
+	printf("nfapi_nb_harq_indication_t %zu\n", sizeof(nfapi_nb_harq_indication_t));
+	printf("nfapi_nrach_indication_t %zu\n", sizeof(nfapi_nrach_indication_t));
+	printf("nfapi_lbt_dl_config_request_t %zu\n", sizeof(nfapi_lbt_dl_config_request_t));
+	printf("nfapi_lbt_dl_indication_t %zu\n", sizeof(nfapi_lbt_dl_indication_t));
+
+	printf("P4\n");
+	printf("nfapi_lte_rssi_request_t %zu\n", sizeof(nfapi_lte_rssi_request_t));
+	printf("nfapi_utran_rssi_request_t %zu\n", sizeof(nfapi_utran_rssi_request_t));
+	printf("nfapi_geran_rssi_request_t %zu\n", sizeof(nfapi_geran_rssi_request_t));
+	printf("nfapi_lte_cell_search_request_t %zu\n", sizeof(nfapi_lte_cell_search_request_t));
+	printf("nfapi_utran_cell_search_request_t %zu\n", sizeof(nfapi_utran_cell_search_request_t));
+	printf("nfapi_geran_cell_search_request_t %zu\n", sizeof(nfapi_geran_cell_search_request_t));
+	printf("nfapi_lte_cell_search_indication_t %zu\n", sizeof(nfapi_lte_cell_search_indication_t));
+	printf("nfapi_utran_cell_search_indication_t %zu\n", sizeof(nfapi_utran_cell_search_indication_t));
+	printf("nfapi_geran_cell_search_indication_t %zu\n", sizeof(nfapi_geran_cell_search_indication_t));
+	printf("nfapi_lte_broadcast_detect_request_t %zu\n", sizeof(nfapi_lte_broadcast_detect_request_t));
+	printf("nfapi_utran_broadcast_detect_request_t %zu\n", sizeof(nfapi_utran_broadcast_detect_request_t));
+	printf("nfapi_lte_broadcast_detect_indication_t %zu\n", sizeof(nfapi_lte_broadcast_detect_indication_t));
+	printf("nfapi_utran_broadcast_detect_indication_t %zu\n", sizeof(nfapi_utran_broadcast_detect_indication_t));
+	printf("nfapi_lte_system_information_schedule_request_t %zu\n", sizeof(nfapi_lte_system_information_schedule_request_t));
+	printf("nfapi_lte_system_information_request_t %zu\n", sizeof(nfapi_lte_system_information_request_t));
+	printf("nfapi_utran_system_information_request_t %zu\n", sizeof(nfapi_utran_system_information_request_t));
+	printf("nfapi_geran_system_information_request_t %zu\n", sizeof(nfapi_geran_system_information_request_t));
+	printf("nfapi_lte_system_information_indication_t %zu\n", sizeof(nfapi_lte_system_information_indication_t));
+	printf("nfapi_utran_system_information_indication_t %zu\n", sizeof(nfapi_utran_system_information_indication_t));
+	printf("nfapi_geran_system_information_indication_t %zu\n", sizeof(nfapi_geran_system_information_indication_t));
+}
+
+/************* Test Runner Code goes here **************/
+
+
+int main ( int argc, char** argv)
+{
+
+/*
+        printf("1..3\n");
+        printf("ok 1 - run good\n");	
+        printf("ok 2 - mojojojo\n");	
+        printf("not ok 3 - not implemented\n");	
+	return 0;
+	*/
+
+
+	int i;
+	printf("%d \n", argc);
+	for(i = 0; i < argc; ++i)
+	{
+		if(argv[i] != 0)
+			printf("%s \n", argv[i]);
+	}
+
+	CU_pSuite pSuite = NULL;
+
+	/* initialize the CUnit test registry */
+	if ( CUE_SUCCESS != CU_initialize_registry() )
+		return CU_get_error();
+
+	/* add a suite to the registry */
+	pSuite = CU_add_suite( "nfapi_test_suite", init_suite, clean_suite );
+	if ( NULL == pSuite ) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	/* add the tests to the suite */
+	//if ( (NULL == CU_add_test(pSuite, "nfapi_test_pnf_config_req", nfapi_test_pnf_config_req)) ||
+	//     (NULL == CU_add_test(pSuite, "nfapi_test_2", nfapi_test_2)) 
+	//   )
+	// {
+	//   CU_cleanup_registry();
+	//   return CU_get_error();
+	//}
+
+
+	CU_pSuite pSuiteP4 = CU_add_suite( "nfapi_p4_pack_unpack_test_suite", init_suite, clean_suite );
+	if(pSuiteP4)
+	{
+		if((NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_lte", nfapi_test_rssi_request_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_lte2", nfapi_test_rssi_request_lte2)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_lte_overrun", nfapi_test_rssi_request_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_lte_rat_type_mismatch", nfapi_test_rssi_request_lte_rat_type_mismatch)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_utran", nfapi_test_rssi_request_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_geran", nfapi_test_rssi_request_geran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_request_nb_iot", nfapi_test_rssi_request_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_response", nfapi_test_rssi_response)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_indication", nfapi_test_rssi_indication)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_rssi_indication_overrun", nfapi_test_rssi_indication_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_lte", nfapi_test_cell_search_request_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_lte_overrun", nfapi_test_cell_search_request_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_utran", nfapi_test_cell_search_request_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_utran_overrun", nfapi_test_cell_search_request_utran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_geran", nfapi_test_cell_search_request_geran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_geran_overrun", nfapi_test_cell_search_request_geran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_request_nb_iot", nfapi_test_cell_search_request_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_response", nfapi_test_cell_search_response)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_lte", nfapi_test_cell_search_indication_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_lte_overrun", nfapi_test_cell_search_indication_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_utran", nfapi_test_cell_search_indication_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_utran_overrun", nfapi_test_cell_search_indication_utran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_geran", nfapi_test_cell_search_indication_geran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_geran_overrun", nfapi_test_cell_search_indication_geran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_state_overrun", nfapi_test_cell_search_indication_state_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_cell_search_indication_nb_iot", nfapi_test_cell_search_indication_nb_iot)) ||				
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_request_lte", nfapi_test_broadcast_detect_request_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_request_utran", nfapi_test_broadcast_detect_request_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_request_nb_iot", nfapi_test_broadcast_detect_request_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_request_state_overrun", nfapi_test_broadcast_detect_request_state_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_response", nfapi_test_broadcast_detect_response)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_lte", nfapi_test_broadcast_detect_indication_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_lte_overrun", nfapi_test_broadcast_detect_indication_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_utran", nfapi_test_broadcast_detect_indication_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_utran_overrun", nfapi_test_broadcast_detect_indication_utran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_state_overrun", nfapi_test_broadcast_detect_indication_state_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_broadcast_detect_indication_nb_iot", nfapi_test_broadcast_detect_indication_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_request_lte", nfapi_test_system_information_schedule_request_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_request_state_overrun", nfapi_test_system_information_schedule_request_state_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_request_nb_iot", nfapi_test_system_information_schedule_request_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_response", nfapi_test_system_information_schedule_response)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_indication_lte", nfapi_test_system_information_schedule_indication_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_schedule_indication_nb_iot", nfapi_test_system_information_schedule_indication_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_lte", nfapi_test_system_information_request_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_lte_overrun", nfapi_test_system_information_request_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_utran", nfapi_test_system_information_request_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_geran", nfapi_test_system_information_request_geran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_state_overrun", nfapi_test_system_information_request_state_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_request_nb_iot", nfapi_test_system_information_request_nb_iot)) ||				
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_response", nfapi_test_system_information_response)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_lte", nfapi_test_system_information_indication_lte)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_lte_overrun", nfapi_test_system_information_indication_lte_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_utran", nfapi_test_system_information_indication_utran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_utran_overrun", nfapi_test_system_information_indication_utran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_geran", nfapi_test_system_information_indication_geran)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_geran_overrun", nfapi_test_system_information_indication_geran_overrun)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_system_information_indication_nb_iot", nfapi_test_system_information_indication_nb_iot)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_nmm_stop_request", nfapi_test_nmm_stop_request)) ||
+				(NULL == CU_add_test(pSuiteP4, "nfapi_test_nmm_stop_response", nfapi_test_nmm_stop_response))
+				) 
+				{
+					CU_cleanup_registry();
+					return CU_get_error();
+				}
+	}
+	else
+	{
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	CU_pSuite pSuiteP5 = CU_add_suite( "nfapi_p5_pack_unpack_test_suite", init_suite, clean_suite );
+	if(pSuiteP5)
+	{
+		if((NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_param_request", nfapi_test_pnf_param_request)) ||
+		    (NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_param_request_ve", nfapi_test_pnf_param_request_ve)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_param_response", nfapi_test_pnf_param_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_config_request", nfapi_test_pnf_config_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_config_response", nfapi_test_pnf_config_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_config_response1", nfapi_test_pnf_config_response1)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_start_request", nfapi_test_pnf_start_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_start_response", nfapi_test_pnf_start_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_stop_request", nfapi_test_pnf_stop_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_pnf_stop_request", nfapi_test_pnf_stop_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_param_request", nfapi_test_param_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_param_response", nfapi_test_param_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_config_request", nfapi_test_config_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_config_response", nfapi_test_config_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_start_request", nfapi_test_start_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_start_response", nfapi_test_start_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_stop_request", nfapi_test_stop_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_stop_response", nfapi_test_stop_response)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_measurement_request", nfapi_test_measurement_request)) ||
+			(NULL == CU_add_test(pSuiteP5, "nfapi_test_measurement_response", nfapi_test_measurement_response))
+		  )
+		{
+			CU_cleanup_registry();
+			return CU_get_error();
+		}
+
+	}
+	else
+	{
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+	CU_pSuite pSuiteP7 = CU_add_suite( "nfapi_p7_pack_unpack_test_suite", init_suite, clean_suite );
+	if(pSuiteP7)
+	{
+		if((NULL == CU_add_test(pSuiteP7, "nfapi_test_dl_config_request", nfapi_test_dl_config_request)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_ul_config_request", nfapi_test_ul_config_request)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_hi_dci0_request", nfapi_test_hi_dci0_request)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_tx_request", nfapi_test_tx_request)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_harq_indication", nfapi_test_harq_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_crc_indication", nfapi_test_crc_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_rx_ulsch_indication", nfapi_test_rx_ulsch_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_rach_indication", nfapi_test_rach_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_srs_indication", nfapi_test_srs_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_rx_sr_indication", nfapi_test_rx_sr_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_rx_cqi_indication", nfapi_test_rx_cqi_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_lbt_dl_config_request", nfapi_test_lbt_dl_config_request)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_lbt_dl_indication", nfapi_test_lbt_dl_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_lbt_dl_indication_invalid_pdu_type", nfapi_test_lbt_dl_indication_invalid_pdu_type)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_nb_harq_indication", nfapi_test_nb_harq_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_nrach_indication", nfapi_test_nrach_indication)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_dl_node_sync", nfapi_test_dl_node_sync)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_ul_node_sync", nfapi_test_ul_node_sync)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_test_timing_info", nfapi_test_timing_info)) ||
+			(NULL == CU_add_test(pSuiteP7, "nfapi_struct_sizes", nfapi_struct_sizes))
+		  )
+		{
+			CU_cleanup_registry();
+			return CU_get_error();
+		}
+
+	}
+	else
+	{
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
+
+	// Run all tests using the basic interface
+	CU_basic_set_mode(CU_BRM_VERBOSE);
+	//printf(" CU_basic_set_mode set \n");
+	CU_set_output_filename("nfapi_unit_test_results.xml");
+
+	CU_basic_run_tests();
+	//CU_automated_run_tests();
+
+	//CU_set_test_complete_handler(automated_test_complete_message_handler);
+	//CU_run_all_tests();
+
+	
+	CU_pSuite s = CU_get_registry()->pSuite;
+	int count = 0;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+	printf("%d..%d\n", 1, count);
+
+
+
+	s = CU_get_registry()->pSuite;
+	count = 1;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			int pass = 1;
+			CU_FailureRecord* failures = CU_get_failure_list();
+			while(failures)
+			{
+				if(strcmp(failures->pSuite->pName, s->pName) == 0 &&
+				   strcmp(failures->pTest->pName, t->pName) == 0)
+				{
+					pass = 0;
+					failures = 0;
+				}
+				else
+				{
+					failures = failures->pNext;
+				}
+			}
+
+			if(pass)
+				printf("ok %d - %s:%s\n", count, s->pName, t->pName);
+			else 
+				printf("not ok %d - %s:%s\n", count, s->pName, t->pName);
+
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+	/*
+	s = CU_get_registry()->pSuite;
+	while(s)
+	{
+	   printf("Suite %s\n", s->pName);
+	   CU_pTest t = s->pTest;
+	   while(t)
+	   {
+		   printf(" Test %s\n", t->pName);
+			i//CU_ErrorCode e = CU_basic_run_test(s, t);
+
+		   t = t->pNext;
+	   }
+	   s = s->pNext;
+	}
+	*/
+
+
+
+	//printf("CU_basic_run_tests completed \n");
+	//CU_basic_show_failures(CU_get_failure_list());
+	//printf("CU_basic_show_failures completed\n\n");
+	/*
+	// Run all tests using the automated interface
+	CU_automated_run_tests();
+	CU_list_tests_to_file();
+
+	// Run all tests using the console interface
+	CU_console_run_tests();
+	*/
+	/* Clean up registry and return */
+
+
+	CU_cleanup_registry();
+	return CU_get_error();
+
+}
diff --git a/nfapi/open-nFAPI/pnf/Makefile.am b/nfapi/open-nFAPI/pnf/Makefile.am
new file mode 100644
index 0000000000..663d96b6dd
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AUTOMAKE_OPTIONS=subdir-objects
+
+AM_CPPFLAGS = -I$(top_srcdir)/pnf/inc -I$(top_srcdir)/pnf/public_inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/common/public_inc -g -Wall -Werror
+
+
+noinst_LIBRARIES = libnfapi_pnf.a
+
+libnfapi_pnf_a_SOURCES = src/pnf.c\
+						 src/pnf_interface.c\
+						 src/pnf_p7.c\
+						 src/pnf_p7_interface.c
+
+LDADD = -lsctp
+
+
+
diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h
new file mode 100644
index 0000000000..ab38c66e09
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/inc/pnf.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _PNF_H_
+#define _PNF_H_
+
+#include "nfapi_pnf_interface.h"
+
+#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192
+
+typedef struct {
+
+	nfapi_pnf_config_t _public;
+
+	int p5_sock;
+	uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE];
+
+	uint8_t sctp;
+
+	uint8_t terminate;
+
+} pnf_t;
+
+
+int pnf_connect(pnf_t *pnf);
+int pnf_message_pump(pnf_t *pnf);
+
+int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
+int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
+int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id);
+
+nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, uint16_t phy_id);
+
+#endif // _PNF_H_
+
diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h
new file mode 100644
index 0000000000..3f08d85e6b
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _PNF_P7_H_
+#define _PNF_P7_H_
+
+#define TIMEHR_SEC(_time_hr) ((uint32_t)(_time_hr) >> 20)
+#define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF)
+#define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF))
+
+#include "nfapi_pnf_interface.h"
+
+#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192
+
+typedef struct {
+	uint16_t dl_conf_ontime;
+	uint16_t dl_conf_late;
+	uint16_t ul_conf_ontime;
+	uint16_t ul_conf_late;
+	uint16_t hi_dci0_ontime;
+	uint16_t hi_dci0_late;
+	uint16_t tx_ontime;
+	uint16_t tx_late;
+} pnf_p7_stats_t;
+
+typedef struct {
+	uint8_t* buffer;
+	uint16_t length;
+} pnf_p7_rx_message_segment_t;
+
+typedef struct pnf_p7_rx_message pnf_p7_rx_message_t;
+
+typedef struct pnf_p7_rx_message {
+	uint8_t sequence_number;
+	uint8_t num_segments_received;
+	uint8_t num_segments_expected;
+
+	// the spec allows of upto 128 segments, this does seem excessive
+	pnf_p7_rx_message_segment_t segments[128];
+
+	uint32_t rx_hr_time;
+
+	pnf_p7_rx_message_t* next;
+} pnf_p7_rx_message_t;
+
+typedef struct {
+
+	pnf_p7_rx_message_t* msg_queue;
+
+} pnf_p7_rx_reassembly_queue_t;
+
+
+typedef struct {
+
+	nfapi_pnf_p7_config_t _public;
+
+	//private data
+	int p7_sock;
+
+	uint8_t terminate;
+
+	uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE];
+	uint8_t* rx_message_buffer;
+	uint16_t rx_message_buffer_size;
+
+	pthread_mutex_t mutex; // should we allow the client to specifiy
+	pthread_mutex_t pack_mutex; // should we allow the client to specifiy
+
+	nfapi_pnf_p7_subframe_buffer_t subframe_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/];
+
+	uint32_t sequence_number;
+	uint16_t max_num_segments;
+
+	pnf_p7_rx_reassembly_queue_t reassembly_queue;
+
+	uint8_t* reassemby_buffer;
+	uint32_t reassemby_buffer_size;
+
+	uint16_t sfn_sf;
+	uint32_t sf_start_time_hr;
+	int32_t sfn_sf_shift;
+
+	uint8_t timing_info_period_counter;
+	uint8_t timing_info_aperiodic_send; // 0:false 1:true
+
+	uint32_t timing_info_ms_counter; // number of ms since last timing info
+
+	uint32_t dl_config_jitter;
+	uint32_t ul_config_jitter;
+	uint32_t hi_dci0_jitter;
+	uint32_t tx_jitter;
+
+	uint32_t tick;
+	pnf_p7_stats_t stats;
+
+} pnf_p7_t;
+
+int pnf_p7_message_pump(pnf_p7_t* pnf_p7);
+
+int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len);
+int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len);
+
+
+int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf);
+
+pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len);
+void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg);
+void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta);
+
+#endif /* _PNF_P7_H_ */
+
diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
new file mode 100644
index 0000000000..b25caf2876
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
@@ -0,0 +1,803 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _NFAPI_PNF_INTERFACE_H_
+#define _NFAPI_PNF_INTERFACE_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "nfapi_interface.h"
+#include "debug.h"
+
+#include <sys/types.h>
+
+/*! This enum is used to describe the states of the pnf 
+ */
+typedef enum
+{
+	NFAPI_PNF_IDLE = 0,
+	NFAPI_PNF_CONFIGURED,
+	NFAPI_PNF_RUNNING
+} nfapi_pnf_state_e;
+
+/*! This enum is used to describe the states of a phy instance of a pnf
+ */
+typedef enum
+{
+	NFAPI_PNF_PHY_IDLE = 0,
+	NFAPI_PNF_PHY_CONFIGURED = 1,
+	NFAPI_PNF_PHY_RUNNING = 2
+} nfapi_pnf_phy_state_e;
+
+typedef struct nfapi_pnf_phy_config nfapi_pnf_phy_config_t;
+
+/*! Configuration information for a pnf phy instance
+ */
+typedef struct nfapi_pnf_phy_config
+{
+	/*! The PHY id*/
+	uint16_t phy_id;
+
+	/*! The state of the PNF PHY instance*/
+	nfapi_pnf_phy_state_e state;
+
+	/*! Optional user defined data that will be passed back in the callbacks*/
+	void* user_data;
+
+	/*! Pointer for use in a linked list */
+	struct nfapi_pnf_phy_config* next;
+} nfapi_pnf_phy_config_t;
+
+typedef struct nfapi_pnf_config nfapi_pnf_config_t;
+
+/*! Configuration information for the pnf created by calling nfapi_pnf_create
+ */
+typedef struct nfapi_pnf_config
+{
+	/*! A user define callback to override the default memory allocation 
+	 * \param size The size of the data buffer to allocate
+	 * \return A pointer to a data buffer
+	 */
+	void* (*malloc)(size_t size);
+	
+	/*! A user define callback to override the default memory deallocation 
+	 * \param ptr Pointer to a data buffer to be deallocated
+	 */
+	void (*free)(void* ptr);
+
+	/*! A user define callback to handle trace from the pnf 
+	 * \param level The trace level 
+	 * \param message The trace string
+	 * 
+	 * This is a vardic function.
+	 */
+	void (*trace)(nfapi_trace_level_t  level, const char* message, ...);
+
+	/*! The ip address of the VNF 
+	 *
+	 */
+	char* vnf_ip_addr;
+
+	/*! The ip port of the VNF 
+	 */
+	int vnf_p5_port;
+
+	/*! The state of the PNF */
+	nfapi_pnf_state_e state;
+
+	/*! List of PHY instances configured for this PNF */
+	nfapi_pnf_phy_config_t* phys;
+	
+	/*! Configuation option of the p4 p5 encode decode functions */
+	nfapi_p4_p5_codec_config_t codec_config;
+	
+	/*! Optional user defined data that will be passed back in the callbacks*/
+	void* user_data;
+
+
+	/*! A callback for the PNF_PARAM.request 
+	 *  \param config A pointer to the pnf configuration
+	 *  \param req A data structure for the decoded PNF_PARAM.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the PNF_PARAM.response after receiving the
+	 *  PNF_PARAM.request. This can be done in the call back. 
+	 */
+	int (*pnf_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req);
+	
+	/*! A callback for the PNF_CONFIG.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param req A data structure for the decoded PNF_CONFIG.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the PNF_CONFIG.response after receiving the
+	 *  PNF_CONFIG.request. This can be done in the call back. 
+	 */
+	int (*pnf_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req);
+	
+	/*! A callback for the PNF_START.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param req A data structure for the decoded PNF_CONFIG.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the PNF_START.response after receiving the
+	 *  PNF_START.request. This can be done in the call back. 
+	 */
+	int (*pnf_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req);
+	
+	/*! A callback for the PNF_STOP.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param req A data structure for the decoded PNF_STOP.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the PNF_STOP.response after receiving the
+	 *  PNF_STOP.request. This can be done in the call back. 
+	 */
+	int (*pnf_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_stop_request_t* req);
+
+	/*! A callback for the PARAM.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded PARAM.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the PARAM.response after receiving the
+	 *  PARAM.request. This can be done in the call back. 
+	 */
+	int (*param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req);
+	
+	/*! A callback for the CONFIG.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded CONFIG.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the CONFIG.response after receiving the
+	 *  CONFIG.request. This can be done in the call back. 
+	 */
+	int (*config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req);
+	
+	/*! A callback for the START.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded START.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the START.response after the client has received the
+	 *  first subframe indication from FAPI.
+	 */
+	int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req);
+	
+	/*! A callback for the STOP.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded STOP.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the STOP.response after receiving the
+	 *  STOP.request. This can be done in the call back. 
+	 */
+	int (*stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_stop_request_t* req);
+	
+	/*! A callback for the MEASUREMENT.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded MEASUREMENT.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the MEASUREMENT.response after receiving the
+	 *  MEASUREMENT.request. This can be done in the call back. 
+	 */
+	int (*measurement_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_measurement_request_t* req);
+	
+	/*! A callback for the RSSI.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded RSSI.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the RSSI.response after receiving the
+	 *  RSSI.request. This can be done in the call back. 
+	 */
+	int (*rssi_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_rssi_request_t* req);
+	
+	/*! A callback for the CELL_SEARCH.request
+	 *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded CELL_SEARCH.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the CELL_SEARCH.response after receiving the
+	 *  CELL_SEARCH.request. This can be done in the call back. 	
+	 */
+	int (*cell_search_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_cell_search_request_t* req);
+	
+	/*! A callback for the BROADCAST_DETECT.request
+     *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded BROADCAST_DETECT.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the BROADCAST_DETECT.response after receiving the
+	 *  BROADCAST_DETECT.request. This can be done in the call back. 	
+	 */
+	int (*broadcast_detect_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_broadcast_detect_request_t* req);
+	
+	/*! A callback for the SYSTEM_INFORMATION_SCHEDULE.request
+     *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded SYSTEM_INFORMATION_SCHEDULE.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the SYSTEM_INFORMATION_SCHEDULE.response after receiving the
+	 *  SYSTEM_INFORMATION_SCHEDULE.request. This can be done in the call back. 	
+	 */
+	int (*system_information_schedule_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_schedule_request_t* req);
+	
+	/*! A callback for the SYSTEM_INFORMATION.request
+     *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded SYSTEM_INFORMATION.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the SYSTEM_INFORMATION.response after receiving the
+	 *  SYSTEM_INFORMATION.request. This can be done in the call back. 	
+	 */
+	int (*system_information_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_request_t* req);
+	
+	/*! A callback for the NMM_STOP.request
+     *  \param config A pointer to the pnf configuration
+	 *  \param phy A pointer to the pnf phy configuration
+	 *  \param req A data structure for the decoded NMM_STOP.request. This will have
+	 *             been allocated on the stack
+	 *  \return not currently used
+	 * 
+	 * 	The client is expected to send the NMM_STOP.response after receiving the
+	 *  NMM_STOP.request. This can be done in the call back.
+	 */
+	int (*nmm_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nmm_stop_request_t* req);
+	
+	/*! A callback for any vendor extension messages recevied
+	 *  \param config A pointer to the pnf configuration
+	 *  \param msg A pointer to the decode P4/P5 message
+	 *  \return not current used
+	 */
+	int (*vendor_ext)(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg);
+	
+	/*! A callback to allocate vendor extension message
+	 * \param message_id The message id from the decode P4/P5 message header
+	 * \param msg_size A pointer a the size of the allocated message structure. The callee should set this
+	 * \return A pointer to a allocated P4/P5 message structure
+	 */
+	nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
+	
+	/*! A callback to deallocate vendor extension message 
+	 * \param header A pointer to an P4/P5 message structure
+	 */
+	void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header);
+
+
+
+} nfapi_pnf_config_t;
+
+/*! Create a pnf configuration 
+ *  \return A pointer to a pnf configuration struture
+ * 
+ *  This function will create and initialize a pnf instance. It is expected that 
+ *  the client will set the callback and parameters need before calling nfapi_pnf_start
+ *
+ *  0 will be returned if it fails.
+ * 
+ * \code
+ * nfapi_pnf_config_t* config = nfapi_pnf_config_create(void);
+ * \endcode
+ */
+nfapi_pnf_config_t* nfapi_pnf_config_create(void);
+
+/*! Delete a pnf configuration 
+ * \param config A pointer to a pnf configuraiton
+ * \return 0 is success, -1 for failure
+ */
+int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config);
+
+/*! Start the PNF library. 
+ * \param config A pointer to the pnf configuration
+ * \return 0 is success, -1 for failure
+ * 
+ * This function will not return until nfapi_pnf_stop is called
+ *
+ * \code
+ * // Create the pnf config
+ * nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+ *
+ * // Assumed that the vnf_address and vnf_port are provided over the P9 interface
+ * config->vnf_ip_addr = vnf_address;
+ * config->vnf_p5_port = vnf_port;
+ *
+ * // Set the required callbacks
+ * config->pnf_param_req = &pnf_param_request;
+ * ...
+ * 
+ * // Call start for the PNF to initiate a connection to the VNF
+ * nfai_pnf_start(config);
+ * 
+ * \endcode
+ */
+int nfapi_pnf_start(nfapi_pnf_config_t* config);
+
+/*! Stop the PNF library. 
+ * \param config A pointer to the pnf configuration
+ * \return 0 is success, -1 for failure
+ * 
+ * This function will cause the nfapi_pnf_start function to return
+ */
+int nfapi_pnf_stop(nfapi_pnf_config_t* config);
+
+/*! Send the PNF_PARAM.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp);
+
+/*! Send the PNF_CONFIG.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp);
+
+/*! Send the PNF_START.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp);
+
+/*! Send the PNF_STOP.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp);
+
+/*! Send the PARAM.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp);
+
+/*! Send the CONFIG.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp);
+
+/*! Send the START.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp);
+
+/*! Send the STOP.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp);
+
+/*! Send the MEASUREMENT.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp);
+
+/*! Send the RSSI.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_rssi_resp(nfapi_pnf_config_t* config, nfapi_rssi_response_t* resp);
+
+/*! Send the RSSI.indication
+ * \param config A pointer to a pnf configuraiton
+ * \param ind A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_rssi_ind(nfapi_pnf_config_t* config, nfapi_rssi_indication_t* ind);
+
+/*! Send the CELL_SEARCH.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_cell_search_resp(nfapi_pnf_config_t* config, nfapi_cell_search_response_t* resp);
+
+/*! Send the CELL_SEARCH.indication
+ * \param config A pointer to a pnf configuraiton
+ * \param ind A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_cell_search_ind(nfapi_pnf_config_t* config, nfapi_cell_search_indication_t* ind);
+
+/*! Send the BROADCAST_DETECT.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_broadcast_detect_resp(nfapi_pnf_config_t* config, nfapi_broadcast_detect_response_t* resp);
+
+/*! Send the BROADCAST_DETECT.indication
+ * \param config A pointer to a pnf configuraiton
+ * \param ind A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_broadcast_detect_ind(nfapi_pnf_config_t* config, nfapi_broadcast_detect_indication_t* ind);
+
+/*! Send the SYSTEM_INFORMATION_SCHEDULE.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_system_information_schedule_resp(nfapi_pnf_config_t* config, nfapi_system_information_schedule_response_t* resp);
+
+/*! Send the SYSTEM_INFORMATION_SCHEDULE.indication
+ * \param config A pointer to a pnf configuraiton
+ * \param ind A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_system_information_schedule_ind(nfapi_pnf_config_t* config, nfapi_system_information_schedule_indication_t* ind);
+
+/*! Send the SYSTEM_INFORMATION.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_system_information_resp(nfapi_pnf_config_t* config, nfapi_system_information_response_t* resp);
+
+/*! Send the SYSTEM_INFORMATION.indication
+ * \param config A pointer to a pnf configuraiton
+ * \param ind A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_system_information_ind(nfapi_pnf_config_t* config, nfapi_system_information_indication_t* ind);
+
+/*! Send the NMM_STOP.response
+ * \param config A pointer to a pnf configuraiton
+ * \param resp A pointer to the message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_nmm_stop_resp(nfapi_pnf_config_t* config, nfapi_nmm_stop_response_t* resp);
+
+/*! Send a vendor extension message
+ * \param config A pointer to a pnf configuraiton
+ * \param msg A pointer to the vendor extention message structure
+ * \param msg_len The size of the vendor extention message structure
+ * \return 0 for success, -1 for failure
+ * 
+ */
+int nfapi_pnf_vendor_extension(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
+
+//--------------------------
+
+/*! A subframe buffer structure which can be used by the client to 
+ *  to configure the dummy information
+ */
+typedef struct 
+{
+	uint16_t sfn_sf;
+	
+	nfapi_dl_config_request_t* dl_config_req;
+	nfapi_ul_config_request_t* ul_config_req;
+	nfapi_hi_dci0_request_t* hi_dci0_req;
+	nfapi_tx_request_t* tx_req;
+	nfapi_lbt_dl_config_request_t* lbt_dl_config_req;
+
+} nfapi_pnf_p7_subframe_buffer_t;
+
+typedef struct nfapi_pnf_p7_config nfapi_pnf_p7_config_t;
+
+/*! The nfapi PNF PHY P7 configuration information created using the nfapi_pnf_p7_create function
+ */
+typedef struct nfapi_pnf_p7_config
+{
+	/*! A user define callback to override the default memory allocation 
+	 * \param size The size of the buffer to allocate
+	 * \return An allocated buffer. 0 in the case of failure
+	 * 
+	 * If not set malloc will be used
+	 */
+	void* (*malloc)(size_t size);
+	
+	/*! A user define callback to override the default memory deallocation 
+	 *  \param ptr Pointer to a buffer to dellocate
+	 *
+	 * If not set free will be used
+	 */
+	void (*free)(void* ptr);
+
+	/*! A user define callback to handle trace from the pnf
+	 * \param level The trace level
+	 * \param message The message string
+	 */
+	void (*trace)(nfapi_trace_level_t  level, const char* message, ...);
+
+	/*! The PHY id*/
+	uint16_t phy_id;
+
+	// remote
+	/*! The VNF P7 UDP port */
+	int remote_p7_port;
+	/*! The VNF P7 UDP address */
+	char* remote_p7_addr;
+
+	// local
+	/*! The PNF P7 UDP port */
+	int local_p7_port;
+	/*! The PNF P7 UDP address */
+	char* local_p7_addr;
+
+	/*! Flag to indicate of the pnf should use the P7 checksum */
+	uint8_t checksum_enabled;
+
+	/*! The maxium size of a P7 segement. If a message is large that this it
+	 * will be segemented */
+	uint16_t segment_size;
+
+	/*! The dummy subframe buffer structure that should be used in case there
+	 * are no 'valid' subframe messages */
+	nfapi_pnf_p7_subframe_buffer_t dummy_subframe;
+	
+	/*! Configuration options for the p7 pack unpack functions*/
+	nfapi_p7_codec_config_t codec_config;
+	
+	/*! Optional userdata that will be passed back in the callbacks*/
+	void* user_data;
+
+	// tdb : if these should be public
+	uint16_t subframe_buffer_size;
+	uint8_t timing_info_mode_periodic; // 0:false 1:true
+	uint8_t timing_info_mode_aperiodic; // 0:false 1:true
+	uint8_t timing_info_period; // 1..225 in subframes
+
+	/*! A callback for the DL_CONFIG.request
+	 * \param config A poiner to the PNF P7 config
+	 * \param req A pointer to the dl config request message structure
+	 * \return not currently used
+	 */
+	int (*dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req);
+	
+	/*! A callback for the UL_CONFIG.request
+	 * \param config A poiner to the PNF P7 config
+	 * \param req A pointer to the ul config request message structure
+	 * \return not currently used	
+	 */
+	int (*ul_config_req)(nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req);
+	
+	/*! A callback for the HI_DCI0.request
+	 * \param config A poiner to the PNF P7 config
+	 * \param req A pointer to the hi dci0 request message structure
+	 * \return not currently used
+	 */
+	int (*hi_dci0_req)(nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req);
+	
+	/*! A callback for the TX_REQ.request
+	 * \param config A poiner to the PNF P7 config
+	 * \param req A pointer to the tx request message structure
+	 * \return not currently used
+	 * 
+	 * The TX request contains pointers to the downlink PDUs to be sent. In the case that the FAPI interface
+	 * will 'keep' the pointers until they are transmitted the callee should set the pointers in the req to 0
+	 * and then use the p7 codec config free function to release the pdu's when appropriate. 
+	 */
+	int (*tx_req)(nfapi_pnf_p7_config_t* config, nfapi_tx_request_t* req);
+	
+	/*! A callback for the LBT_DL_CONFIG.request
+	 * \param config A poiner to the PNF P7 config
+	 * \param req A pointer to the lbt dl request message structure
+	 * \return not currently used
+	 */
+	int (*lbt_dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req);
+	
+	/*! A callback for vendor extension messages
+	 * \param config A poiner to the PNF P7 config
+	 * \param msg A pointer to a decode vendor extention message
+	 * \return not currently used
+	 */
+	int (*vendor_ext)(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
+
+	/*! A callback to allocate vendor extension message
+	 * \param message_id The vendor extention message id from the decode message header
+	 * \param msg_size A pointer to size of the allocate vendor extention message. Set by the callee
+	 * \return A pointer to an allocated vendor extention message structure. 0 if failed
+	 * 
+	 * 
+	 */
+	nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
+	
+	/*! A callback to deallocate vendor extension message
+	 * \param header A pointer to a p7 vendor extention message
+	 */
+	void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header);
+
+
+
+} nfapi_pnf_p7_config_t;
+
+/*! Create and initialise a nfapi_pnf_p7_config structure
+ * \return A pointer to a PNF P7 config structure
+ */
+nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create(void);
+
+/*! Delete an nfapi_pnf_p7_config structure
+ * \param config 
+ */
+int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config);
+
+
+/*! Start the PNF P7 library. 
+ * \param config A pointer to a PNF P7 config
+ * \return 0 means success, -1 means failure
+ * 
+ * This function will not return until nfapi_pnf_p7_stop is called.
+ */
+int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config);
+
+/*! Stop the PNF P7 library. 
+ * \param config A pointer to a PNF P7 config
+ * \return  0 means success, -1 means failure
+ * 
+ * This function will cause the nfapi_pnf_p7_start to return
+ */
+int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config);
+
+/*! Subframe indication
+ * \param config A pointer to a PNF P7 config
+ * \param phy_id The phy_id for the phy instance
+ * \param sfn_sf The SFN and SF in the format of FAPI
+ * \return 0 means success, -1 means failure
+ * 
+ * The client should call the subframe indication every 1ms. The PNF will
+ * respond by invoking the pnf p7 subframe callbacks with the messages from the subframe buffer
+ *
+ * If messages are not in the subframe buffer, they dummy subframe messages will be sent
+ */
+int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf);
+
+/*! Send the HARQ.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the harq indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_harq_indication_t* ind);
+
+/*! Send the CRC.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the crc indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_crc_indication_t* ind);
+
+/*! Send the RX.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the rx indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_rx_ind(nfapi_pnf_p7_config_t* config, nfapi_rx_indication_t* ind);
+
+/*! Send the RACH.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the rach indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t* ind);
+
+/*! Send the SRS.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the srs indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind);
+
+/*! Send the SR.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the sr indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind);
+
+/*! Send the CQI.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the cqi indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_cqi_ind(nfapi_pnf_p7_config_t* config, nfapi_cqi_indication_t* ind);
+
+/*! Send the LBT_DL.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the lbt dl indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_lbt_dl_ind(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_indication_t* ind);
+
+/*! Send the NB_HARQ.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the lbt dl indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_nb_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind);
+
+/*! Send the NRACH.indication
+ * \param config A pointer to a PNF P7 config
+ * \param ind A pointer to the lbt dl indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t* config, nfapi_nrach_indication_t* ind);
+
+
+/*! Send a vendor exntesion message
+ * \param config A pointer to a PNF P7 config
+ * \param msg A pointer to the lbt dl indication message structure
+ * \return 0 means success, -1 means failure
+ */
+int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // _NFAPI_PNF_INTERFACE_H_
diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c
new file mode 100644
index 0000000000..d0a7fa6fd1
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/src/pnf.c
@@ -0,0 +1,1598 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "pnf.h"
+
+#define MAX_SCTP_STREAMS 16
+
+void nfapi_pnf_phy_config_delete_all(nfapi_pnf_config_t* config)
+{
+	nfapi_pnf_phy_config_t* curr = config->phys;
+	while(curr != 0)
+	{
+		nfapi_pnf_phy_config_t* to_delete = curr;
+		curr = curr->next;
+		free(to_delete);
+	}
+
+	config->phys = 0;
+}
+
+void nfapi_pnf_phy_config_add(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy)
+{
+	phy->next = config->phys;
+	config->phys = phy;
+}
+
+nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, uint16_t phy_id)
+{
+	nfapi_pnf_phy_config_t* curr = config->phys;
+	while(curr != 0)
+	{
+		if(curr->phy_id == phy_id)
+			return curr;
+
+		curr = curr->next;
+	}
+	return 0;
+}
+
+void pnf_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_pnf_param_request_t req;
+		
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n");
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_pnf_param_request_t), &pnf->_public.codec_config) >= 0)
+		{
+			if(pnf->_public.state == NFAPI_PNF_IDLE)
+			{
+				if(pnf->_public.pnf_param_req)
+				{
+					(pnf->_public.pnf_param_req)(&pnf->_public, &req);
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in IDLE state\n", __FUNCTION__);
+		
+				nfapi_pnf_param_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_pnf_param_resp(&pnf->_public, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+
+
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_pnf_config_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n");
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
+		{
+			// ensure correct state
+			if(pnf->_public.state != NFAPI_PNF_RUNNING)
+			{
+				// delete the phy records
+				nfapi_pnf_phy_config_delete_all(&pnf->_public);
+		
+				// create the phy records
+				if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG)
+				{
+					int i = 0;
+					for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i)
+					{
+						nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t));
+						memset(phy, 0, sizeof(nfapi_pnf_phy_config_t));
+		
+						phy->state = NFAPI_PNF_PHY_IDLE;
+						phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id;
+		
+						nfapi_pnf_phy_config_add(&(pnf->_public), phy);
+					}
+				}
+		
+				if(pnf->_public.pnf_config_req)
+				{
+					(pnf->_public.pnf_config_req)(&(pnf->_public), &req);
+				}
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in correct state: %d\n", __FUNCTION__, pnf->_public.state);
+		
+				nfapi_pnf_config_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_pnf_config_resp(&(pnf->_public), &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_pnf_start_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n");
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
+		{
+			if(pnf->_public.state == NFAPI_PNF_CONFIGURED)
+			{
+				if(pnf->_public.pnf_start_req)
+				{
+					(pnf->_public.pnf_start_req)(&(pnf->_public), &req);
+				}
+			}
+			else
+			{
+				nfapi_pnf_start_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_PNF_START_RESPONSE;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_pnf_start_resp(&(pnf->_public), &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_pnf_stop_request_t req;
+		
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_STOP.request Received\n");
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0)
+		{
+			if(pnf->_public.state == NFAPI_PNF_RUNNING)
+			{
+				if(pnf->_public.pnf_stop_req)
+				{
+					(pnf->_public.pnf_stop_req)(&(pnf->_public), &req);
+				}
+			}
+			else
+			{
+				nfapi_pnf_stop_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_pnf_stop_resp(&(pnf->_public), &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_param_request_t req;
+		
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n");
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_IDLE)
+					{
+						if(config->param_req)
+						{
+							(config->param_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_param_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_PARAM_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_param_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_param_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_PARAM_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_param_resp(config, &resp);
+				}
+		
+			}
+			else
+			{
+				nfapi_param_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_PARAM_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_param_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+
+	}
+}
+
+void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_config_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "CONFIG.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state != NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->config_req)
+						{
+							(config->config_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_config_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_config_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_config_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_config_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_config_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_config_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_start_request_t req;
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state);
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state != NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->start_req)
+						{
+							(config->start_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_start_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_START_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_start_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_start_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_START_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_start_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_start_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_START_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_start_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+
+	}
+}
+
+void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_stop_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state != NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->stop_req)
+						{
+							(config->stop_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_stop_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_STOP_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_stop_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_stop_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_STOP_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_stop_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_stop_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_STOP_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_stop_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+			
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	
+	}
+}
+
+void pnf_handle_measurement_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_measurement_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "MEASUREMENT.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state != NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->measurement_req)
+						{
+							(config->measurement_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_measurement_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_measurement_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_measurement_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_measurement_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_measurement_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_measurement_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_rssi_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+
+
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{	
+		nfapi_rssi_request_t req;
+		
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "RSSI.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->rssi_req)
+						{
+							(config->rssi_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_rssi_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_RSSI_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_rssi_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_rssi_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_RSSI_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_rssi_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_rssi_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_RSSI_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_rssi_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	
+	}
+}
+
+void pnf_handle_cell_search_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_cell_search_request_t req;
+		
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "CELL_SEARCH.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->cell_search_req)
+						{
+							(config->cell_search_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_cell_search_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_cell_search_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_cell_search_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_cell_search_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_cell_search_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_cell_search_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+
+}
+
+void pnf_handle_broadcast_detect_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_broadcast_detect_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "BROADCAST_DETECT.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->broadcast_detect_req)
+						{
+							(config->broadcast_detect_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_broadcast_detect_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_broadcast_detect_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_broadcast_detect_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_broadcast_detect_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_broadcast_detect_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_broadcast_detect_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+
+	}
+}
+
+void pnf_handle_system_information_schedule_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_system_information_schedule_request_t req;
+	
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "SYSTEM_INFORMATION_SCHEDULE.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->system_information_schedule_req)
+						{
+							(config->system_information_schedule_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_system_information_schedule_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_system_information_schedule_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_system_information_schedule_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_system_information_schedule_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_system_information_schedule_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_system_information_schedule_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+void pnf_handle_system_information_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_system_information_request_t req;
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "SYSTEM_INFORMATION.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state == NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->system_information_req)
+						{
+							(config->system_information_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_system_information_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_system_information_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_system_information_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_system_information_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_system_information_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_system_information_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+
+}
+
+void pnf_handle_nmm_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_nmm_stop_request_t req;
+		
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "NMM_STOP.request received\n");
+	
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0)
+		{
+			if(config->state == NFAPI_PNF_RUNNING)
+			{
+				nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
+				if(phy)
+				{
+					if(phy->state != NFAPI_PNF_PHY_RUNNING)
+					{
+						if(config->nmm_stop_req)
+						{
+							(config->nmm_stop_req)(config, phy, &req);
+						}
+					}
+					else
+					{
+						nfapi_nmm_stop_response_t resp;
+						memset(&resp, 0, sizeof(resp));
+						resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
+						resp.header.phy_id = req.header.phy_id;
+						resp.error_code = NFAPI_MSG_INVALID_STATE;
+						nfapi_pnf_nmm_stop_resp(config, &resp);
+					}
+				}
+				else
+				{
+					nfapi_nmm_stop_response_t resp;
+					memset(&resp, 0, sizeof(resp));
+					resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
+					resp.header.phy_id = req.header.phy_id;
+					resp.error_code = NFAPI_MSG_INVALID_CONFIG;
+					nfapi_pnf_nmm_stop_resp(config, &resp);
+				}
+			}
+			else
+			{
+				nfapi_nmm_stop_response_t resp;
+				memset(&resp, 0, sizeof(resp));
+				resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
+				resp.header.phy_id = req.header.phy_id;
+				resp.error_code = NFAPI_MSG_INVALID_STATE;
+				nfapi_pnf_nmm_stop_resp(config, &resp);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		if(req.vendor_extension)
+			pnf->_public.codec_config.deallocate(req.vendor_extension);
+	}
+}
+
+
+void pnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_t* pnf, uint16_t message_id)
+{
+	if (pRecvMsg == NULL || pnf == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_pnf_config_t* config = &(pnf->_public);
+	
+		if(config->allocate_p4_p5_vendor_ext)
+		{
+			uint16_t msg_size;
+			nfapi_p4_p5_message_header_t* msg = config->allocate_p4_p5_vendor_ext(message_id, &msg_size);
+	
+			if(msg == 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n");
+				return;
+			}
+	
+			
+			int unpack_result = nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &config->codec_config);
+	
+			if(unpack_result == 0)
+			{
+				if(config->vendor_ext)
+					config->vendor_ext(config, msg);
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+			}
+			
+			if(config->deallocate_p4_p5_vendor_ext)
+				config->deallocate_p4_p5_vendor_ext(msg);
+			
+		}
+	}
+}
+
+
+
+void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+{
+	nfapi_p4_p5_message_header_t messageHeader;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &pnf->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	switch (messageHeader.message_id)
+	{
+		case NFAPI_PNF_PARAM_REQUEST:
+			pnf_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_PNF_CONFIG_REQUEST:
+			pnf_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_PNF_START_REQUEST:
+			pnf_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_PNF_STOP_REQUEST:
+			pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_PARAM_REQUEST:
+			pnf_handle_param_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_CONFIG_REQUEST:
+			pnf_handle_config_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_START_REQUEST:
+			pnf_handle_start_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_STOP_REQUEST:
+			pnf_handle_stop_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_MEASUREMENT_REQUEST:
+			pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_RSSI_REQUEST:
+			pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_CELL_SEARCH_REQUEST:
+			pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_REQUEST:
+			pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST:
+			pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_REQUEST:
+			pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		case NFAPI_NMM_STOP_REQUEST:
+			pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen);
+			break;
+
+		default:
+			{
+				if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id);
+				}
+			}
+			break;
+	}
+}
+
+int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len)
+{
+	int packed_len = nfapi_p5_message_pack(msg, msg_len,
+										   pnf->tx_message_buffer, 
+										   sizeof(pnf->tx_message_buffer), 
+										   &pnf->_public.codec_config);
+
+	if (packed_len < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len);
+		return -1;
+	}
+
+	return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/);
+}
+
+int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len)
+{
+	int packed_len = nfapi_p4_message_pack(msg, msg_len,
+										   pnf->tx_message_buffer, 
+										   sizeof(pnf->tx_message_buffer), 
+										   &pnf->_public.codec_config);
+
+	if (packed_len < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p4_message_pack failed (%d)\n", packed_len);
+		return -1;
+	}
+
+	return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/);
+}
+
+
+
+int pnf_connect(pnf_t* pnf)
+{
+	struct sockaddr_in servaddr;
+	uint8_t socketConnected = 0;
+
+	if(pnf->_public.vnf_ip_addr == 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnfIpAddress is null\n");
+		return -1;
+	}
+
+
+	(void)memset(&servaddr, 0, sizeof(struct sockaddr_in));
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 PNF connection to VNF at %s:%u\n", pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port);
+
+	// todo split the vnf address list. currently only supporting 1
+	
+	struct addrinfo hints, *servinfo;
+	memset(&hints, 0, sizeof(hints));
+
+	hints.ai_socktype = SOCK_STREAM; // For SCTP we are only interested in SOCK_STREAM
+	// todo : allow the client to restrict IPV4 or IPV6
+		// todo : randomize which address to connect to?
+	
+	char port_str[8];
+	snprintf(port_str, sizeof(port_str), "%d", pnf->_public.vnf_p5_port);
+	if(getaddrinfo(pnf->_public.vnf_ip_addr, port_str,  &hints, &servinfo) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to get host (%s) addr info h_errno:%d \n", pnf->_public.vnf_ip_addr, h_errno);
+		return -1;
+	}
+
+	struct addrinfo *p = servinfo;
+	int i = 0;
+	int connected = 0;
+
+	while(p != NULL && connected == 0)
+	{
+		char* family = "Unknown";
+		char* address = "Unknown";
+		char _addr[128];
+		
+		if(p->ai_family == AF_INET6)
+		{
+			family = "IPV6";
+			struct sockaddr_in6* addr = (struct sockaddr_in6*)p->ai_addr;
+			inet_ntop(AF_INET6, &addr->sin6_addr, _addr, sizeof(_addr));
+			address = &_addr[0];
+		}
+		else if(p->ai_family == AF_INET)
+		{
+			family = "IPV4";
+			struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr;
+			address = inet_ntoa(addr->sin_addr);
+		}
+
+		NFAPI_TRACE(NFAPI_TRACE_NOTE, "Host address info  %d Family:%s Address:%s\n", i++, family, address);
+
+		if (pnf->sctp)
+		{
+			// open the SCTP socket
+			if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_SCTP)) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
+				freeaddrinfo(servinfo);
+				return -1;
+			}
+			int noDelay;
+			struct sctp_initmsg initMsg;
+
+			(void)memset(&initMsg, 0, sizeof(struct sctp_initmsg));
+
+			// configure the socket options
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF Setting the SCTP_INITMSG\n");
+			initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS;  // number of output streams can be greater
+			initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS;  // number of output streams can be greater
+			if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
+				freeaddrinfo(servinfo);
+				return -1;
+			}
+			noDelay = 1;
+			if (setsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
+				freeaddrinfo(servinfo);
+				return -1;
+
+			}
+
+			struct sctp_event_subscribe events;
+			memset( (void *)&events, 0, sizeof(events) );
+			events.sctp_data_io_event = 1;
+
+			if(setsockopt(pnf->p5_sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
+				freeaddrinfo(servinfo);
+				return -1;
+			}
+		}
+		else
+		{
+			// Create an IP socket point 
+			if ((pnf->p5_sock = socket(p->ai_family, SOCK_STREAM, IPPROTO_IP)) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
+				freeaddrinfo(servinfo);
+				return -1;
+			}
+		}
+	
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created...\n");
+	
+		if (connect(pnf->p5_sock, p->ai_addr, p->ai_addrlen ) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After connect (address:%s port:%d) errno: %d\n", 
+					pnf->_public.vnf_ip_addr, pnf->_public.vnf_p5_port, errno);
+
+			if(errno == EINVAL)
+			{
+				freeaddrinfo(servinfo);
+				return -1;
+			}
+			else
+			{
+				if(pnf->terminate != 0)
+				{
+					freeaddrinfo(servinfo);
+					return 0;
+				}
+				else
+				{
+					close(pnf->p5_sock);
+					sleep(1);
+				}
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "connect succeeded...\n");
+
+			connected = 1;
+		}
+
+		p = p->ai_next;
+	}
+
+	freeaddrinfo(servinfo);
+
+	// If we have failed to connect return 0 and it is retry
+	if(connected == 0)
+		return 0;
+
+
+	NFAPI_TRACE(NFAPI_TRACE_NOTE, "After connect loop\n");
+	if (pnf->sctp)
+	{
+		socklen_t optLen;
+		struct sctp_status status;
+
+		(void)memset(&status, 0, sizeof(struct sctp_status));
+
+		// check the connection status
+		optLen = (socklen_t) sizeof(struct sctp_status);
+		if (getsockopt(pnf->p5_sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
+			return -1;
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Association ID = %d\n", status.sstat_assoc_id);
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Receiver window size = %d\n", status.sstat_rwnd);
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "In Streams = %d\n",  status.sstat_instrms);
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Out Streams = %d\n", status.sstat_outstrms);
+
+			socketConnected = 1;
+		}
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_NOTE, "Socket %s\n", socketConnected ? "CONNECTED" : "NOT_CONNECTED");
+	return socketConnected;
+}
+
+int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream)
+{
+	if (pnf->sctp)
+	{
+		if (sctp_sendmsg(pnf->p5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno);
+			return -1;
+		}
+	}
+	else
+	{
+		if (write(pnf->p5_sock, msg, len) != len)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "read failed errno: %d\n", errno);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+int pnf_read_dispatch_message(pnf_t* pnf)
+{
+	int socket_connected = 1;
+
+	// 1. Peek the message header
+	// 2. If the message is larger than the stack buffer then create a dynamic buffer
+	// 3. Read the buffer
+	// 4. Handle the p5 message
+
+	uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+	uint8_t header_buffer[header_buffer_size];
+
+	uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure
+	uint8_t stack_buffer[stack_buffer_size];
+
+	uint8_t* dynamic_buffer = 0;
+
+	uint8_t* read_buffer = &stack_buffer[0];
+	uint32_t message_size = 0;
+
+	struct sockaddr_in addr;
+	socklen_t addr_len = sizeof(addr);
+
+	struct sctp_sndrcvinfo sndrcvinfo;
+	(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+
+	{
+		int flags = MSG_PEEK;
+		message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, /*(struct sockaddr*)&addr, &addr_len*/ 0, 0, &sndrcvinfo,  &flags);
+
+		if(message_size == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno);
+			return 0;
+		}
+
+		nfapi_p4_p5_message_header_t header;
+		int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0);
+		if(unpack_result < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n");
+			return 0;
+		}
+		message_size = header.message_length;
+
+		// now have the size of the mesage
+	}
+
+	if(message_size > stack_buffer_size)
+	{
+		dynamic_buffer = (uint8_t*)malloc(message_size);
+
+		if(dynamic_buffer == NULL)
+		{
+			// todo : add error mesage
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size);
+			return -1;
+		}
+
+		read_buffer = dynamic_buffer;
+	}
+
+	{
+		int flags = 0;
+		(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+
+		int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags);
+		if(recvmsg_result == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno);
+		}
+		else
+		{
+			if (flags & MSG_NOTIFICATION)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+
+				// todo - handle the events
+			}
+			else
+			{
+				/*
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n",
+						pnf->p5_sock,
+						inet_ntoa(addr.sin_addr),
+						ntohs(addr.sin_port),
+						sndrcvinfo.sinfo_assoc_id,
+						sndrcvinfo.sinfo_stream,
+						ntohl(sndrcvinfo.sinfo_ppid),
+						message_size,
+						flags);
+				*/
+
+				// handle now if complete message in one or more segments
+				if ((flags & 0x80) == 0x80)
+				{
+					pnf_handle_p5_message(pnf, read_buffer, message_size);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags);
+
+					// assume socket disconnected
+					NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n");
+					socket_connected =  0;
+				}
+
+
+			}
+		}
+	}
+
+	if(dynamic_buffer)
+	{
+		free(dynamic_buffer);
+	}
+
+	return socket_connected;
+
+
+}
+
+
+int pnf_message_pump(pnf_t* pnf)
+{
+	uint8_t socketConnected = 1;
+
+	while(socketConnected && pnf->terminate == 0)
+	{
+		fd_set rfds;
+		int selectRetval = 0;
+
+		// select on a timeout and then get the message
+		FD_ZERO(&rfds);
+		FD_SET(pnf->p5_sock, &rfds);
+
+		struct timeval timeout;
+		timeout.tv_sec = 1;
+		timeout.tv_usec = 0;
+
+		selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout);
+
+		if(selectRetval == 0)
+		{	
+			// timeout
+			continue;
+		}
+		else if (selectRetval == -1 && (errno == EINTR))
+		{
+			// interrupted by signal
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno);
+			continue;
+		}
+		else if (selectRetval == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n");
+			sleep(1);
+			continue;
+		}
+
+		if(FD_ISSET(pnf->p5_sock, &rfds))
+		{
+			socketConnected = pnf_read_dispatch_message(pnf);
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n");
+		}
+	}
+
+	// Drop back to idle if we have lost connection
+	pnf->_public.state = NFAPI_PNF_PHY_IDLE;
+
+
+	// close the connection and socket
+	if (close(pnf->p5_sock) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno);
+	}
+
+	return 0;
+
+}
+
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c
new file mode 100644
index 0000000000..7310fc0c66
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "pnf.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+nfapi_pnf_config_t* nfapi_pnf_config_create()
+{
+	pnf_t* _this = (pnf_t*)malloc(sizeof(pnf_t));
+
+	if(_this == 0)
+		return 0;
+
+	memset(_this, 0, sizeof(pnf_t));
+
+	_this->sctp = 1;	// enable sctp
+	
+	_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
+	
+	_this->_public.malloc = &malloc;
+	_this->_public.free = &free;	
+
+	_this->_public.codec_config.allocate = &malloc;
+	_this->_public.codec_config.deallocate = &free;
+
+	return &(_this->_public);
+}
+
+void nfapi_pnf_config_destory(nfapi_pnf_config_t* config)
+{
+	free(config);
+}
+
+int nfapi_pnf_start(nfapi_pnf_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+	// Make sure to set the defined trace function before using NFAPI_TRACE
+	if(config->trace)
+		nfapi_trace_g = config->trace;
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	while (_this->terminate == 0)
+	{
+		int connect_result = pnf_connect(_this);
+
+		if(connect_result > 0)
+		{
+			pnf_message_pump(_this);
+		}
+		else if(connect_result < 0)
+		{
+			return connect_result;
+		}
+
+		sleep(1);
+	}
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__);
+
+	return 0;
+}
+
+int nfapi_pnf_stop(nfapi_pnf_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+
+	pnf_t* _this = (pnf_t*)(config);
+	_this->terminate = 1;
+
+	// todo wait for the pnf to stop before returning
+
+	return 0;
+}
+
+int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp)
+{
+	// ensure it's valid
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_param_response_t));
+}
+
+int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp)
+{
+	// ensure it's valid
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	if(resp->error_code == NFAPI_MSG_OK)
+	{
+		config->state = NFAPI_PNF_CONFIGURED;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_config_response_t));
+}
+
+int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp)
+{
+	// ensure it's valid
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	if(resp->error_code == NFAPI_MSG_OK)
+	{
+		config->state = NFAPI_PNF_RUNNING;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_start_response_t));
+}
+
+int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp)
+{
+	// ensure it's valid
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	if(resp->error_code == NFAPI_MSG_OK)
+	{
+		config->state = NFAPI_PNF_CONFIGURED;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_stop_response_t));
+}
+
+int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+	
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_param_response_t));
+}
+
+int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
+
+	if(phy)
+	{
+		if(resp->error_code == NFAPI_MSG_OK)
+		{
+			phy->state = NFAPI_PNF_PHY_CONFIGURED;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
+		return -1;
+	}
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_config_response_t));
+}
+
+int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
+	if(phy)
+	{
+		if(resp->error_code == NFAPI_MSG_OK)
+		{
+			phy->state = NFAPI_PNF_PHY_RUNNING;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id);
+		return -1;
+	}
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_start_response_t));
+}
+
+int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id);
+	if(phy)
+	{
+		if(resp->error_code == NFAPI_MSG_OK)
+		{
+			phy->state = NFAPI_PNF_PHY_CONFIGURED;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id);
+		return -1;
+	}
+
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t));
+}
+
+int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_measurement_response_t));
+}
+
+
+int nfapi_pnf_rssi_resp(nfapi_pnf_config_t* config, nfapi_rssi_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_rssi_response_t));
+}
+
+int nfapi_pnf_rssi_ind(nfapi_pnf_config_t* config, nfapi_rssi_indication_t* ind)
+{
+	if (config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_rssi_indication_t));
+}
+int nfapi_pnf_cell_search_resp(nfapi_pnf_config_t* config, nfapi_cell_search_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Send CELL_SEARCH.response\n");
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_cell_search_response_t));
+}
+int nfapi_pnf_cell_search_ind(nfapi_pnf_config_t* config, nfapi_cell_search_indication_t* ind)
+{
+	if (config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_cell_search_indication_t));
+}
+int nfapi_pnf_broadcast_detect_resp(nfapi_pnf_config_t* config, nfapi_broadcast_detect_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_broadcast_detect_response_t));
+}
+int nfapi_pnf_broadcast_detect_ind(nfapi_pnf_config_t* config, nfapi_broadcast_detect_indication_t* ind)
+{
+	if (config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_broadcast_detect_indication_t));
+}
+int nfapi_pnf_system_information_schedule_resp(nfapi_pnf_config_t* config, nfapi_system_information_schedule_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_schedule_response_t));
+}
+
+int nfapi_pnf_system_information_schedule_ind(nfapi_pnf_config_t* config, nfapi_system_information_schedule_indication_t* ind)
+{
+	if (config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_schedule_indication_t));
+}
+int nfapi_pnf_system_information_resp(nfapi_pnf_config_t* config, nfapi_system_information_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_system_information_response_t));
+}
+
+int nfapi_pnf_system_information_ind(nfapi_pnf_config_t* config, nfapi_system_information_indication_t* ind)
+{
+	if (config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(ind->header), sizeof(nfapi_system_information_indication_t));
+}
+int nfapi_pnf_nmm_stop_resp(nfapi_pnf_config_t* config, nfapi_nmm_stop_response_t* resp)
+{
+	// ensure it's valid
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p4_message(_this, &(resp->header), sizeof(nfapi_nmm_stop_request_t));
+}
+
+int nfapi_pnf_vendor_extension(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len)
+{
+	// ensure it's valid
+	if (config == NULL || msg == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_t* _this = (pnf_t*)(config);
+
+	return pnf_pack_and_send_p5_message(_this, msg, msg_len);
+}
+
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
new file mode 100644
index 0000000000..02b828d382
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
@@ -0,0 +1,1769 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <sys/select.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include "pnf_p7.h"
+
+#define FAPI2_IP_DSCP	0
+
+extern uint16_t sf_ahead;
+//uint16_t sf_ahead=4;
+
+void add_sf(uint16_t *frameP, uint16_t *subframeP, int offset)
+{
+    *frameP    = *frameP + ((*subframeP + offset) / 10);
+
+    *subframeP = ((*subframeP + offset) % 10);
+}
+
+void subtract_sf(uint16_t *frameP, uint16_t *subframeP, int offset)
+{
+  if (*subframeP < offset)
+  {
+    *frameP = (*frameP+1024-1)%1024;
+  }
+  *subframeP = (*subframeP+10-offset)%10;
+}
+
+uint16_t sfnsf_add_sf(uint16_t sfnsf, int offset)
+{
+  uint16_t new_sfnsf;
+  uint16_t sfn = NFAPI_SFNSF2SFN(sfnsf);
+  uint16_t sf  = NFAPI_SFNSF2SF(sfnsf);
+
+  //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf);
+  add_sf(&sfn, &sf, offset);
+
+  new_sfnsf = sfn<<4|sf;
+
+  //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf));
+
+  return new_sfnsf;
+}
+
+uint16_t sfnsf_subtract_sf(uint16_t sfnsf, int offset)
+{
+  uint16_t new_sfnsf;
+  uint16_t sfn = NFAPI_SFNSF2SFN(sfnsf);
+  uint16_t sf  = NFAPI_SFNSF2SF(sfnsf);
+
+  //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf);
+  subtract_sf(&sfn, &sf, offset);
+
+  new_sfnsf = sfn<<4|sf;
+
+  //printf("%s() offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf));
+
+  return new_sfnsf;
+}
+
+uint32_t pnf_get_current_time_hr(void)
+{
+	struct timeval now;
+	(void)gettimeofday(&now, NULL);
+	uint32_t time_hr = TIME2TIMEHR(now);
+	return time_hr;
+}
+
+void* pnf_p7_malloc(pnf_p7_t* pnf_p7, size_t size)
+{
+	if(pnf_p7->_public.malloc)
+	{
+		return (pnf_p7->_public.malloc)(size);
+	}
+	else
+	{
+		return calloc(1, size); 
+	}
+}
+void pnf_p7_free(pnf_p7_t* pnf_p7, void* ptr)
+{
+	if(pnf_p7->_public.free)
+	{
+		return (pnf_p7->_public.free)(ptr);
+	}
+	else
+	{
+		return free(ptr); 
+	}
+}
+
+// todo : for now these just malloc/free need to move to a memory cache
+nfapi_dl_config_request_t* allocate_nfapi_dl_config_request(pnf_p7_t* pnf_p7) 
+{ 
+	void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_dl_config_request_t));
+        //printf("%s() ptr:%p\n", __FUNCTION__, ptr);
+        return ptr;
+}
+
+void deallocate_nfapi_dl_config_request(nfapi_dl_config_request_t* req, pnf_p7_t* pnf_p7) 
+{ 
+  //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->dl_config_request_body.dl_config_pdu_list);
+	if(pnf_p7->_public.codec_config.deallocate)
+	{
+		(pnf_p7->_public.codec_config.deallocate)(req->dl_config_request_body.dl_config_pdu_list);
+	}
+	else
+	{
+		free(req->dl_config_request_body.dl_config_pdu_list);
+	}
+        req->dl_config_request_body.dl_config_pdu_list=0;
+
+	pnf_p7_free(pnf_p7, req);
+}
+
+nfapi_ul_config_request_t* allocate_nfapi_ul_config_request(pnf_p7_t* pnf_p7) 
+{ 
+	void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_ul_config_request_t));
+        //printf("%s() ptr:%p\n", __FUNCTION__, ptr);
+        return ptr;
+}
+
+void deallocate_nfapi_ul_config_request(nfapi_ul_config_request_t* req, pnf_p7_t* pnf_p7) 
+{ 
+  //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->ul_config_request_body.ul_config_pdu_list);
+	if(pnf_p7->_public.codec_config.deallocate)
+	{
+		(pnf_p7->_public.codec_config.deallocate)(req->ul_config_request_body.ul_config_pdu_list);
+	}
+	else
+	{
+		free(req->ul_config_request_body.ul_config_pdu_list);
+	}
+        req->ul_config_request_body.ul_config_pdu_list=0;
+
+	pnf_p7_free(pnf_p7, req);
+}
+
+nfapi_hi_dci0_request_t* allocate_nfapi_hi_dci0_request(pnf_p7_t* pnf_p7) 
+{ 
+	return pnf_p7_malloc(pnf_p7, sizeof(nfapi_hi_dci0_request_t));
+}
+
+void deallocate_nfapi_hi_dci0_request(nfapi_hi_dci0_request_t* req, pnf_p7_t* pnf_p7) 
+{ 
+  //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->hi_dci0_request_body.hi_dci0_pdu_list);
+	if(pnf_p7->_public.codec_config.deallocate)
+	{
+		(pnf_p7->_public.codec_config.deallocate)(req->hi_dci0_request_body.hi_dci0_pdu_list);
+	}
+	else
+	{
+		free(req->hi_dci0_request_body.hi_dci0_pdu_list);
+	}
+        req->hi_dci0_request_body.hi_dci0_pdu_list=0;
+
+	pnf_p7_free(pnf_p7, req);
+}
+
+nfapi_tx_request_t* allocate_nfapi_tx_request(pnf_p7_t* pnf_p7) 
+{ 
+	return pnf_p7_malloc(pnf_p7, sizeof(nfapi_tx_request_t));
+}
+
+void deallocate_nfapi_tx_request(nfapi_tx_request_t* req, pnf_p7_t* pnf_p7) 
+{ 
+	int i = 0;
+
+  //printf("%s() SFN/SF:%d %s req:%p pdu[0]:data:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->tx_request_body.tx_pdu_list[i].segments[0].segment_data);
+
+	for(i = 0; i < req->tx_request_body.number_of_pdus; ++i)
+	{
+		void* data = req->tx_request_body.tx_pdu_list[i].segments[0].segment_data;
+
+		if(pnf_p7->_public.codec_config.deallocate)
+		{
+			(pnf_p7->_public.codec_config.deallocate)(data);
+		}
+		else
+		{
+			free(data);
+		}
+                data=0;
+	}
+
+
+	if(pnf_p7->_public.codec_config.deallocate)
+	{
+		(pnf_p7->_public.codec_config.deallocate)(req->tx_request_body.tx_pdu_list);
+	}
+	else
+	{
+		free(req->tx_request_body.tx_pdu_list);
+	}
+        req->tx_request_body.tx_pdu_list=0;
+
+	pnf_p7_free(pnf_p7, req);
+}
+
+nfapi_lbt_dl_config_request_t* allocate_nfapi_lbt_dl_config_request(pnf_p7_t* pnf_p7) 
+{ 
+	return pnf_p7_malloc(pnf_p7, sizeof(nfapi_lbt_dl_config_request_t));
+}
+
+void deallocate_nfapi_lbt_dl_config_request(nfapi_lbt_dl_config_request_t* req, pnf_p7_t* pnf_p7) 
+{ 
+	if(pnf_p7->_public.codec_config.deallocate)
+	{
+		(pnf_p7->_public.codec_config.deallocate)(req->lbt_dl_config_request_body.lbt_dl_config_req_pdu_list);
+	}
+	else
+	{
+		free(req->lbt_dl_config_request_body.lbt_dl_config_req_pdu_list);
+	}
+        req->lbt_dl_config_request_body.lbt_dl_config_req_pdu_list=0;
+
+	pnf_p7_free(pnf_p7, req);
+}
+
+pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len)
+{
+	pnf_p7_rx_message_t* msg = 0;
+	// attempt to find a entry for this segment
+	pnf_p7_rx_message_t* iterator = queue->msg_queue;
+	while(iterator != 0)
+	{
+		if(iterator->sequence_number == sequence_number)
+		{
+			msg = iterator;
+			break;
+		}
+
+		iterator = iterator->next;
+	}
+	
+	// if found then copy data to message
+	if(msg != 0)
+	{
+	
+		msg->segments[segment_number].buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, data_len);
+		memcpy(msg->segments[segment_number].buffer, data, data_len);
+		msg->segments[segment_number].length = data_len;
+
+		msg->num_segments_received++;
+
+		// set the segement number if we have the last segment
+		if(m == 0)
+			msg->num_segments_expected = segment_number + 1;
+	}
+	// else add new rx message entry
+	else
+	{
+		// create a new message
+		msg = (pnf_p7_rx_message_t*)(pnf_p7_malloc(pnf_p7, sizeof(pnf_p7_rx_message_t)));
+		memset(msg, 0, sizeof(pnf_p7_rx_message_t));
+
+		msg->sequence_number = sequence_number;
+		msg->num_segments_expected = m ? 255 : segment_number + 1;
+		msg->num_segments_received = 1;
+		msg->rx_hr_time = rx_hr_time;
+
+		msg->segments[segment_number].buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, data_len);
+		memcpy(msg->segments[segment_number].buffer, data, data_len);
+		msg->segments[segment_number].length = data_len;
+
+		// place the message at the head of the queue
+		msg->next = queue->msg_queue;
+		queue->msg_queue = msg;
+	}
+
+	return msg;
+}
+
+void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg)
+{
+	// remove message if it has the same sequence number
+	pnf_p7_rx_message_t* iterator = queue->msg_queue;
+	pnf_p7_rx_message_t* previous = 0;
+
+	while(iterator != 0)
+	{
+		if(iterator->sequence_number == msg->sequence_number)
+		{
+			if(previous == 0)
+			{
+				queue->msg_queue = iterator->next;
+			}
+			else
+			{
+				previous->next = iterator->next;
+			}
+
+			//NFAPI_TRACE(NFAPI_TRACE_INFO, "Deleting reassembly message\n");
+			// delete the message
+			uint16_t i;
+			for(i = 0; i < 128; ++i)
+			{
+				if(iterator->segments[i].buffer)
+					pnf_p7_free(pnf_p7, iterator->segments[i].buffer);
+			}
+			pnf_p7_free(pnf_p7, iterator);
+
+			break;
+		}
+
+		previous = iterator;
+		iterator = iterator->next;
+	}
+}
+
+void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta)
+{
+	// remove all messages that are too old
+	pnf_p7_rx_message_t* iterator = queue->msg_queue;
+	pnf_p7_rx_message_t* previous = 0;
+
+	while(iterator != 0)
+	{
+		if(rx_hr_time - iterator->rx_hr_time > delta)
+		{
+			if(previous == 0)
+			{
+				queue->msg_queue = iterator->next;
+			}
+			else
+			{
+				previous->next = iterator->next;
+			}
+			
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Deleting stale reassembly message (%u %u %d)\n", iterator->rx_hr_time, rx_hr_time, delta);
+
+			pnf_p7_rx_message_t* to_delete = iterator;
+			iterator = iterator->next;
+
+			// delete the message
+			uint16_t i;
+			for(i = 0; i < 128; ++i)
+			{
+				if(to_delete->segments[i].buffer)
+					pnf_p7_free(pnf_p7, to_delete->segments[i].buffer);
+			}
+			pnf_p7_free(pnf_p7, to_delete);
+
+		}
+		else
+		{
+			previous = iterator;
+			iterator = iterator->next;
+		}
+	}
+}
+
+
+static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr)
+{
+	if(now_hr < sf_start_hr)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe now_hr:%u sf_start_hr:%u\n", now_hr, sf_start_hr);
+		return 0;
+	}
+	else
+	{
+		uint32_t now_us = TIMEHR_USEC(now_hr);
+		uint32_t sf_start_us = TIMEHR_USEC(sf_start_hr);
+
+		// if the us have wrapped adjust for it
+		if(now_hr < sf_start_us)
+		{
+			now_us += 1000000;
+		}
+
+		return now_us - sf_start_us;
+	}
+}
+
+int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len)
+{
+	// todo : consider how to do this only once
+	struct sockaddr_in remote_addr;
+	memset((char*)&remote_addr, 0, sizeof(struct sockaddr_in));
+	remote_addr.sin_family = AF_INET;
+	remote_addr.sin_port = htons(pnf_p7->_public.remote_p7_port);
+	//remote_addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.remote_p7_addr);
+	if(inet_aton(pnf_p7->_public.remote_p7_addr, &remote_addr.sin_addr) == -1)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "inet_aton failed %d\n", errno);
+		return -1;
+	}
+	
+	socklen_t remote_addr_len = sizeof(struct sockaddr_in);
+	
+	int sendto_result;
+	if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", __FUNCTION__, pnf_p7->_public.remote_p7_addr, pnf_p7->_public.remote_p7_port, (int)pnf_p7->p7_sock, (const char*)msg, len, remote_addr_len,  errno);
+		return -1;
+	}
+
+	if(sendto_result != len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s sendto failed to send the entire message %d %d\n", __FUNCTION__, sendto_result, len);
+	}
+	return 0;
+}
+
+int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len)
+{
+	header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number);
+
+	// Need to guard against different threads calling the encode function at the same time
+	if(pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+		return -1;
+	}
+
+	int len = nfapi_p7_message_pack(header, pnf_p7->tx_message_buffer, sizeof(pnf_p7->tx_message_buffer), &pnf_p7->_public.codec_config);
+
+	if (len < 0)
+	{
+		if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return -1;
+		}
+		
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len );
+		return -1;
+	}
+
+	if(len > pnf_p7->_public.segment_size)
+	{
+		int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; 
+		int seg_body_len = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; 
+		int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); 
+
+		int segment = 0;
+		int offset = NFAPI_P7_HEADER_LENGTH;
+		uint8_t buffer[pnf_p7->_public.segment_size];
+		for(segment = 0; segment < segment_count; ++segment)
+		{
+			uint8_t last = 0;
+			uint16_t size = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH;
+			if(segment + 1 == segment_count)
+			{
+				last = 1;
+				size = (msg_body_len) - (seg_body_len * segment);
+			}
+
+			uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH;
+
+			// Update the header with the m and segement 
+			memcpy(&buffer[0], pnf_p7->tx_message_buffer, NFAPI_P7_HEADER_LENGTH);
+
+			// set the segment length
+			buffer[4] = (segment_size & 0xFF00) >> 8;
+			buffer[5] = (segment_size & 0xFF);
+
+			// set the m & segment number
+			buffer[6] = ((!last) << 7) + segment;
+
+			memcpy(&buffer[NFAPI_P7_HEADER_LENGTH], pnf_p7->tx_message_buffer + offset, size);
+			offset += size;
+
+			if(pnf_p7->_public.checksum_enabled)
+			{
+				nfapi_p7_update_checksum(buffer, segment_size);
+			}
+
+
+			pnf_p7_send_message(pnf_p7, &buffer[0], segment_size);
+		}
+	}
+	else
+	{
+		if(pnf_p7->_public.checksum_enabled)
+		{
+			nfapi_p7_update_checksum(pnf_p7->tx_message_buffer, len);
+		}
+
+		// simple case that the message fits in a single segment
+		pnf_p7_send_message(pnf_p7, pnf_p7->tx_message_buffer, len);
+	}
+
+	pnf_p7->sequence_number++;
+	
+	if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7)
+{
+	nfapi_timing_info_t timing_info;
+	memset(&timing_info, 0, sizeof(timing_info));
+	timing_info.header.message_id = NFAPI_TIMING_INFO;
+	timing_info.header.phy_id = pnf_p7->_public.phy_id;
+
+	timing_info.last_sfn_sf = pnf_p7->sfn_sf;
+	timing_info.time_since_last_timing_info = pnf_p7->timing_info_ms_counter;
+
+	timing_info.dl_config_jitter = pnf_p7->dl_config_jitter;
+	timing_info.tx_request_jitter = pnf_p7->tx_jitter;
+	timing_info.ul_config_jitter = pnf_p7->ul_config_jitter;
+	timing_info.hi_dci0_jitter = pnf_p7->hi_dci0_jitter;
+
+	timing_info.dl_config_latest_delay = 0;
+	timing_info.tx_request_latest_delay = 0;
+	timing_info.ul_config_latest_delay = 0;
+	timing_info.hi_dci0_latest_delay = 0;
+
+	timing_info.dl_config_earliest_arrival = 0;
+	timing_info.tx_request_earliest_arrival = 0;
+	timing_info.ul_config_earliest_arrival = 0;
+	timing_info.hi_dci0_earliest_arrival = 0;
+
+
+	pnf_p7_pack_and_send_p7_message(pnf_p7, &(timing_info.header), sizeof(timing_info));
+
+	pnf_p7->timing_info_ms_counter = 0;
+}
+
+void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf)
+{
+  struct timespec t;
+  clock_gettime( CLOCK_MONOTONIC, &t);
+
+  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(sfn_sf:%d) t:%ld.%09ld\n", __FUNCTION__, NFAPI_SFNSF2DEC(sfn_sf), t.tv_sec, t.tv_nsec);
+
+	if(pnf_p7->_public.tx_req && pnf_p7->_public.dummy_subframe.tx_req)
+	{
+		pnf_p7->_public.dummy_subframe.tx_req->sfn_sf = sfn_sf;
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - enter\n");
+		(pnf_p7->_public.tx_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.tx_req);
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - exit\n");
+	}
+	if(pnf_p7->_public.dl_config_req && pnf_p7->_public.dummy_subframe.dl_config_req)
+	{
+		pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf;
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - enter\n");
+		(pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req);
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - exit\n");
+	}
+	if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req)
+	{
+		pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf;
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy ul_config_req - enter\n");
+		(pnf_p7->_public.ul_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.ul_config_req);
+	}
+	if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req)
+	{
+		pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf;
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy hi_dci0 - enter\n");
+		(pnf_p7->_public.hi_dci0_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.hi_dci0_req);
+	}
+	if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req)
+	{
+		pnf_p7->_public.dummy_subframe.lbt_dl_config_req->sfn_sf = sfn_sf;
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy lbt - enter\n");
+		(pnf_p7->_public.lbt_dl_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.lbt_dl_config_req);
+	}
+}
+
+int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
+{
+	// We could either send an event to the p7 thread have have it run the
+	// subframe or we could handle it here and lock access to the subframe
+	// buffers. If we do it on the p7 thread then we run the risk of blocking
+	// on the udp send. 
+	//
+	// todo : start a timer to give us more of the 1 ms tick before send back
+	// the frame
+	
+	// todo : consider a more efficent lock mechasium
+	if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+		return -1;
+	}
+
+#if 1
+	// save the curren time and sfn_sf
+	pnf_p7->sf_start_time_hr = pnf_get_current_time_hr();
+	pnf_p7->sfn_sf = sfn_sf;
+
+        uint32_t sfn_sf_tx = sfnsf_add_sf(sfn_sf, sf_ahead);
+        uint32_t tx_sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf_tx);
+
+	// If the subframe_buffer has been configured
+	if(pnf_p7->_public.subframe_buffer_size != 0)
+	{
+
+		// apply the shift to the incoming sfn_sf
+		if(pnf_p7->sfn_sf_shift != 0)
+		{
+			int32_t sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf);
+
+			int32_t shifted_sfn_sf = sfn_sf_dec += pnf_p7->sfn_sf_shift;
+
+			// adjust for wrap-around
+			if(shifted_sfn_sf < 0)
+				shifted_sfn_sf += NFAPI_MAX_SFNSFDEC;
+			else if(shifted_sfn_sf > NFAPI_MAX_SFNSFDEC)
+				shifted_sfn_sf -= NFAPI_MAX_SFNSFDEC;
+
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/sf (%d -> %d)\n", pnf_p7->sfn_sf_shift, NFAPI_SFNSF2DEC(sfn_sf), shifted_sfn_sf);
+			sfn_sf = shifted_sfn_sf;
+
+                        //
+                        // DJP - why does the shift not apply to pnf_p7->sfn_sf???
+                        //
+
+			pnf_p7->sfn_sf_shift = 0;
+		}
+
+		uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf);
+		uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+		nfapi_pnf_p7_subframe_buffer_t* subframe_buffer = &(pnf_p7->subframe_buffer[buffer_index]);
+
+		uint8_t tx_buffer_index = tx_sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+		nfapi_pnf_p7_subframe_buffer_t* tx_subframe_buffer = &(pnf_p7->subframe_buffer[tx_buffer_index]);
+
+                //printf("sfn_sf_dec:%d tx_sfn_sf_dec:%d\n", sfn_sf_dec, tx_sfn_sf_dec);
+
+                if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d subframe_buffer->sfn_sf:%d tx_subframe_buffer->sfn_sf:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] "
+                    "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", 
+                    __FUNCTION__, 
+                    pnf_p7->sfn_sf_shift, 
+                    NFAPI_SFNSF2DEC(subframe_buffer->sfn_sf), 
+                    NFAPI_SFNSF2DEC(tx_subframe_buffer->sfn_sf), 
+                       sfn_sf_dec,    buffer_index,    subframe_buffer->dl_config_req,    subframe_buffer->tx_req, 
+                    tx_sfn_sf_dec, tx_buffer_index, tx_subframe_buffer->dl_config_req, tx_subframe_buffer->tx_req);
+
+		// if the subframe buffer sfn sf is set then we have atlease 1 message
+		// from the vnf. 
+		// todo : how to handle the messages we don't have, send dummies for
+		// now
+
+                //printf("tx_subframe_buffer->sfn_sf:%d sfn_sf_tx:%d\n", tx_subframe_buffer->sfn_sf, sfn_sf_tx);
+                //printf("subframe_buffer->sfn_sf:%d sfn_sf:%d\n", subframe_buffer->sfn_sf, sfn_sf);
+		if(tx_subframe_buffer->sfn_sf == sfn_sf_tx)
+		{
+			if(tx_subframe_buffer->tx_req != 0)
+			{
+				if(pnf_p7->_public.tx_req)
+					(pnf_p7->_public.tx_req)(&(pnf_p7->_public), tx_subframe_buffer->tx_req);
+
+				//deallocate_nfapi_tx_request(subframe_buffer->tx_req, pnf_p7);
+			}
+			else
+			{
+				// send dummy
+				if(pnf_p7->_public.tx_req && pnf_p7->_public.dummy_subframe.tx_req)
+				{
+					pnf_p7->_public.dummy_subframe.tx_req->sfn_sf = sfn_sf_tx;
+					(pnf_p7->_public.tx_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.tx_req);
+				}
+			}
+
+			if(tx_subframe_buffer->dl_config_req != 0)
+			{
+				if(pnf_p7->_public.dl_config_req)
+					(pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), tx_subframe_buffer->dl_config_req);
+
+				//deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7);
+			}
+			else
+			{
+				// send dummy
+				if(pnf_p7->_public.dl_config_req && pnf_p7->_public.dummy_subframe.dl_config_req)
+				{
+					pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf_tx;
+					(pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req);
+				}
+			}
+
+			if(tx_subframe_buffer->hi_dci0_req != 0)
+			{
+				if(pnf_p7->_public.hi_dci0_req)
+					(pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), tx_subframe_buffer->hi_dci0_req);
+
+				//deallocate_nfapi_hi_dci0_request(subframe_buffer->hi_dci0_req, pnf_p7);
+			}
+			else
+			{
+				//send dummy
+				if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req)
+				{
+					pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf_tx;
+					(pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.hi_dci0_req);
+				}
+			}
+
+                        if(tx_subframe_buffer->dl_config_req != 0)
+                        {
+                          deallocate_nfapi_dl_config_request(tx_subframe_buffer->dl_config_req, pnf_p7);
+                          tx_subframe_buffer->dl_config_req = 0;
+                        }
+			if(tx_subframe_buffer->tx_req != 0)
+                        {
+                          deallocate_nfapi_tx_request(tx_subframe_buffer->tx_req, pnf_p7);
+                          tx_subframe_buffer->tx_req = 0;
+                        }
+                        if(tx_subframe_buffer->hi_dci0_req != 0)
+                        {
+                          deallocate_nfapi_hi_dci0_request(tx_subframe_buffer->hi_dci0_req, pnf_p7);
+                          tx_subframe_buffer->hi_dci0_req = 0;
+                        }
+                }
+		else
+		{
+                  // If we ever need to "send" a dummy ul_config this won't work!!!
+                  send_dummy_subframe(pnf_p7, sfn_sf_tx);
+		}
+
+                if(subframe_buffer->sfn_sf == sfn_sf)
+		{
+
+			if(subframe_buffer->ul_config_req != 0)
+			{
+				if(pnf_p7->_public.ul_config_req)
+					(pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), subframe_buffer->ul_config_req);
+
+				//deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7);
+			}
+			else
+			{
+				// send dummy
+				if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req)
+				{
+					pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf;
+					(pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ul_config_req);
+				}
+			}
+
+			if(subframe_buffer->lbt_dl_config_req != 0)
+			{
+				if(pnf_p7->_public.lbt_dl_config_req)
+					(pnf_p7->_public.lbt_dl_config_req)(&(pnf_p7->_public), subframe_buffer->lbt_dl_config_req);
+
+				//deallocate_nfapi_lbt_dl_config_request(subframe_buffer->lbt_dl_config_req, pnf_p7);
+			}
+			else
+			{
+				// send dummy
+				if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req)
+				{
+					pnf_p7->_public.dummy_subframe.lbt_dl_config_req->sfn_sf = sfn_sf;
+					(pnf_p7->_public.lbt_dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.lbt_dl_config_req);
+				}
+
+			}
+
+                        //if(subframe_buffer->dl_config_req != 0)
+                          //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7);
+			//if(subframe_buffer->tx_req != 0)
+                          //deallocate_nfapi_tx_request(subframe_buffer->tx_req, pnf_p7);
+                        if(subframe_buffer->ul_config_req != 0)
+                        {
+                          deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7);
+                          subframe_buffer->ul_config_req = 0;
+
+                        }
+                        //if(subframe_buffer->hi_dci0_req != 0)
+                          //deallocate_nfapi_hi_dci0_request(subframe_buffer->hi_dci0_req, pnf_p7);
+			if(subframe_buffer->lbt_dl_config_req != 0)
+                        {
+                          deallocate_nfapi_lbt_dl_config_request(subframe_buffer->lbt_dl_config_req, pnf_p7);
+                          subframe_buffer->lbt_dl_config_req = 0;
+                        }
+                } // sfn_sf match
+
+                if (subframe_buffer->dl_config_req == 0 && subframe_buffer->tx_req == 0 && subframe_buffer->ul_config_req == 0 && subframe_buffer->lbt_dl_config_req == 0)
+                {
+                  memset(&(pnf_p7->subframe_buffer[buffer_index]), 0, sizeof(nfapi_pnf_p7_subframe_buffer_t));
+                  pnf_p7->subframe_buffer[buffer_index].sfn_sf = -1;
+		}
+
+                //printf("pnf_p7->_public.timing_info_mode_periodic:%d pnf_p7->timing_info_period_counter:%d pnf_p7->_public.timing_info_period:%d\n", pnf_p7->_public.timing_info_mode_periodic, pnf_p7->timing_info_period_counter, pnf_p7->_public.timing_info_period);
+                //printf("pnf_p7->_public.timing_info_mode_aperiodic:%d pnf_p7->timing_info_aperiodic_send:%d\n", pnf_p7->_public.timing_info_mode_aperiodic, pnf_p7->timing_info_aperiodic_send);
+                //printf("pnf_p7->timing_info_ms_counter:%d\n", pnf_p7->timing_info_ms_counter);
+
+		// send the periodic timing info if configured
+		if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period)
+		{
+			pnf_pack_and_send_timing_info(pnf_p7);
+
+			pnf_p7->timing_info_period_counter = 0;
+		}
+		else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send)
+		{
+			pnf_pack_and_send_timing_info(pnf_p7);
+
+			pnf_p7->timing_info_aperiodic_send = 0;
+		}
+		else
+		{
+			pnf_p7->timing_info_ms_counter++;
+		}
+	}
+	else
+	{
+		//send_dummy_subframe(pnf_p7, sfn_sf_tx);
+	}
+
+
+        //printf("pnf_p7->tick:%d\n", pnf_p7->tick);
+	if(pnf_p7->tick == 1000)
+	{
+
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF P7:%d] (ONTIME/LATE) DL:(%d/%d) UL:(%d/%d) HI:(%d/%d) TX:(%d/%d)\n", pnf_p7->_public.phy_id,
+					pnf_p7->stats.dl_conf_ontime, pnf_p7->stats.dl_conf_late, 
+					pnf_p7->stats.ul_conf_ontime, pnf_p7->stats.ul_conf_late, 
+					pnf_p7->stats.hi_dci0_ontime, pnf_p7->stats.hi_dci0_late, 
+					pnf_p7->stats.tx_ontime, pnf_p7->stats.tx_late);
+		pnf_p7->tick = 0;
+		memset(&pnf_p7->stats, 0, sizeof(pnf_p7->stats));
+	}
+	pnf_p7->tick++;
+#endif
+
+	if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+
+// return 1 if in window
+// return 0 if out of window
+uint8_t is_p7_request_in_window(uint16_t sfnsf, const char* name, pnf_p7_t* phy)
+{
+	uint32_t recv_sfn_sf_dec = NFAPI_SFNSF2DEC(sfnsf);
+	uint32_t current_sfn_sf_dec = NFAPI_SFNSF2DEC(phy->sfn_sf);
+
+	uint8_t in_window = 0;
+	uint8_t timing_window = phy->_public.subframe_buffer_size;
+
+	if(recv_sfn_sf_dec <= current_sfn_sf_dec)
+	{
+		// Need to check for wrap in window
+		if(((current_sfn_sf_dec + timing_window) % NFAPI_MAX_SFNSFDEC) < current_sfn_sf_dec)
+		{
+			if(recv_sfn_sf_dec > ((current_sfn_sf_dec + timing_window) % NFAPI_MAX_SFNSFDEC))
+			{
+				// out of window
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is late %d (with wrap)\n", current_sfn_sf_dec, name, recv_sfn_sf_dec);
+			}
+			else
+			{
+				// ok
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d (with wrap)\n", current_sfn_sf_dec, name, recv_sfn_sf_dec);
+				in_window = 1;
+			}
+		}
+		else
+		{
+			// too late
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in late %d (delta:%d)\n", current_sfn_sf_dec, name, recv_sfn_sf_dec, (current_sfn_sf_dec - recv_sfn_sf_dec));
+		}
+
+	}
+	else
+	{
+		// Need to check it is in window
+		if((recv_sfn_sf_dec - current_sfn_sf_dec) <= timing_window)
+		{
+			// in window
+			//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_sf_dec, name, recv_sfn_sf_dec);
+			in_window = 1;
+		}
+		else
+		{
+			// too far in the future
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_sf_dec, name, recv_sfn_sf_dec,  (recv_sfn_sf_dec - current_sfn_sf_dec), timing_window);
+		}
+
+	}
+
+	return in_window;
+}
+
+
+// P7 messages
+//
+void pnf_handle_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req Received\n");
+
+	nfapi_dl_config_request_t* req  = allocate_nfapi_dl_config_request(pnf_p7);
+
+	if(req == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_dl_config_request structure\n");
+		return;
+	}
+
+	int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_dl_config_request_t), &(pnf_p7->_public.codec_config));
+
+	if(unpack_result == 0)
+	{
+		if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+			return;
+		}
+
+                if (
+                    0 && 
+                    (NFAPI_SFNSF2DEC(req->sfn_sf) % 100 ==0 ||
+                     NFAPI_SFNSF2DEC(req->sfn_sf) % 105 ==0 
+                    )
+                )
+                  NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req sfn_sf:%d pdcch:%u dci:%u pdu:%u pdsch_rnti:%u pcfich:%u\n", 
+                      NFAPI_SFNSF2DEC(req->sfn_sf),
+                      req->dl_config_request_body.number_pdcch_ofdm_symbols,
+                      req->dl_config_request_body.number_dci,
+                      req->dl_config_request_body.number_pdu,
+                      req->dl_config_request_body.number_pdsch_rnti,
+                      req->dl_config_request_body.transmission_power_pcfich
+                      );
+
+                if(is_p7_request_in_window(req->sfn_sf, "dl_config_request", pnf_p7))
+                {
+                  uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+                  uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+                        struct timespec t;
+                        clock_gettime(CLOCK_MONOTONIC, &t);
+
+                  NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_CONFIG_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_sf_dec, buffer_index);
+
+			// if there is already an dl_config_req make sure we free it.
+			if(pnf_p7->subframe_buffer[buffer_index].dl_config_req != 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "%s() is_p7_request_in_window()=TRUE buffer_index occupied - free it first sfn_sf:%d buffer_index:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), buffer_index);
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing dl_config_req at index %d (%d/%d)", 
+				//			pMyPhyInfo->sfnSf, bufferIdx,
+				//			SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf));
+				deallocate_nfapi_dl_config_request(pnf_p7->subframe_buffer[buffer_index].dl_config_req, pnf_p7);
+			}
+
+			// saving dl_config_request in subframe buffer
+			pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+			pnf_p7->subframe_buffer[buffer_index].dl_config_req = req;
+
+			pnf_p7->stats.dl_conf_ontime++;
+			
+		}
+		else
+		{
+			//NFAPI_TRACE(NFAPI_TRACE_NOTE, "NOT storing dl_config_req SFN/SF %d\n", req->sfn_sf);
+			deallocate_nfapi_dl_config_request(req, pnf_p7);
+
+			if(pnf_p7->_public.timing_info_mode_aperiodic)
+			{
+				pnf_p7->timing_info_aperiodic_send = 1;
+			}
+
+			pnf_p7->stats.dl_conf_late++;
+		}
+
+		if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack dl_config_req");
+		deallocate_nfapi_dl_config_request(req, pnf_p7);
+	}
+}
+
+void pnf_handle_ul_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "UL_CONFIG.req Received\n");
+
+	nfapi_ul_config_request_t* req  = allocate_nfapi_ul_config_request(pnf_p7);
+
+	if(req == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_ul_config_request structure\n");
+		return;
+	}
+
+	int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_ul_config_request_t), &(pnf_p7->_public.codec_config));
+
+	if(unpack_result == 0)
+	{
+		if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+			return;
+		}
+
+		if(is_p7_request_in_window(req->sfn_sf, "ul_config_request", pnf_p7))
+		{
+			uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+			uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+                        struct timespec t;
+                        clock_gettime(CLOCK_MONOTONIC, &t);
+
+                        NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_CONFIG_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_sf_dec, buffer_index);
+
+			if(pnf_p7->subframe_buffer[buffer_index].ul_config_req != 0)
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing ul_config_req at index %d (%d/%d)", 
+				//			pMyPhyInfo->sfnSf, bufferIdx,
+				//			SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf));
+
+				deallocate_nfapi_ul_config_request(pnf_p7->subframe_buffer[buffer_index].ul_config_req, pnf_p7);
+			}
+
+			pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+			pnf_p7->subframe_buffer[buffer_index].ul_config_req = req;
+			
+			pnf_p7->stats.ul_conf_ontime++;
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing ul_config_req OUTSIDE OF TRANSMIT BUFFER WINDOW SFN/SF %d\n", NFAPI_SFNSF2DEC(pnf_p7->sfn_sf), NFAPI_SFNSF2DEC(req->sfn_sf));
+			deallocate_nfapi_ul_config_request(req, pnf_p7);
+
+			if(pnf_p7->_public.timing_info_mode_aperiodic)
+			{
+				pnf_p7->timing_info_aperiodic_send = 1;
+			}
+
+			pnf_p7->stats.ul_conf_late++;
+		}
+
+		if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_config_req\n");
+		deallocate_nfapi_ul_config_request(req, pnf_p7);
+	}
+}
+
+void pnf_handle_hi_dci0_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "HI_DCI0.req Received\n");
+
+	nfapi_hi_dci0_request_t* req  = allocate_nfapi_hi_dci0_request(pnf_p7);
+
+	if(req == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_hi_dci0_request structure\n");
+		return;
+	}
+
+	int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_hi_dci0_request_t), &pnf_p7->_public.codec_config);
+
+	if(unpack_result == 0)
+	{
+		if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+			return;
+		}
+
+		if(is_p7_request_in_window(req->sfn_sf, "hi_dci0_request", pnf_p7))
+		{
+			uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+			uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+			if(pnf_p7->subframe_buffer[buffer_index].hi_dci0_req!= 0)
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing hi_dci0_req at index %d (%d/%d)", 
+				//			pMyPhyInfo->sfnSf, bufferIdx,
+				//			SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf));
+
+				deallocate_nfapi_hi_dci0_request(pnf_p7->subframe_buffer[buffer_index].hi_dci0_req, pnf_p7);
+			}
+
+			pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+			pnf_p7->subframe_buffer[buffer_index].hi_dci0_req = req;
+
+			pnf_p7->stats.hi_dci0_ontime++;
+			
+		}
+		else
+		{
+			//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing hi_dci0_req SFN/SF %d/%d\n", pMyPhyInfo->sfnSf, SFNSF2SFN(req->sfn_sf), SFNSF2SF(req->sfn_sf));
+			deallocate_nfapi_hi_dci0_request(req, pnf_p7);
+
+			if(pnf_p7->_public.timing_info_mode_aperiodic)
+			{
+				pnf_p7->timing_info_aperiodic_send = 1;
+			}
+
+			pnf_p7->stats.hi_dci0_late++;
+		}
+
+		if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return;
+		}
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack hi_dci0_req\n");
+		deallocate_nfapi_hi_dci0_request(req, pnf_p7);
+	}
+}
+
+void pnf_handle_tx_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "TX.req Received\n");
+	
+	nfapi_tx_request_t* req = allocate_nfapi_tx_request(pnf_p7);
+
+	if(req == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_tx_request structure\n");
+		return;
+	}
+
+	int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_tx_request_t), &pnf_p7->_public.codec_config);
+	if(unpack_result == 0)
+	{
+		if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+			return;
+		}
+
+		if(is_p7_request_in_window(req->sfn_sf, "tx_request", pnf_p7))
+		{
+			uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+			uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+                        struct timespec t;
+                        clock_gettime(CLOCK_MONOTONIC, &t);
+
+                        NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_sf_dec, buffer_index);
+
+                        if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX_REQ.req sfn_sf:%d pdus:%d - TX_REQ is within window\n",
+                            __FUNCTION__,
+                            NFAPI_SFNSF2DEC(req->sfn_sf),
+                            req->tx_request_body.number_of_pdus);
+
+			if(pnf_p7->subframe_buffer[buffer_index].tx_req != 0)
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing tx_req at index %d (%d/%d)", 
+				//			pMyPhyInfo->sfnSf, bufferIdx,
+				//			SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf));
+
+				deallocate_nfapi_tx_request(pnf_p7->subframe_buffer[buffer_index].tx_req, pnf_p7);
+			}
+
+			pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+			pnf_p7->subframe_buffer[buffer_index].tx_req = req;
+
+			pnf_p7->stats.tx_ontime++;
+		}
+		else
+		{
+                  NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() TX_REQUEST Request is outside of window REQ:SFN_SF:%d CURR:SFN_SF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), NFAPI_SFNSF2DEC(pnf_p7->sfn_sf));
+
+			deallocate_nfapi_tx_request(req, pnf_p7);
+
+			if(pnf_p7->_public.timing_info_mode_aperiodic)
+			{
+				pnf_p7->timing_info_aperiodic_send = 1;
+			}
+
+			pnf_p7->stats.tx_late++;
+		}
+
+		if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return;
+		}
+	}
+	else
+	{
+		deallocate_nfapi_tx_request(req, pnf_p7);
+	}
+}
+
+void pnf_handle_lbt_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+	nfapi_lbt_dl_config_request_t* req = allocate_nfapi_lbt_dl_config_request(pnf_p7);
+
+	if(req == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_lbt_dl_config_request structure\n");
+		return;
+	}
+
+	int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_lbt_dl_config_request_t), &pnf_p7->_public.codec_config);
+
+	if(unpack_result == 0)
+	{
+		if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+			return;
+		}
+
+		if(is_p7_request_in_window(req->sfn_sf, "lbt_dl_request", pnf_p7))
+		{
+			uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+			uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+			if(pnf_p7->subframe_buffer[buffer_index].lbt_dl_config_req != 0)
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing tx_req at index %d (%d/%d)", 
+				//			pMyPhyInfo->sfnSf, bufferIdx,
+				//			SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf));
+
+				deallocate_nfapi_lbt_dl_config_request(pnf_p7->subframe_buffer[buffer_index].lbt_dl_config_req, pnf_p7);
+			}
+
+			pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+			pnf_p7->subframe_buffer[buffer_index].lbt_dl_config_req = req;
+		}
+		else
+		{
+			deallocate_nfapi_lbt_dl_config_request(req, pnf_p7);
+
+			if(pnf_p7->_public.timing_info_mode_aperiodic)
+			{
+				pnf_p7->timing_info_aperiodic_send = 1;
+			}
+		}
+
+		if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+			return;
+		}
+	}
+	else
+	{
+		deallocate_nfapi_lbt_dl_config_request(req, pnf_p7);
+	}
+
+}
+
+void pnf_handle_p7_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint16_t message_id)
+{
+	if(pnf_p7->_public.allocate_p7_vendor_ext)
+	{
+		uint16_t msg_size;
+		nfapi_p7_message_header_t* msg = pnf_p7->_public.allocate_p7_vendor_ext(message_id, &msg_size);
+
+		if(msg == 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n");
+			return;
+		}
+
+		int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &pnf_p7->_public.codec_config);
+
+		if(unpack_result == 0)
+		{
+			if(pnf_p7->_public.vendor_ext)
+				pnf_p7->_public.vendor_ext(&(pnf_p7->_public), msg);
+		}
+		
+		if(pnf_p7->_public.deallocate_p7_vendor_ext)
+			pnf_p7->_public.deallocate_p7_vendor_ext(msg);
+		
+	}
+	
+}
+
+
+uint32_t calculate_t2(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr)
+{
+	uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
+	uint32_t t2 = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
+
+        if (0)
+        {
+          static uint32_t prev_t2 = 0;
+
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s(now_time_hr:%u sfn_sf:%d sf_start_time_Hr:%u) sf_time_us:%u t2:%u prev_t2:%u diff:%u\n",
+              __FUNCTION__,
+              now_time_hr, NFAPI_SFNSF2DEC(sfn_sf), sf_start_time_hr,
+              sf_time_us,
+              t2,
+              prev_t2,
+              t2-prev_t2);
+
+          prev_t2 = t2;
+        }
+
+	return t2;
+}
+
+uint32_t calculate_t3(uint16_t sfn_sf, uint32_t sf_start_time_hr)
+{
+	uint32_t now_time_hr = pnf_get_current_time_hr();
+
+	uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
+
+	uint32_t t3 = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
+
+	return t3;
+}
+
+void pnf_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time)
+{
+	nfapi_dl_node_sync_t dl_node_sync;
+
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_NODE_SYNC Received\n");
+
+	if (pRecvMsg == NULL || pnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return;
+	}
+
+	// unpack the message
+	if (nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		return;
+	}
+
+	if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
+		return;
+	}
+
+
+	if (dl_node_sync.delta_sfn_sf != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Will shift SF timing by %d on next subframe\n", dl_node_sync.delta_sfn_sf);
+
+		pnf_p7->sfn_sf_shift = dl_node_sync.delta_sfn_sf;
+	}
+
+	nfapi_ul_node_sync_t ul_node_sync;
+	memset(&ul_node_sync, 0, sizeof(ul_node_sync));
+	ul_node_sync.header.message_id = NFAPI_UL_NODE_SYNC;
+	ul_node_sync.header.phy_id = dl_node_sync.header.phy_id;
+	ul_node_sync.t1 = dl_node_sync.t1;
+	ul_node_sync.t2 = calculate_t2(rx_hr_time, pnf_p7->sfn_sf, pnf_p7->sf_start_time_hr);
+	ul_node_sync.t3 = calculate_t3(pnf_p7->sfn_sf, pnf_p7->sf_start_time_hr);
+
+	if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
+		return;
+	}
+
+	pnf_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync));
+}
+
+void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7,  uint32_t rx_hr_time)
+{
+	nfapi_p7_message_header_t header;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	// ensure the message is sensible
+	if (recvMsgLen < 8 || pRecvMsg == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
+		return;
+	}
+
+	switch (header.message_id)
+	{
+		case NFAPI_DL_NODE_SYNC:
+			pnf_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time);
+			break;
+
+		case NFAPI_DL_CONFIG_REQUEST:
+			pnf_handle_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+
+		case NFAPI_UL_CONFIG_REQUEST:
+			pnf_handle_ul_config_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+
+		case NFAPI_HI_DCI0_REQUEST:
+			pnf_handle_hi_dci0_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+
+		case NFAPI_TX_REQUEST:
+			pnf_handle_tx_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			pnf_handle_lbt_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+		
+		default:
+			{
+				if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					pnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, pnf_p7, header.message_id);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P7 Unknown message ID %d\n", __FUNCTION__, header.message_id);
+				}
+			}
+			break;
+	}
+}
+
+void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7,  uint32_t rx_hr_time)
+{
+	nfapi_p7_message_header_t messageHeader;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, pnf_p7);
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &pnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence);
+	uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence);
+	uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence);
+
+	if(pnf_p7->_public.checksum_enabled)
+	{
+		uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen);
+		if(checksum != messageHeader.checksum)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum);
+			return;
+		}
+	}
+
+	if(m == 0 && segment_num == 0)
+	{
+		// we have a complete message
+		// ensure the message is sensible
+		if (recvMsgLen < 8 || pRecvMsg == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
+			return;
+		}
+
+		pnf_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time);
+	}
+	else
+	{
+		pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, sequence_num, segment_num, m, pRecvMsg, recvMsgLen);
+
+		if(rx_msg->num_segments_received == rx_msg->num_segments_expected)
+		{
+			// send the buffer on
+			uint16_t i = 0;
+			uint16_t length = 0;
+			for(i = 0; i < rx_msg->num_segments_expected; ++i)
+			{
+				length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0);
+			}
+			
+			if(pnf_p7->reassemby_buffer_size < length)
+			{
+				pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer);
+				pnf_p7->reassemby_buffer = 0;
+			}
+
+			if(pnf_p7->reassemby_buffer == 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length);
+				pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length);
+
+				if(pnf_p7->reassemby_buffer == 0)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length);
+					return;
+				}
+
+				pnf_p7->reassemby_buffer_size = length;
+			}
+			
+			uint16_t offset = 0;
+			for(i = 0; i < rx_msg->num_segments_expected; ++i)
+			{
+				if(i == 0)
+				{
+					memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length);
+					offset += rx_msg->segments[i].length;
+				}
+				else
+				{
+					memcpy(pnf_p7->reassemby_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH);
+					offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH;
+				}
+			}
+
+			
+			pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time);
+
+
+			// delete the structure
+			pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg);
+		}
+	}
+
+	pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000);
+	
+}
+void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time)
+{
+	int recvfrom_result = 0;
+	struct sockaddr_in remote_addr;
+	socklen_t remote_addr_size = sizeof(remote_addr);
+
+	do
+	{
+		// peek the header
+		uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH];
+		recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size);
+
+		if(recvfrom_result > 0)
+		{
+			// get the segment size
+			nfapi_p7_message_header_t header;
+			nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, 34, 0);
+
+			// resize the buffer if we have a large segment
+			if(header.message_length > pnf_p7->rx_message_buffer_size)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); 
+				pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length);
+				pnf_p7->rx_message_buffer_size = header.message_length;
+			}
+
+			// read the segment
+			recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, header.message_length, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size);
+
+		now_hr_time = pnf_get_current_time_hr(); //DJP - moved to here - get closer timestamp???
+
+			if(recvfrom_result > 0)
+			{
+				pnf_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time);
+			}
+		}
+		else if(recvfrom_result == 0)
+		{
+			// recv zero length message
+			recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size);
+		}
+
+		if(recvfrom_result == -1)
+		{
+			if(errno == EAGAIN || errno == EWOULDBLOCK)
+			{
+				// return to the select
+				//NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno);
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno);
+			}
+		}
+
+		// need to update the time as we would only use the value from the
+		// select
+#if 0
+// DJP - why do this here and not on return from recv???
+		now_hr_time = pnf_get_current_time_hr();
+#endif
+	}
+	while(recvfrom_result > 0);
+}
+
+int pnf_p7_message_pump(pnf_p7_t* pnf_p7)
+{
+
+	// initialize the mutex lock
+	if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno);
+		return -1;
+	}
+	
+	if(pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno);
+		return -1;
+	}	
+
+	// create the pnf p7 socket
+	if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno);
+		return -1;
+	}
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock);
+
+	// configure the UDP socket options
+	int reuseaddr_enable = 1;
+	if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed  errno: %d\n", errno);
+		return -1;
+	}
+
+/*
+	int reuseport_enable = 1;
+	if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed  errno: %d\n", errno);
+		return -1;
+	}
+*/
+		
+	int iptos_value = FAPI2_IP_DSCP << 2;
+	if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno);
+		return -1;
+	}
+
+	struct sockaddr_in addr;
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(pnf_p7->_public.local_p7_port);
+
+	if(pnf_p7->_public.local_p7_addr == 0)
+	{
+		addr.sin_addr.s_addr = INADDR_ANY;
+	}
+	else
+	{
+		//addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr);
+		if(inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n");
+		}
+	}
+
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+	if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno);
+		return -1;
+	}
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n");
+
+	while(pnf_p7->terminate == 0)
+	{
+		fd_set rfds;
+		int selectRetval = 0;
+
+		// select on a timeout and then get the message
+		FD_ZERO(&rfds);
+		FD_SET(pnf_p7->p7_sock, &rfds);
+
+		struct timeval timeout;
+		timeout.tv_sec = 1;
+		timeout.tv_usec = 0;
+
+		selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout);
+
+		uint32_t now_hr_time = pnf_get_current_time_hr();
+
+		if(selectRetval == 0)
+		{	
+			// timeout
+			continue;
+		}
+		else if (selectRetval == -1 && (errno == EINTR))
+		{
+			// interrupted by signal
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno);
+			continue;
+		}
+		else if (selectRetval == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n");
+			sleep(1);
+			continue;
+		}
+
+		if(FD_ISSET(pnf_p7->p7_sock, &rfds))
+		{
+			pnf_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time);
+		}
+	}
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n");
+
+	// close the connection and socket
+	if (close(pnf_p7->p7_sock) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno);
+	}
+
+	if(pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno);
+	}
+
+	if(pthread_mutex_destroy(&(pnf_p7->mutex)) != 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno);
+	}
+
+	return 0;
+}
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
new file mode 100644
index 0000000000..74de5e5d78
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "pnf_p7.h"
+#include <stdlib.h>
+#include <string.h>
+
+nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create()
+{
+	pnf_p7_t* _this = (pnf_p7_t*)calloc(1, sizeof(pnf_p7_t));
+
+	if(_this == 0)
+		return 0;
+
+
+	// set the default parameters
+	_this->_public.segment_size = 1400;
+	_this->max_num_segments = 8;
+	
+	_this->_public.subframe_buffer_size = 8;
+	_this->_public.timing_info_mode_periodic = 1;
+	_this->_public.timing_info_period = 32;
+	_this->_public.timing_info_mode_aperiodic = 1;
+	
+	_this->_public.checksum_enabled = 1;
+	
+	_this->_public.malloc = &malloc;
+	_this->_public.free = &free;	
+
+	_this->_public.codec_config.allocate = &malloc;
+	_this->_public.codec_config.deallocate = &free;
+
+	return &(_this->_public);
+}
+
+void nfapi_pnf_p7_config_destory(nfapi_pnf_p7_config_t* config)
+{
+	if(config == 0)
+		return ;
+
+	free(config);
+}
+
+
+
+int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+	// Make sure to set the defined trace function before using NFAPI_TRACE
+	if(config->trace)
+		nfapi_trace_g = config->trace;
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+
+	pnf_p7_message_pump(_this);
+
+	return 0;
+}
+
+int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	_this->terminate = 1;
+
+	return 0;
+}
+
+
+int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+	
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+
+	return pnf_p7_subframe_ind(_this, phy_id, sfn_sf);
+}
+
+int nfapi_pnf_p7_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_harq_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_harq_indication_t));
+}
+int nfapi_pnf_p7_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_crc_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_crc_indication_t));
+}
+int nfapi_pnf_p7_rx_ind(nfapi_pnf_p7_config_t* config, nfapi_rx_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rx_indication_t));
+}
+int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t));
+}
+int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t));
+}
+int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_sr_indication_t));
+}
+int nfapi_pnf_p7_cqi_ind(nfapi_pnf_p7_config_t* config, nfapi_cqi_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_cqi_indication_t));
+}
+int nfapi_pnf_p7_lbt_dl_ind(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_lbt_dl_indication_t));
+}
+int nfapi_pnf_p7_nb_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nb_harq_indication_t));
+}
+int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t* config, nfapi_nrach_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nrach_indication_t));
+}
+int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg)
+{
+	if(config == NULL || msg == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, msg, 0);
+}
+
diff --git a/nfapi/open-nFAPI/pnf/tests/Makefile.am b/nfapi/open-nFAPI/pnf/tests/Makefile.am
new file mode 100644
index 0000000000..4dcdea0511
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/tests/Makefile.am
@@ -0,0 +1,28 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+#nfapi unit test
+AUTOMAKE_OPTIONS=subdir-objects
+AM_CPPFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc  -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/pnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
+
+check_PROGRAMS= test_pnf
+
+test_pnf_SOURCES = pnf_cunit_main.c ../../common/src/debug.c   
+test_pnf_LDADD=$(top_builddir)/pnf/libnfapi_pnf.a $(top_builddir)/nfapi/libnfapi.a -L$(libdir) -lpthread -lrt -lsctp -lz -lcunit
+
+LOG_DRIVER = $(top_srcdir)/tap-driver.sh
+TESTS=$(check_PROGRAMS)
+EXTRA_DIST = $(TESTS)
diff --git a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c
new file mode 100644
index 0000000000..d2ab031ad4
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c
@@ -0,0 +1,2365 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "CUnit.h"
+
+#include "Basic.h"
+#include "Automated.h"
+//#include "CUnit/Console.h"
+
+#include "nfapi_interface.h"
+#include "nfapi_pnf_interface.h"
+#include "nfapi.h"
+#include <stdio.h>  // for printf
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include "debug.h"
+
+/* Test Suite setup and cleanup functions: */
+
+int init_suite(void) { return 0; }
+int clean_suite(void) { return 0; }
+
+#define MAX_PACKED_MESSAGE_SIZE	8192
+
+typedef struct phy_info
+{
+	uint8_t enabled;
+	uint16_t phy_id;
+	uint16_t sfn_sf;
+
+	pthread_t thread;
+
+	int pnf_p7_port;
+	char* pnf_p7_addr;
+
+	int vnf_p7_port;
+	char* vnf_p7_addr;
+
+	nfapi_pnf_p7_config_t* config;
+
+} phy_info_t;
+
+typedef struct pnf_info
+{
+	uint8_t num_phys;
+	phy_info_t phys[8];
+
+} pnf_info_t;
+
+phy_info_t* find_phy_info(pnf_info_t* pnf, uint16_t phy_id)
+{
+	int i = 0;
+	for(i = 0; i < 8; ++i)
+	{
+		if(pnf->phys[i].enabled == 1 && pnf->phys[i].phy_id == phy_id)
+		{
+			return &(pnf->phys[i]);
+		}
+	}
+	return 0;
+}
+
+
+
+/************* Test case functions ****************/
+
+void pnf_test_start_no_config(void) 
+{
+	int result = nfapi_pnf_start(0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void test_trace(nfapi_trace_level_t level, const char* message, ...)
+{
+	printf("%s", message);
+}
+
+
+void* pnf_test_start_thread(void* ptr)
+{
+	int result = nfapi_pnf_start((nfapi_pnf_config_t*)ptr);
+	return (void*)(intptr_t)result;
+}
+
+void* pnf_test_start_p7_thread(void* ptr)
+{
+	int result = nfapi_pnf_p7_start((nfapi_pnf_p7_config_t*)ptr);
+	return (void*)(intptr_t)result;
+}
+
+void pnf_test_start_no_connection(void) 
+{
+	char* vnf_addr = "127.127.0.1";
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	sleep(1);
+
+	nfapi_pnf_stop(config);
+
+	int* result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+}
+
+void pnf_test_start_no_ip(void) 
+{
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	sleep(2);
+
+	nfapi_pnf_stop(config);
+
+	intptr_t result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL((int)result, -1);
+}
+
+void pnf_test_start_invalid_ip(void) 
+{
+	char* vnf_addr = "not.an.ip.address";
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	sleep(2);
+
+	nfapi_pnf_stop(config);
+
+	intptr_t result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL((int)result, -1);
+}
+
+int create_p5_listen_socket(char* ip, int port)
+{
+	int p5ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	
+	struct sockaddr_in addr;
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(port);
+	addr.sin_addr.s_addr = INADDR_ANY;
+
+	// bind to the configured address and port
+	bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+
+	return p5ListenSock;
+}
+int create_p5_ipv6_listen_socket(char* ip, int port)
+{
+	struct addrinfo hints, *servinfo;
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM; // For SCTP we are only interested in SOCK_STREAM
+	hints.ai_family= AF_INET6;
+
+	char port_str[8];
+	snprintf(port_str, sizeof(port_str), "%d", port);
+	getaddrinfo(ip, port_str,  &hints, &servinfo);
+
+
+	int p5ListenSock = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP);
+	//printf("Socket result %d\n", p5ListenSock);
+	
+	// bind to the configured address and port
+	/*int bind_result = */
+	bind(p5ListenSock, servinfo->ai_addr, servinfo->ai_addrlen);
+	//printf("Bind result %d (errno:%d)\n", bind_result, errno);
+
+	freeaddrinfo(servinfo);
+
+	return p5ListenSock;
+}
+
+/*
+int wait_for_pnf_connection(int p5ListenSock)
+{
+	listen(p5ListenSock, 2);
+	socklen_t addrSize;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+
+	return p5Sock;
+}
+*/
+
+int test_param_request_called = 0;
+int test_pnf_param_request(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req)
+{
+	printf("test_pnf_param_request called.... ;-)\n");
+	
+	nfapi_pnf_param_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
+
+	resp.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG;
+	resp.pnf_param_general.nfapi_sync_mode = 2;
+	resp.pnf_param_general.location_mode = 1;
+	resp.pnf_param_general.location_coordinates[0] = 123;
+	resp.pnf_param_general.dl_config_timing = 12;
+	resp.pnf_param_general.tx_timing = 12;
+	resp.pnf_param_general.ul_config_timing = 12;
+	resp.pnf_param_general.hi_dci0_timing = 12;
+	resp.pnf_param_general.maximum_number_phys = 2;
+	resp.pnf_param_general.maximum_total_bandwidth = 100;
+	resp.pnf_param_general.maximum_total_number_dl_layers = 2;
+	resp.pnf_param_general.maximum_total_number_ul_layers = 2;
+	resp.pnf_param_general.shared_bands = 0;
+	resp.pnf_param_general.shared_pa = 0;
+	resp.pnf_param_general.maximum_total_power = -190;
+	resp.pnf_param_general.oui[0] = 88;
+/*
+	in.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG;
+	in.pnf_phy.number_of_phys = 2;
+	in.pnf_phy.phy[0].phy_config_index = 0;
+	in.pnf_phy.phy[0].number_of_rfs = 2;
+	in.pnf_phy.phy[0].rf_config[0].rf_config_index = 0;
+	in.pnf_phy.phy[0].number_of_rf_exclusions = 1;
+	in.pnf_phy.phy[0].rf_config[0].rf_config_index = 1;
+	in.pnf_phy.phy[0].downlink_channel_bandwidth_supported = 20;
+	in.pnf_phy.phy[0].uplink_channel_bandwidth_supported = 20;
+	in.pnf_phy.phy[0].number_of_dl_layers_supported = 2;
+	in.pnf_phy.phy[0].number_of_ul_layers_supported = 1;
+	in.pnf_phy.phy[0].maximum_3gpp_release_supported = 3;
+	in.pnf_phy.phy[0].nmm_modes_supported = 2;
+
+	in.pnf_rf.tl.tag = NFAPI_PNF_RF_TAG;
+	in.pnf_rf.number_of_rfs = 2;
+	in.pnf_rf.rf[0].rf_config_index = 0;
+	in.pnf_rf.rf[0].band = 1;
+	in.pnf_rf.rf[0].maximum_transmit_power = -100; 
+	in.pnf_rf.rf[0].minimum_transmit_power = -90; 
+	in.pnf_rf.rf[0].number_of_antennas_suppported = 4;
+	in.pnf_rf.rf[0].minimum_downlink_frequency = 100;
+	in.pnf_rf.rf[0].maximum_downlink_frequency = 2132;
+	in.pnf_rf.rf[0].minimum_uplink_frequency = 1231;
+	in.pnf_rf.rf[0].maximum_uplink_frequency = 123;
+
+
+	in.pnf_phy_rel10.tl.tag = NFAPI_PNF_PHY_REL10_TAG;
+	in.pnf_phy_rel10.number_of_phys = 2;
+	in.pnf_phy_rel10.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel10.phy[0].transmission_mode_7_supported = 1;
+	in.pnf_phy_rel10.phy[0].transmission_mode_8_supported = 2;
+	in.pnf_phy_rel10.phy[0].two_antenna_ports_for_pucch = 3;
+	in.pnf_phy_rel10.phy[0].transmission_mode_9_supported = 4;
+	in.pnf_phy_rel10.phy[0].simultaneous_pucch_pusch = 5;
+	in.pnf_phy_rel10.phy[0].four_layer_tx_with_tm3_and_tm4 = 6;
+
+	in.pnf_phy_rel11.tl.tag = NFAPI_PNF_PHY_REL11_TAG;
+	in.pnf_phy_rel11.number_of_phys = 2;
+	in.pnf_phy_rel11.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel11.phy[0].edpcch_supported = 1;
+	in.pnf_phy_rel11.phy[0].multi_ack_csi_reporting = 2;
+	in.pnf_phy_rel11.phy[0].pucch_tx_diversity = 3;
+	in.pnf_phy_rel11.phy[0].ul_comp_supported = 4;
+	in.pnf_phy_rel11.phy[0].transmission_mode_5_supported = 5;
+
+	in.pnf_phy_rel12.tl.tag = NFAPI_PNF_PHY_REL12_TAG;
+	in.pnf_phy_rel12.number_of_phys = 2;
+	in.pnf_phy_rel12.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel12.phy[0].csi_subframe_set = 1;
+	in.pnf_phy_rel12.phy[0].enhanced_4tx_codebook = 2;
+	in.pnf_phy_rel12.phy[0].drs_supported = 3;
+	in.pnf_phy_rel12.phy[0].ul_64qam_supported = 4;
+	in.pnf_phy_rel12.phy[0].transmission_mode_10_supported = 5;
+	in.pnf_phy_rel12.phy[0].alternative_bts_indices = 6;
+
+	in.pnf_phy_rel13.tl.tag = NFAPI_PNF_PHY_REL13_TAG;
+	in.pnf_phy_rel13.number_of_phys = 2;
+	in.pnf_phy_rel13.phy[0].phy_config_index = 0;
+	in.pnf_phy_rel13.phy[0].pucch_format4_supported = 1;
+	in.pnf_phy_rel13.phy[0].pucch_format5_supported = 2;
+	in.pnf_phy_rel13.phy[0].more_than_5_ca_support = 3;
+	in.pnf_phy_rel13.phy[0].laa_supported = 4;
+	in.pnf_phy_rel13.phy[0].laa_ending_in_dwpts_supported = 5;
+	in.pnf_phy_rel13.phy[0].laa_starting_in_second_slot_supported = 6;
+	in.pnf_phy_rel13.phy[0].beamforming_supported = 7;
+	in.pnf_phy_rel13.phy[0].csi_rs_enhancement_supported = 8;
+	in.pnf_phy_rel13.phy[0].drms_enhancement_supported = 9;
+	in.pnf_phy_rel13.phy[0].srs_enhancement_supported = 10;
+*/
+	test_param_request_called++;
+
+	nfapi_pnf_pnf_param_resp(config, &resp);
+	return 0;
+}
+
+int test_config_request_called = 0;
+int test_pnf_config_request(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req)
+{
+	printf("test_pnf_config_request called.... ;-)\n");
+
+	CU_ASSERT_EQUAL(req->pnf_phy_rf_config.tl.tag, NFAPI_PNF_PHY_RF_TAG);
+
+	if(config->user_data != 0)
+	{
+		pnf_info_t* pnf = (pnf_info_t*)(config->user_data);	
+		int i = 0;
+		for(i = 0; i < req->pnf_phy_rf_config.number_phy_rf_config_info; ++i)
+		{
+			pnf->phys[i].enabled = 1;
+			pnf->phys[i].phy_id = req->pnf_phy_rf_config.phy_rf_config[i].phy_id;
+			printf("test_pnf_config_request creating phy %d\n", pnf->phys[i].phy_id);
+
+		}
+	}
+	
+	nfapi_pnf_config_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_config_resp(config, &resp);
+
+	test_config_request_called++;
+	return 0;
+}
+int test_pnf_start_request(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req)
+{
+	printf("test_pnf_start_request called.... ;-)\n");
+
+	nfapi_pnf_start_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_START_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_start_resp(config, &resp);
+	return 0;
+}
+int test_pnf_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_stop_request_t* req)
+{
+	printf("test_pnf_stop_request called.... ;-)\n");
+
+	nfapi_pnf_stop_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_stop_resp(config, &resp);
+	return 0;
+}
+int test_param_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req)
+{
+	printf("test_param_request called.... ;-)\n");
+
+	nfapi_param_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PARAM_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+
+	if(config->user_data != 0)
+	{
+		phy_info_t* phy_info = find_phy_info((pnf_info_t*)(config->user_data), req->header.phy_id);	
+
+		resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
+		resp.nfapi_config.p7_pnf_port.value = phy_info->pnf_p7_port;
+		resp.num_tlv++;
+
+		resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
+		struct sockaddr_in pnf_p7_sockaddr;
+		pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(phy_info->pnf_p7_addr);
+		memcpy(&(resp.nfapi_config.p7_pnf_address_ipv4.address[0]), &pnf_p7_sockaddr.sin_addr.s_addr, 4);
+		resp.num_tlv++;
+	}
+
+
+
+
+	nfapi_pnf_param_resp(config, &resp);
+	return 0;
+}
+int test_config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req)
+{
+	printf("test_config_request called.... ;-)\n");
+
+	if(config->user_data != 0)
+	{
+		phy_info_t* phy_info = find_phy_info((pnf_info_t*)(config->user_data), req->header.phy_id);
+
+		if(req->nfapi_config.p7_vnf_port.tl.tag == NFAPI_NFAPI_P7_VNF_PORT_TAG)
+		{
+			phy_info->vnf_p7_port = req->nfapi_config.p7_vnf_port.value;
+			printf("vnf_p7_port %d\n", phy_info->vnf_p7_port);
+		}
+
+		if(req->nfapi_config.p7_vnf_address_ipv4.tl.tag == NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG)
+		{
+			struct sockaddr_in addr;
+			memcpy(&addr.sin_addr.s_addr, req->nfapi_config.p7_vnf_address_ipv4.address, 4);
+			char* ip = inet_ntoa(addr.sin_addr);
+			phy_info->vnf_p7_addr = ip;
+			printf("vnf_p7_addr %s\n", phy_info->vnf_p7_addr);
+		}
+
+			
+	}
+
+	nfapi_config_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_config_resp(config, &resp);
+	return 0;
+}
+int test_dl_config_req(nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req)
+{
+	printf("test_dl_config_req called.... ;-)\n");
+	return 0;
+}
+
+int test_ul_config_req(nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req)
+{
+	printf("test_ul_config_req called.... ;-)\n");
+	return 0;
+}
+int test_hi_dci0_req(nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req)
+{
+	printf("test_hi_dci0_req called.... ;-)\n");
+	return 0;
+}
+int test_tx_req(nfapi_pnf_p7_config_t* config, nfapi_tx_request_t* req)
+{
+	printf("test_tx_req called.... ;-)\n");
+	return 0;
+}
+int test_lbt_dl_config_req(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req)
+{
+	printf("test_lbt_dl_req called.... ;-)\n");
+	return 0;
+}
+int test_start_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req)
+{
+	printf("test_start_request called.... ;-)\n");
+
+
+	if(config->user_data != 0)
+	{
+		phy_info_t* phy_info = find_phy_info((pnf_info_t*)(config->user_data), req->header.phy_id);
+
+		phy_info->config = nfapi_pnf_p7_config_create();
+		phy_info->config->local_p7_port = phy_info->pnf_p7_port;
+
+		phy_info->config->remote_p7_port = phy_info->vnf_p7_port;
+		phy_info->config->remote_p7_addr = phy_info->vnf_p7_addr;
+
+		phy_info->config->dl_config_req = &test_dl_config_req;
+		phy_info->config->ul_config_req = &test_ul_config_req;
+		phy_info->config->hi_dci0_req = &test_hi_dci0_req;
+		phy_info->config->tx_req = &test_tx_req;
+		phy_info->config->lbt_dl_config_req = &test_lbt_dl_config_req;
+
+		//phy_info->config->subframe_buffer_size = 8;
+		//phy_info->config->timing_info_mode_periodic = 1;
+		//phy_info->config->timing_info_period = 32;
+		//phy_info->config->timing_info_mode_aperiodic = 1;
+
+		phy_info->config->segment_size = 1400;
+		phy_info->config->checksum_enabled = 0;
+
+
+		pthread_create(&phy_info->thread, NULL, &pnf_test_start_p7_thread, phy_info->config);
+	}
+
+	nfapi_start_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_START_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_start_resp(config, &resp);
+	return 0;
+}
+int test_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_stop_request_t* req)
+{
+	printf("test_stop_request called.... ;-)\n");
+
+	nfapi_stop_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_STOP_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_stop_resp(config, &resp);
+	return 0;
+}
+
+int send_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size, struct sockaddr* addr, socklen_t addr_size)
+{
+	char buffer[256];
+	int encoded_size = nfapi_p5_message_pack(msg, msg_size, buffer, sizeof(buffer), 0);
+	int result  = sendto(p5Sock, buffer, encoded_size, 0, addr, addr_size);
+	return result;
+}
+
+int send_p7_message(int p7Sock, nfapi_p7_message_header_t* msg, unsigned msg_size, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	char buffer[256];
+	int encoded_size = nfapi_p7_message_pack(msg, buffer, sizeof(buffer), 0);
+	int result = sendto(p7Sock, buffer, encoded_size, 0, (struct sockaddr*)addr, addr_size);
+
+	printf("send_p7_message result %d\n", result);
+	return result;
+}
+int send_p7_segmented_message(int p7Sock, nfapi_p7_message_header_t* msg, unsigned msg_size, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	char buffer[1024 * 10];
+	int encoded_size = nfapi_p7_message_pack(msg, buffer, sizeof(buffer), 0);
+
+	uint16_t segment_size = 256;
+
+	if(encoded_size < segment_size)
+	{
+		int result = sendto(p7Sock, buffer, encoded_size, 0, (struct sockaddr*)addr, addr_size);
+		return result;
+	}
+	else
+	{
+	//	printf("Segmenting p7 message %d\n", encoded_size);
+
+		uint8_t segment_count = 0;
+		uint8_t buffer2[segment_size];
+		uint32_t offset = 0;
+		uint16_t msg_size;
+		//uint8_t m = 1;
+
+		do{
+
+			if(segment_count == 0)
+			{
+				msg_size = segment_size;
+				memcpy(&buffer2[0], &buffer[0], msg_size);
+				// M = 1
+				buffer2[6] = (1 << 7) | (segment_count & 0x7F);
+
+				offset = msg_size;
+			}
+			else
+			{
+				memcpy(&buffer2[0], &buffer[0], NFAPI_P7_HEADER_LENGTH);
+
+				if(encoded_size - offset > segment_size)
+				{
+					// M = 1
+					buffer2[6] = (1 << 7) | (segment_count & 0x7F);
+					msg_size = segment_size;
+				}
+				else
+				{
+					// M = 0
+					buffer2[6] = (0 << 7) | (segment_count & 0x7F);
+					msg_size = encoded_size - offset + NFAPI_P7_HEADER_LENGTH;
+				}
+
+
+				memcpy(&buffer2[NFAPI_P7_HEADER_LENGTH], &buffer[offset], msg_size - NFAPI_P7_HEADER_LENGTH);
+			
+				offset += msg_size - NFAPI_P7_HEADER_LENGTH;
+			}
+
+			uint8_t* p = &buffer2[4];
+			push16(msg_size, &p, &buffer2[segment_size]);
+
+		//printf("Segmenting p7 message %d %di %d\n", segment_count, msg_size, offset);
+			/*int result = */sendto(p7Sock, buffer2, msg_size, 0, (struct sockaddr*)addr, addr_size);
+
+			segment_count++;
+
+		}while(offset < encoded_size);
+
+	}
+
+	return 0;
+}
+int send_p7_segmented_message_outoforder(int p7Sock, nfapi_p7_message_header_t* msg, unsigned msg_size, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	char buffer[1024 * 10];
+	int encoded_size = nfapi_p7_message_pack(msg, buffer, sizeof(buffer), 0);
+
+	uint16_t segment_size = 256;
+
+	if(encoded_size < segment_size)
+	{
+		int result = sendto(p7Sock, buffer, encoded_size, 0, (struct sockaddr*)addr, addr_size);
+		return result;
+	}
+	else
+	{
+	//	printf("Segmenting p7 message %d\n", encoded_size);
+
+		uint8_t segment_count = 0;
+		uint8_t buffer2[128][segment_size];
+		uint32_t offset = 0;
+		uint16_t msg_size[128];
+		uint8_t i = 0;
+
+		do{
+
+			if(segment_count == 0)
+			{
+				msg_size[i] = segment_size;
+				memcpy(&buffer2[i][0], &buffer[0], msg_size[i]);
+				// M = 1
+				buffer2[i][6] = (1 << 7) | (segment_count & 0x7F);
+
+				offset = msg_size[i];
+			}
+			else
+			{
+				memcpy(&buffer2[i][0], &buffer[0], NFAPI_P7_HEADER_LENGTH);
+
+				if(encoded_size - offset > segment_size)
+				{
+					// M = 1
+					buffer2[i][6] = (1 << 7) | (segment_count & 0x7F);
+					msg_size[i] = segment_size;
+				}
+				else
+				{
+					// M = 0
+					buffer2[i][6] = (0 << 7) | (segment_count & 0x7F);
+					msg_size[i] = encoded_size - offset + NFAPI_P7_HEADER_LENGTH;
+				}
+
+
+				memcpy(&buffer2[i][NFAPI_P7_HEADER_LENGTH], &buffer[offset], msg_size[i] - NFAPI_P7_HEADER_LENGTH);
+			
+				offset += msg_size[i] - NFAPI_P7_HEADER_LENGTH;
+			}
+
+			uint8_t* p = &buffer2[i][4];
+			push16(msg_size[i], &p, &buffer2[i][segment_size]);
+
+
+			segment_count++;
+			i++;
+
+		}while(offset < encoded_size);
+
+		// send all odd then send event
+		uint8_t e = 0;
+		uint8_t o = 1;
+		while(o <= i)
+		{
+			sendto(p7Sock, &buffer2[o][0], msg_size[o], 0, (struct sockaddr*)addr, addr_size);
+			o += 2;
+		}
+		while(e <= i)
+		{
+			sendto(p7Sock, &buffer2[e][0], msg_size[e], 0, (struct sockaddr*)addr, addr_size);
+			e += 2;
+		}
+
+	}
+
+	return 0;
+}
+
+int get_p7_segmented_message(int p7Sock, nfapi_p7_message_header_t* msg, unsigned _msg_size, struct sockaddr_in* addr, socklen_t addr_size, uint8_t (buffer2)[][256], uint16_t msg_size[256], uint8_t i)
+{
+	char buffer[1024 * 10];
+	int encoded_size = nfapi_p7_message_pack(msg, buffer, sizeof(buffer), 0);
+
+	uint16_t segment_size = 256;
+
+	printf("get_p7_segmented_message size %d\n", encoded_size);
+
+	if(encoded_size < segment_size)
+	{
+		msg_size[i] = encoded_size;
+		memcpy(&buffer2[i][0], &buffer[0], msg_size[i]);
+		i++;
+	}
+	else
+	{
+		uint8_t segment_count = 0;
+		uint32_t offset = 0;
+
+		do{
+
+			if(segment_count == 0)
+			{
+				msg_size[i] = segment_size;
+				memcpy(&buffer2[i][0], &buffer[0], msg_size[i]);
+				// M = 1
+				(buffer2[i][6]) = (1 << 7) | (segment_count & 0x7F);
+
+				offset = msg_size[i];
+			}
+			else
+			{
+				memcpy(&buffer2[i][0], &buffer[0], NFAPI_P7_HEADER_LENGTH);
+
+				if(encoded_size - offset > segment_size)
+				{
+					// M = 1
+					(buffer2[i][6]) = (1 << 7) | (segment_count & 0x7F);
+					msg_size[i] = segment_size;
+				}
+				else
+				{
+					// M = 0
+					(buffer2[i][6]) = (0 << 7) | (segment_count & 0x7F);
+					msg_size[i] = encoded_size - offset + NFAPI_P7_HEADER_LENGTH;
+				}
+
+
+				memcpy(&buffer2[i][NFAPI_P7_HEADER_LENGTH], &buffer[offset], msg_size[i] - NFAPI_P7_HEADER_LENGTH);
+			
+				offset += msg_size[i] - NFAPI_P7_HEADER_LENGTH;
+			}
+
+			uint8_t* p = &buffer2[i][4];
+			push16(msg_size[i], &p, &buffer2[i][segment_size]);
+
+
+			segment_count++;
+			i++;
+
+		}while(offset < encoded_size);
+
+	}
+
+	return i;
+}
+
+
+int recv_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size)
+{
+	//struct sockaddr_in addr2;
+	//socklen_t addr2len;
+	char buffer2[1024];
+	int result2 = recv(p5Sock, buffer2, sizeof(buffer2), 0); //, (struct sockaddr*)&addr2, &addr2len); 
+
+	if(result2 == -1)
+	{
+		printf("%s recvfrom failed errno:%d\n", __FUNCTION__, errno);
+	}
+	else
+	{
+		/*int unpack_result =*/ nfapi_p5_message_unpack(buffer2, result2, msg, msg_size, 0); //, sizeof(resp));
+	}
+	return 0;
+}
+
+int recv_p7_message(int p7Sock, nfapi_p7_message_header_t* msg, unsigned msg_size)
+{
+	char buffer2[2560];
+	int result2 = recvfrom(p7Sock, buffer2, sizeof(buffer2), 0, 0, 0);
+
+	if(result2 == -1)
+	{
+		printf("%s recvfrom failed errno:%d\n", __FUNCTION__, errno);
+	}
+	else
+	{
+		/*int unpack_result =*/ nfapi_p7_message_unpack(buffer2, result2, msg, msg_size, 0); //, sizeof(resp));
+	}
+	return 0;
+}
+
+int send_pnf_param_request(int p5Sock, struct sockaddr* addr, socklen_t addr_size)
+{
+	printf("%s\n", __FUNCTION__);
+	nfapi_pnf_param_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+	req.header.message_length = 0;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+	return 0;
+}
+
+int receive_pnf_param_response(int p5Sock, uint8_t error_code)
+{
+	nfapi_pnf_param_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+
+		printf("0x%x\n", resp.header.message_id);
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_PNF_PARAM_RESPONSE);
+	if(resp.header.message_id == NFAPI_PNF_PARAM_RESPONSE)
+	{
+		printf("decoded nfapi_pnf_param_response\n");
+		CU_ASSERT_EQUAL(resp.error_code, error_code);
+		if(error_code == NFAPI_MSG_OK)
+		{
+			CU_ASSERT_EQUAL(resp.pnf_param_general.tl.tag, NFAPI_PNF_PARAM_GENERAL_TAG);
+			CU_ASSERT_EQUAL(resp.pnf_param_general.nfapi_sync_mode,  2);
+			CU_ASSERT_EQUAL(resp.pnf_param_general.location_mode, 1);
+		}
+	}
+	return 0;
+}
+
+int send_pnf_config_request(int p5Sock, struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_pnf_config_request_t req;
+	req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
+	req.header.message_length = 0;
+
+	req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
+	req.pnf_phy_rf_config.number_phy_rf_config_info = 1;
+	req.pnf_phy_rf_config.phy_rf_config[0].phy_id = 0;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+	return 0;
+}
+
+int receive_pnf_config_response(int p5Sock)
+{
+	nfapi_pnf_config_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_PNF_CONFIG_RESPONSE);
+	if(resp.header.message_id == NFAPI_PNF_CONFIG_RESPONSE)
+	{
+		printf("decoded nfapi_pnf_config_response\n");
+	}
+	return 0;
+}
+
+void send_pnf_start_request(int p5Sock,  struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_pnf_start_request_t req;
+	req.header.message_id = NFAPI_PNF_START_REQUEST;
+	req.header.message_length = 0;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+
+void receive_pnf_start_response(int p5Sock)
+{
+	nfapi_pnf_start_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_PNF_START_RESPONSE);
+	if(resp.header.message_id == NFAPI_PNF_START_RESPONSE)
+	{
+		printf("decoded nfapi_pnf_start_response\n");
+	}
+}
+
+void send_pnf_stop_request(int p5Sock,  struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_pnf_stop_request_t req;
+	req.header.message_id = NFAPI_PNF_STOP_REQUEST;
+	req.header.message_length = 0;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+
+void receive_pnf_stop_response(int p5Sock)
+{
+	nfapi_pnf_stop_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_PNF_STOP_RESPONSE);
+	if(resp.header.message_id == NFAPI_PNF_STOP_RESPONSE)
+	{
+		printf("decoded nfapi_pnf_stop_response\n");
+	}
+}
+
+void send_param_request(int p5Sock, int phy_id, struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_param_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PARAM_REQUEST;
+	req.header.phy_id = phy_id;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void receive_param_response(int p5Sock)
+{
+	nfapi_pnf_stop_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_PARAM_RESPONSE);
+	if(resp.header.message_id == NFAPI_PARAM_RESPONSE)
+	{
+		printf("decoded nfapi_param_response\n");
+	}
+}
+void send_config_request(int p5Sock, int phy_id, struct sockaddr* addr, socklen_t addr_size, pnf_info_t* pnf_info)
+{
+	nfapi_config_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_CONFIG_REQUEST;
+	req.header.phy_id = phy_id;
+
+	phy_info_t* phy_info = find_phy_info(pnf_info, phy_id);
+
+	req.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NFAPI_P7_VNF_PORT_TAG;
+	req.nfapi_config.p7_vnf_port.value = phy_info->vnf_p7_port;
+	req.num_tlv++;
+
+	//req.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+	//req.num_tlv++;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void receive_config_response(int p5Sock)
+{
+	nfapi_pnf_stop_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_CONFIG_RESPONSE);
+	if(resp.header.message_id == NFAPI_CONFIG_RESPONSE)
+	{
+		printf("decoded nfapi_config_response\n");
+	}
+}
+void send_start_request(int p5Sock, int phy_id, struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_start_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_START_REQUEST;
+	req.header.phy_id = phy_id;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void receive_start_response(int p5Sock)
+{
+	nfapi_pnf_start_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_START_RESPONSE);
+	if(resp.header.message_id == NFAPI_START_RESPONSE)
+	{
+		printf("decoded nfapi_start_response\n");
+	}
+}
+void send_stop_request(int p5Sock, int phy_id, struct sockaddr* addr, socklen_t addr_size)
+{
+	nfapi_start_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_STOP_REQUEST;
+	req.header.phy_id = phy_id;
+
+	send_p5_message(p5Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+
+void receive_stop_response(int p5Sock)
+{
+	nfapi_pnf_stop_response_t resp;
+	recv_p5_message(p5Sock, &(resp.header), sizeof(resp));
+	
+	CU_ASSERT_EQUAL(resp.header.message_id, NFAPI_STOP_RESPONSE);
+	if(resp.header.message_id == NFAPI_STOP_RESPONSE)
+	{
+		printf("decoded nfapi_stop_response\n");
+	}
+}
+
+void send_dl_node_sync(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_dl_node_sync_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_DL_NODE_SYNC;
+	req.header.phy_id = phy_id;
+	req.t1 = 1977;
+	req.delta_sfn_sf = 5000;
+
+	send_p7_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void receive_ul_node_sync(int p7Sock)
+{
+	nfapi_ul_node_sync_t sync;
+	recv_p7_message(p7Sock, &(sync.header), sizeof(sync));
+	
+	CU_ASSERT_EQUAL(sync.header.message_id, NFAPI_UL_NODE_SYNC);
+	if(sync.header.message_id == NFAPI_UL_NODE_SYNC)
+	{
+		printf("decoded nfapi_ul_node_sync t1:%d t2:%d t3:%d\n",
+				sync.t1, sync.t2, sync.t3);
+	}
+}
+
+void receive_timing_info(int p7Sock)
+{
+	nfapi_timing_info_t timing_info;
+	recv_p7_message(p7Sock, &(timing_info.header), sizeof(timing_info));
+	
+	CU_ASSERT_EQUAL(timing_info.header.message_id, NFAPI_TIMING_INFO);
+	if(timing_info.header.message_id == NFAPI_TIMING_INFO)
+	{
+		printf("decoded nfapi_timing_info\n");
+	}
+	else
+	{
+		printf("decoded ?? 0x%x\n", timing_info.header.message_id);
+	}
+}
+void send_dl_config_req(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_dl_config_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+
+	send_p7_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void send_ul_config_req(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_ul_config_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+
+	send_p7_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void send_hi_dci0_req(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_hi_dci0_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_HI_DCI0_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+
+	send_p7_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+void send_tx_req(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_tx_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_TX_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+	send_p7_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+}
+
+void send_tx_req_1(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_tx_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_TX_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+	req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+	req.tx_request_body.number_of_pdus = 8;
+	req.tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)(malloc(sizeof(nfapi_tx_request_t) * 8));
+	uint8_t i = 0;
+	uint8_t test_pdu[1200];
+
+	for(i = 0; i < 8; i++)
+	{
+		req.tx_request_body.tx_pdu_list[i].pdu_length = sizeof(test_pdu);
+		req.tx_request_body.tx_pdu_list[i].pdu_index = i;
+		req.tx_request_body.tx_pdu_list[i].num_segments =1;
+		req.tx_request_body.tx_pdu_list[i].segments[0].segment_length = sizeof(test_pdu);
+		req.tx_request_body.tx_pdu_list[i].segments[0].segment_data  = (void*)&test_pdu;
+	}
+
+	send_p7_segmented_message(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+
+	free(req.tx_request_body.tx_pdu_list);
+
+}
+
+void send_tx_req_2(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+	nfapi_tx_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_TX_REQUEST;
+	req.header.phy_id = phy_id;
+	req.sfn_sf = sfn_sf;
+	req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+	req.tx_request_body.number_of_pdus = 8;
+	req.tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)(malloc(sizeof(nfapi_tx_request_t) * 8));
+	uint8_t i = 0;
+	uint8_t test_pdu[1200];
+
+	for(i = 0; i < 8; i++)
+	{
+		req.tx_request_body.tx_pdu_list[i].pdu_length = sizeof(test_pdu);
+		req.tx_request_body.tx_pdu_list[i].pdu_index = i;
+		req.tx_request_body.tx_pdu_list[i].num_segments =1;
+		req.tx_request_body.tx_pdu_list[i].segments[0].segment_length = sizeof(test_pdu);
+		req.tx_request_body.tx_pdu_list[i].segments[0].segment_data  = (void*)&test_pdu;
+	}
+
+	send_p7_segmented_message_outoforder(p7Sock, &(req.header), sizeof(req), addr, addr_size);
+
+	free(req.tx_request_body.tx_pdu_list);
+
+}
+void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size, uint16_t sfn_sf)
+{
+
+	uint8_t buffer[256][256];
+	uint16_t msg_size[256];
+	uint16_t count = 0;
+
+	{
+		nfapi_dl_config_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+		req.header.phy_id = phy_id;
+		req.header.m_segment_sequence = 34;
+		req.sfn_sf = sfn_sf;
+		req.dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+		req.dl_config_request_body.number_pdu = 8;
+		req.dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)malloc(sizeof(nfapi_dl_config_request_pdu_t) * 8);
+
+		uint8_t i = 0;
+		for(i = 0; i < 8; i++)
+		{
+			nfapi_dl_config_request_pdu_t* pdu = &(req.dl_config_request_body.dl_config_pdu_list[i]);
+			pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
+			pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
+		}
+
+
+		count = get_p7_segmented_message(p7Sock, &(req.header), sizeof(req), addr, addr_size, buffer, msg_size, count);
+	}
+
+	{
+		nfapi_ul_config_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+		req.header.phy_id = phy_id;
+		req.header.m_segment_sequence = 35;
+		req.sfn_sf = sfn_sf;
+
+		count = get_p7_segmented_message(p7Sock, &(req.header), sizeof(req), addr, addr_size, buffer, msg_size, count);
+	}
+
+	{
+		nfapi_hi_dci0_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_HI_DCI0_REQUEST;
+		req.header.phy_id = phy_id;
+		req.header.m_segment_sequence = 36;
+		req.sfn_sf = sfn_sf;
+		count = get_p7_segmented_message(p7Sock, &(req.header), sizeof(req), addr, addr_size, buffer, msg_size, count);
+	}
+
+	{
+		nfapi_tx_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_TX_REQUEST;
+		req.header.phy_id = phy_id;
+		req.header.m_segment_sequence = 37;
+		req.sfn_sf = sfn_sf;
+		req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+		req.tx_request_body.number_of_pdus = 8;
+		req.tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)(malloc(sizeof(nfapi_tx_request_t) * 8));
+		uint8_t i = 0;
+		uint8_t test_pdu[1200];
+
+		for(i = 0; i < 8; i++)
+		{
+			req.tx_request_body.tx_pdu_list[i].pdu_length = sizeof(test_pdu);
+			req.tx_request_body.tx_pdu_list[i].pdu_index = i;
+			req.tx_request_body.tx_pdu_list[i].num_segments =1;
+			req.tx_request_body.tx_pdu_list[i].segments[0].segment_length = sizeof(test_pdu);
+			req.tx_request_body.tx_pdu_list[i].segments[0].segment_data  = (void*)&test_pdu;
+		}
+
+		count = get_p7_segmented_message(p7Sock, &(req.header), sizeof(req), addr, addr_size, buffer, msg_size, count);
+	}
+
+	// send all odd then send event
+	uint8_t e = 0;
+	uint8_t o = 1;
+	while(o <= count)
+	{
+		if(msg_size[o] == 0)
+			printf("**** Sending a zero length msg %d\n", o);
+		sendto(p7Sock, &buffer[o][0], msg_size[o], 0, (struct sockaddr*)addr, addr_size);
+		o += 2;
+	}
+	while(e <= count)
+	{
+		if(msg_size[e] == 0)
+			printf("**** Sending a zero length msg %d\n", e);
+
+		sendto(p7Sock, &buffer[e][0], msg_size[e], 0, (struct sockaddr*)addr, addr_size);
+		e += 2;
+	}
+	//free(req.tx_request_body.tx_pdu_list);
+}
+
+void send_subframe_indication(phy_info_t* phy_info)
+{
+	nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf);
+}
+
+void send_harq_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_harq_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_HARQ_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_harq_ind((phy_info->config), &ind);
+}
+void recieve_harq_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_harq_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_HARQ_INDICATION);
+	if(ind.header.message_id == NFAPI_HARQ_INDICATION)
+	{
+		printf("decoded nfapi_harq_indication\n");
+	}
+	else
+	{
+		printf("decoded ?? 0x%x\n", ind.header.message_id);
+	}
+}
+
+void send_crc_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_crc_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_CRC_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_crc_ind((phy_info->config), &ind);
+
+}
+void recieve_crc_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_crc_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_CRC_INDICATION);
+	if(ind.header.message_id == NFAPI_CRC_INDICATION)
+	{
+		printf("decoded nfapi_crc_indication\n");
+	}
+}
+
+void send_rx_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_rx_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_RX_ULSCH_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_rx_ind((phy_info->config), &ind);
+}
+void recieve_rx_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_rx_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_RX_ULSCH_INDICATION);
+	if(ind.header.message_id == NFAPI_RX_ULSCH_INDICATION)
+	{
+		printf("decoded nfapi_rx_indication\n");
+	}
+}
+
+void send_rach_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_rach_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_RACH_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_rach_ind((phy_info->config), &ind);
+}
+void recieve_rach_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_rach_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_RACH_INDICATION);
+	if(ind.header.message_id == NFAPI_RACH_INDICATION)
+	{
+		printf("decoded nfapi_rach_indication\n");
+	}
+}
+
+void send_srs_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_srs_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_SRS_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_srs_ind((phy_info->config), &ind);
+}
+void recieve_srs_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_srs_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_SRS_INDICATION);
+	if(ind.header.message_id == NFAPI_SRS_INDICATION)
+	{
+		printf("decoded nfapi_srs_indication\n");
+	}
+}
+
+void send_sr_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_sr_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_RX_SR_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_sr_ind((phy_info->config), &ind);
+}
+void recieve_sr_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_sr_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_RX_SR_INDICATION);
+	if(ind.header.message_id == NFAPI_RX_SR_INDICATION)
+	{
+		printf("decoded nfapi_sr_indication\n");
+	}
+}
+
+void send_cqi_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_cqi_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_RX_CQI_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_cqi_ind((phy_info->config), &ind);
+}
+void recieve_cqi_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_cqi_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_RX_CQI_INDICATION);
+	if(ind.header.message_id == NFAPI_RX_CQI_INDICATION)
+	{
+		printf("decoded nfapi_cqi_indication\n");
+	}
+}
+
+void send_lbt_dl_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_lbt_dl_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_LBT_DL_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_lbt_dl_ind((phy_info->config), &ind);
+}
+void recieve_lbt_dl_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_lbt_dl_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_LBT_DL_INDICATION);
+	if(ind.header.message_id == NFAPI_LBT_DL_INDICATION)
+	{
+		printf("decoded nfapi_lbt_dl_indication\n");
+	}
+}
+
+void send_nb_harq_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_nb_harq_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_NB_HARQ_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_nb_harq_ind((phy_info->config), &ind);
+}
+void recieve_nb_harq_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_nb_harq_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_NB_HARQ_INDICATION);
+	if(ind.header.message_id == NFAPI_NB_HARQ_INDICATION)
+	{
+		printf("decoded nfapi_nb_harq_indication\n");
+	}
+}
+
+void send_nrach_ind(phy_info_t* phy_info, uint16_t sfn_sf)
+{
+	nfapi_nrach_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_NRACH_INDICATION;
+	ind.header.phy_id = phy_info->phy_id;
+	ind.sfn_sf = sfn_sf;
+
+	nfapi_pnf_p7_nrach_ind((phy_info->config), &ind);
+}
+void recieve_nrach_ind(int p7Sock, int phy_id, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_nrach_indication_t ind;
+	recv_p7_message(p7Sock, &(ind.header), sizeof(ind));
+	
+	CU_ASSERT_EQUAL(ind.header.message_id, NFAPI_NRACH_INDICATION);
+	if(ind.header.message_id == NFAPI_NRACH_INDICATION)
+	{
+		printf("decoded nfapi_nrach_indication\n");
+	}
+}
+
+void pnf_test_start_connect(void) 
+{
+	pnf_info_t pnf_info;
+	pnf_info.num_phys = 1;
+	pnf_info.phys[0].pnf_p7_port = 9345;
+	pnf_info.phys[0].pnf_p7_addr = "127.0.0.1";
+	pnf_info.phys[0].vnf_p7_port = 8875;
+	pnf_info.phys[0].vnf_p7_addr = "127.0.0.1";
+
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 6699;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+	printf("p5ListenSock %d %d\n", p5ListenSock, errno);
+	listen(p5ListenSock, 2);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+	config->pnf_start_req = &test_pnf_start_request;
+	config->pnf_stop_req = &test_pnf_stop_request;
+	config->param_req = &test_param_request;
+	config->config_req = &test_config_request;
+	config->start_req = &test_start_request;
+	config->stop_req = &test_stop_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("p5 connection accepted %d %d\n", p5Sock, errno);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	send_pnf_start_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_start_response(p5Sock);
+
+	send_param_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_param_response(p5Sock);
+	
+
+	send_config_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize, &pnf_info);
+	receive_config_response(p5Sock);
+
+	send_start_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_start_response(p5Sock);
+
+	sleep(2);
+
+	int p7Sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	{
+		struct sockaddr_in addr;
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(pnf_info.phys[0].vnf_p7_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+
+		bind(p7Sock, (struct sockaddr*)&addr, sizeof(addr));
+	}
+
+	printf("Sending p7 messages too %s:%d\n", pnf_info.phys[0].pnf_p7_addr, pnf_info.phys[0].pnf_p7_port);
+
+	struct sockaddr_in p7_addr;
+	p7_addr.sin_family = AF_INET;
+	p7_addr.sin_port = htons(pnf_info.phys[0].pnf_p7_port);
+	p7_addr.sin_addr.s_addr = inet_addr(pnf_info.phys[0].pnf_p7_addr);
+	socklen_t p7_addrSize = sizeof(p7_addr);
+
+	send_dl_node_sync(p7Sock, 0, &p7_addr, p7_addrSize);
+	receive_ul_node_sync(p7Sock);
+
+
+#define SFNSF(_sfn, _sf) ((_sfn << 4) + _sf)
+
+	uint16_t sfn_sf = SFNSF(500, 3); // sfn:500 sf:3
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	send_subframe_indication(&(pnf_info.phys[0]));
+
+	// should generate dummy messages
+
+	usleep(500);
+
+	sfn_sf = SFNSF(500, 4); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_ul_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_hi_dci0_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_tx_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+
+
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	// should send the cached messages
+
+	send_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_crc_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_crc_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rx_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rx_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_srs_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_srs_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_sr_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_sr_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_cqi_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_cqi_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_lbt_dl_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_lbt_dl_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_nb_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_nb_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_nrach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_nrach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+
+	// send out of window dl_config, should expect the timing info
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, SFNSF(600, 0));
+
+	sfn_sf = SFNSF(500, 5); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	receive_timing_info(p7Sock);
+
+	send_stop_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_stop_response(p5Sock);
+
+
+
+	send_pnf_stop_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_stop_response(p5Sock);
+
+	nfapi_pnf_stop(config);
+
+	int* result;
+	pthread_join(thread, (void**)&result);
+	//CU_ASSERT_NOT_EQUAL(*result, -1);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 1);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+void pnf_test_start_connect_ipv6(void) 
+{
+	pnf_info_t pnf_info;
+	pnf_info.num_phys = 1;
+	pnf_info.phys[0].pnf_p7_port = 9345;
+	pnf_info.phys[0].pnf_p7_addr = "::1";
+	pnf_info.phys[0].vnf_p7_port = 8875;
+	pnf_info.phys[0].vnf_p7_addr = "::1";
+
+	char* vnf_addr = "::1";
+	int vnf_port = 6698;
+	
+	int p5ListenSock = create_p5_ipv6_listen_socket(vnf_addr, vnf_port);
+	printf("p5ListenSock ipv6 %d %d\n", p5ListenSock, errno);
+	int listen_result = listen(p5ListenSock, 2);
+	printf("Listen result %d\n", listen_result);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+	config->pnf_start_req = &test_pnf_start_request;
+	config->pnf_stop_req = &test_pnf_stop_request;
+	config->param_req = &test_param_request;
+	config->config_req = &test_config_request;
+	config->start_req = &test_start_request;
+	config->stop_req = &test_stop_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	struct sockaddr_in6 addr;
+	socklen_t addrSize = sizeof(addr);;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("p5 connection accepted %d %d\n", p5Sock, errno);
+	
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	send_pnf_start_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_start_response(p5Sock);
+
+	send_param_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_param_response(p5Sock);
+}
+        
+void pnf_test_state_pnf_config_invalid_state()
+{
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 4546;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	listen(p5ListenSock, 2);
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("%s p5Sock %d errno %d\n", __FUNCTION__, p5Sock, errno);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_INVALID_STATE);
+	
+	nfapi_pnf_stop(config);
+
+	int* result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 1);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+
+void pnf_test_state_pnf_param_invalid_state()
+{
+	pnf_info_t pnf_info;
+
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 4547;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	listen(p5ListenSock, 2);
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	nfapi_pnf_stop(config);
+
+	int* result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 2);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+void pnf_test_p7_segmentation_test_1(void) 
+{
+	pnf_info_t pnf_info;
+	pnf_info.num_phys = 1;
+	pnf_info.phys[0].pnf_p7_port = 9348;
+	pnf_info.phys[0].pnf_p7_addr = "127.0.0.1";
+	pnf_info.phys[0].vnf_p7_port = 8878;
+	pnf_info.phys[0].vnf_p7_addr = "127.0.0.1";
+
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 6699;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+	printf("p5ListenSock %d %d\n", p5ListenSock, errno);
+	listen(p5ListenSock, 2);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+	config->pnf_start_req = &test_pnf_start_request;
+	config->pnf_stop_req = &test_pnf_stop_request;
+	config->param_req = &test_param_request;
+	config->config_req = &test_config_request;
+	config->start_req = &test_start_request;
+	config->stop_req = &test_stop_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("p5 connection accepted %d %d\n", p5Sock, errno);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	send_pnf_start_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_start_response(p5Sock);
+
+	send_param_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_param_response(p5Sock);
+	
+
+	send_config_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize, &pnf_info);
+	receive_config_response(p5Sock);
+
+	send_start_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_start_response(p5Sock);
+
+	sleep(2);
+
+	int p7Sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	{
+		struct sockaddr_in addr;
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(pnf_info.phys[0].vnf_p7_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+
+		bind(p7Sock, (struct sockaddr*)&addr, sizeof(addr));
+	}
+
+	printf("Sending p7 messages too %s:%d\n", pnf_info.phys[0].pnf_p7_addr, pnf_info.phys[0].pnf_p7_port);
+
+	struct sockaddr_in p7_addr;
+	p7_addr.sin_family = AF_INET;
+	p7_addr.sin_port = htons(pnf_info.phys[0].pnf_p7_port);
+	p7_addr.sin_addr.s_addr = inet_addr(pnf_info.phys[0].pnf_p7_addr);
+	socklen_t p7_addrSize = sizeof(p7_addr);
+
+	send_dl_node_sync(p7Sock, 0, &p7_addr, p7_addrSize);
+	receive_ul_node_sync(p7Sock);
+
+
+#define SFNSF(_sfn, _sf) ((_sfn << 4) + _sf)
+
+	uint16_t sfn_sf = SFNSF(500, 3); // sfn:500 sf:3
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	send_subframe_indication(&(pnf_info.phys[0]));
+
+	// should generate dummy messages
+
+	usleep(500);
+
+	sfn_sf = SFNSF(500, 4); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_ul_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_hi_dci0_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_tx_req_1(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+
+
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	// should send the cached messages
+
+	send_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_crc_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_crc_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rx_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rx_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_srs_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_srs_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_sr_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_sr_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_cqi_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_cqi_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_lbt_dl_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_lbt_dl_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_nb_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_nb_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_nrach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_nrach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+
+	// send out of window dl_config, should expect the timing info
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, SFNSF(600, 0));
+
+	sfn_sf = SFNSF(500, 5); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	receive_timing_info(p7Sock);
+
+	nfapi_pnf_p7_stop(pnf_info.phys[0].config);
+	int* result;
+	pthread_join(pnf_info.phys[0].thread, (void**)&result);
+	close(p7Sock);
+
+	send_stop_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_stop_response(p5Sock);
+
+	send_pnf_stop_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_stop_response(p5Sock);
+
+	nfapi_pnf_stop(config);
+
+	pthread_join(thread, (void**)&result);
+	//CU_ASSERT_NOT_EQUAL(*result, -1);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 1);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+void pnf_test_p7_segmentation_test_2(void) 
+{
+	pnf_info_t pnf_info;
+	pnf_info.num_phys = 1;
+	pnf_info.phys[0].pnf_p7_port = 9348;
+	pnf_info.phys[0].pnf_p7_addr = "127.0.0.1";
+	pnf_info.phys[0].vnf_p7_port = 8878;
+	pnf_info.phys[0].vnf_p7_addr = "127.0.0.1";
+
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 6699;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+	printf("p5ListenSock %d %d\n", p5ListenSock, errno);
+	listen(p5ListenSock, 2);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+	config->pnf_start_req = &test_pnf_start_request;
+	config->pnf_stop_req = &test_pnf_stop_request;
+	config->param_req = &test_param_request;
+	config->config_req = &test_config_request;
+	config->start_req = &test_start_request;
+	config->stop_req = &test_stop_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("p5 connection accepted %d %d\n", p5Sock, errno);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	send_pnf_start_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_start_response(p5Sock);
+
+	send_param_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_param_response(p5Sock);
+	
+
+	send_config_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize, &pnf_info);
+	receive_config_response(p5Sock);
+
+	send_start_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_start_response(p5Sock);
+
+	sleep(2);
+
+	int p7Sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	{
+		struct sockaddr_in addr;
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(pnf_info.phys[0].vnf_p7_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+
+		bind(p7Sock, (struct sockaddr*)&addr, sizeof(addr));
+	}
+
+	printf("Sending p7 messages too %s:%d\n", pnf_info.phys[0].pnf_p7_addr, pnf_info.phys[0].pnf_p7_port);
+
+	struct sockaddr_in p7_addr;
+	p7_addr.sin_family = AF_INET;
+	p7_addr.sin_port = htons(pnf_info.phys[0].pnf_p7_port);
+	p7_addr.sin_addr.s_addr = inet_addr(pnf_info.phys[0].pnf_p7_addr);
+	socklen_t p7_addrSize = sizeof(p7_addr);
+
+	send_dl_node_sync(p7Sock, 0, &p7_addr, p7_addrSize);
+	receive_ul_node_sync(p7Sock);
+
+
+#define SFNSF(_sfn, _sf) ((_sfn << 4) + _sf)
+
+	uint16_t sfn_sf = SFNSF(500, 3); // sfn:500 sf:3
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	send_subframe_indication(&(pnf_info.phys[0]));
+
+	// should generate dummy messages
+
+	usleep(500);
+
+	sfn_sf = SFNSF(500, 4); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_ul_config_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_hi_dci0_req(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+	send_tx_req_2(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+
+
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	// should send the cached messages
+
+	send_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_crc_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_crc_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rx_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rx_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_srs_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_srs_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_sr_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_sr_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_cqi_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_cqi_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_lbt_dl_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_lbt_dl_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	// send out of window dl_config, should expect the timing info
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, SFNSF(600, 0));
+
+	sfn_sf = SFNSF(500, 5); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	receive_timing_info(p7Sock);
+
+	send_stop_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_stop_response(p5Sock);
+
+	nfapi_pnf_p7_stop(pnf_info.phys[0].config);
+	int* result;
+	pthread_join(pnf_info.phys[0].thread, (void**)&result);
+	close(p7Sock);
+
+
+	send_pnf_stop_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_stop_response(p5Sock);
+
+	nfapi_pnf_stop(config);
+
+	pthread_join(thread, (void**)&result);
+	//CU_ASSERT_NOT_EQUAL(*result, -1);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 1);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+void pnf_test_p7_segmentation_test_3(void) 
+{
+	pnf_info_t pnf_info;
+	pnf_info.num_phys = 1;
+	pnf_info.phys[0].pnf_p7_port = 9348;
+	pnf_info.phys[0].pnf_p7_addr = "127.0.0.1";
+	pnf_info.phys[0].vnf_p7_port = 8878;
+	pnf_info.phys[0].vnf_p7_addr = "127.0.0.1";
+
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 6699;
+	
+	int p5ListenSock = create_p5_listen_socket(vnf_addr, vnf_port);
+	printf("p5ListenSock %d %d\n", p5ListenSock, errno);
+	listen(p5ListenSock, 2);
+
+	test_param_request_called = 0;
+	test_config_request_called = 0;
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+	config->vnf_ip_addr = vnf_addr;
+	config->vnf_p5_port = vnf_port;
+	config->pnf_param_req = &test_pnf_param_request;
+	config->pnf_config_req = &test_pnf_config_request;
+	config->pnf_start_req = &test_pnf_start_request;
+	config->pnf_stop_req = &test_pnf_stop_request;
+	config->param_req = &test_param_request;
+	config->config_req = &test_config_request;
+	config->start_req = &test_start_request;
+	config->stop_req = &test_stop_request;
+
+	config->user_data = &pnf_info;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &pnf_test_start_thread, config);
+
+	struct sockaddr_in addr;
+	socklen_t addrSize = sizeof(addr);;
+	int	p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+	printf("p5 connection accepted %d %d\n", p5Sock, errno);
+
+	send_pnf_param_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_param_response(p5Sock, NFAPI_MSG_OK);
+
+	send_pnf_config_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_config_response(p5Sock);
+	
+	send_pnf_start_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_start_response(p5Sock);
+
+	send_param_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_param_response(p5Sock);
+	
+
+	send_config_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize, &pnf_info);
+	receive_config_response(p5Sock);
+
+	send_start_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_start_response(p5Sock);
+
+	sleep(2);
+
+	int p7Sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	{
+		struct sockaddr_in addr;
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(pnf_info.phys[0].vnf_p7_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+
+		bind(p7Sock, (struct sockaddr*)&addr, sizeof(addr));
+	}
+
+	printf("Sending p7 messages too %s:%d\n", pnf_info.phys[0].pnf_p7_addr, pnf_info.phys[0].pnf_p7_port);
+
+	struct sockaddr_in p7_addr;
+	p7_addr.sin_family = AF_INET;
+	p7_addr.sin_port = htons(pnf_info.phys[0].pnf_p7_port);
+	p7_addr.sin_addr.s_addr = inet_addr(pnf_info.phys[0].pnf_p7_addr);
+	socklen_t p7_addrSize = sizeof(p7_addr);
+
+	send_dl_node_sync(p7Sock, 0, &p7_addr, p7_addrSize);
+	receive_ul_node_sync(p7Sock);
+
+
+#define SFNSF(_sfn, _sf) ((_sfn << 4) + _sf)
+
+	uint16_t sfn_sf = SFNSF(500, 3); // sfn:500 sf:3
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	send_subframe_indication(&(pnf_info.phys[0]));
+
+	// should generate dummy messages
+
+	usleep(500);
+
+	sfn_sf = SFNSF(500, 4); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+
+
+	send_dl_subframe_msgs_interleaved(p7Sock, 0, &p7_addr, p7_addrSize, sfn_sf);
+
+
+	usleep(500);
+
+	send_subframe_indication(&(pnf_info.phys[0]));
+	// should send the cached messages
+
+	send_harq_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_harq_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_crc_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_crc_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rx_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rx_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_rach_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_rach_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_srs_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_srs_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_sr_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_sr_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	send_cqi_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_cqi_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+	
+	send_lbt_dl_ind(&pnf_info.phys[0], sfn_sf);
+	recieve_lbt_dl_ind(p7Sock, 0, &p7_addr, p7_addrSize);
+
+	// send out of window dl_config, should expect the timing info
+	printf("Sending late dl config req\n");
+	send_dl_config_req(p7Sock, 0, &p7_addr, p7_addrSize, SFNSF(600, 0));
+
+	sfn_sf = SFNSF(500, 5); // sfn:500 sf:4
+	pnf_info.phys[0].sfn_sf = sfn_sf;
+	sleep(2);
+
+	printf("Sending subframe indication\n");
+	send_subframe_indication(&(pnf_info.phys[0]));
+	printf("Waitning for timing info\n");
+	receive_timing_info(p7Sock);
+
+	printf("Sending stop request\n");
+	send_stop_request(p5Sock, 0, (struct sockaddr*)&addr, addrSize);
+	receive_stop_response(p5Sock);
+
+	printf("Waiting for P7 thread to stop\n");
+	nfapi_pnf_p7_stop(pnf_info.phys[0].config);
+	int* result;
+	pthread_join(pnf_info.phys[0].thread, (void**)&result);
+	close(p7Sock);
+
+
+	send_pnf_stop_request(p5Sock, (struct sockaddr*)&addr, addrSize);
+	receive_pnf_stop_response(p5Sock);
+
+	nfapi_pnf_stop(config);
+
+	pthread_join(thread, (void**)&result);
+	//CU_ASSERT_NOT_EQUAL(*result, -1);
+	CU_ASSERT_EQUAL(test_param_request_called, 1);
+	CU_ASSERT_EQUAL(test_config_request_called, 1);
+
+	close(p5Sock);
+	close(p5ListenSock);
+
+}
+
+/************* Test Runner Code goes here **************/
+
+int main ( void )
+{
+   CU_pSuite pSuite = NULL;
+
+   /* initialize the CUnit test registry */
+   if ( CUE_SUCCESS != CU_initialize_registry() )
+      return CU_get_error();
+
+   /* add a suite to the registry */
+   pSuite = CU_add_suite( "pnf_test_suite", init_suite, clean_suite );
+   if ( NULL == pSuite ) {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+   /* add the tests to the suite */
+   if ( (NULL == CU_add_test(pSuite, "pnf_test_start_no_config", pnf_test_start_no_config)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_no_ip", pnf_test_start_no_ip)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_invalid_ip", pnf_test_start_invalid_ip)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_no_connection", pnf_test_start_no_connection)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_connect", pnf_test_start_connect)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_pnf_config_invalid_state", pnf_test_state_pnf_config_invalid_state)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_start_pnf_param_invalid_state", pnf_test_state_pnf_param_invalid_state)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_p7_segmentation_test_1", pnf_test_p7_segmentation_test_1)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_p7_segmentation_test_2", pnf_test_p7_segmentation_test_2)) ||
+        (NULL == CU_add_test(pSuite, "pnf_test_p7_segmentation_test_3", pnf_test_p7_segmentation_test_3))
+		)
+   {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+   //(NULL == CU_add_test(pSuite, "pnf_test_start_connect_ipv6", pnf_test_start_connect_ipv6)) ||
+
+   // Run all tests using the basic interface
+   CU_basic_set_mode(CU_BRM_VERBOSE);
+   CU_set_output_filename("pnf_unit_test_results.xml");
+   CU_basic_run_tests();
+
+	CU_pSuite s = CU_get_registry()->pSuite;
+	int count = 0;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+	printf("%d..%d\n", 1, count);
+
+
+
+	s = CU_get_registry()->pSuite;
+	count = 1;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			int pass = 1;
+			CU_FailureRecord* failures = CU_get_failure_list();
+			while(failures)
+			{
+				if(strcmp(failures->pSuite->pName, s->pName) == 0 &&
+				   strcmp(failures->pTest->pName, t->pName) == 0)
+				{
+					pass = 0;
+					failures = 0;
+				}
+				else
+				{
+					failures = failures->pNext;
+				}
+			}
+
+			if(pass)
+				printf("ok %d - %s:%s\n", count, s->pName, t->pName);
+			else 
+				printf("not ok %d - %s:%s\n", count, s->pName, t->pName);
+
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+   // Clean up registry and return 
+   CU_cleanup_registry();
+   return CU_get_error();
+
+}
diff --git a/nfapi/open-nFAPI/pnf_sim/Makefile.am b/nfapi/open-nFAPI/pnf_sim/Makefile.am
new file mode 100644
index 0000000000..c8d9d8ddd4
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf_sim/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AUTOMAKE_OPTIONS=subdir-objects
+AM_CPPFLAGS = -I$(top_srcdir)/pnf_sim/inc -I$(top_srcdir)/sim_common/inc -I$(top_srcdir)/pnf/public_inc  -I$(top_srcdir)/common/inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/nfapi/inc $(XML_CFLAGS) -g
+AM_CXXFLAGS = -I$(top_srcdir)/pnf_sim/inc -I$(top_srcdir)/sim_common/inc -I$(top_srcdir)/pnf/public_inc  -I$(top_srcdir)/common/inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/nfapi/inc $(XML_CFLAGS) -std=c++11 $(BOOST_CPPFLAGS) -g
+bin_PROGRAMS = pnfsim
+pnfsim_SOURCES = src/main.cpp src/fapi_stub.cpp
+LDADD= $(top_builddir)/pnf/libnfapi_pnf.a $(top_builddir)/common/libnfapi_common.a $(top_builddir)/nfapi/libnfapi.a $(top_builddir)/sim_common/libnfapi_sim_common.a -L$(libdir) -lpthread -lrt -lsctp  -lz 
diff --git a/nfapi/open-nFAPI/pnf_sim/inc/fapi_interface.h b/nfapi/open-nFAPI/pnf_sim/inc/fapi_interface.h
new file mode 100644
index 0000000000..b1d44eab8b
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf_sim/inc/fapi_interface.h
@@ -0,0 +1,1800 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _FAPI_INTERFACE_H_
+#define _FAPI_INTERFACE_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef signed char		int8_t;
+typedef unsigned char	uint8_t;
+typedef signed short	int16_t;
+typedef unsigned short	uint16_t;
+typedef signed int		int32_t;
+typedef unsigned int	uint32_t;
+
+#define FAPI_PARAM_REQUEST									0x00
+#define FAPI_PARAM_RESPONSE									0x01
+#define FAPI_CONFIG_REQUEST									0x02
+#define FAPI_CONFIG_RESPONSE								0x03
+#define FAPI_START_REQUEST									0x04
+#define FAPI_STOP_REQUEST									0x05
+#define FAPI_STOP_INDICATION								0x06
+#define FAPI_UE_CONFIG_REQUEST								0x07
+#define FAPI_UE_CONFIG_RESPONSE								0x08
+#define FAPI_ERROR_INDICATION								0x09
+#define FAPI_UE_RELEASE_REQUEST								0x0A
+#define FAPI_UE_RELEASE_RESPONSE							0x0B
+#define FAPI_DL_CONFIG_REQUEST								0x80
+#define FAPI_UL_CONFIG_REQUEST								0x81
+#define FAPI_SUBFRAME_INDICATION							0x82
+#define FAPI_HI_DCI0_REQUEST								0x83
+#define FAPI_TX_REQUEST										0x84
+#define FAPI_HARQ_INDICATION								0x85
+#define FAPI_CRC_INDICATION									0x86
+#define FAPI_RX_ULSCH_INDICATION							0x87
+#define FAPI_RACH_INDICATION								0x88
+#define FAPI_SRS_INDICATION									0x89
+#define FAPI_RX_SR_INDICATION								0x8A
+#define FAPI_RX_CQI_INDICATION								0x8B
+#define FAPI_LBT_DL_CONFIG_REQUEST							0x8C
+#define FAPI_LBT_DL_INDICATION								0x8D
+#define FAPI_NB_HARQ_INDICATION								0x8E
+#define FAPI_NRACH_INDICATION								0x8F
+
+
+
+
+#define FAPI_SUBFRAME_DUPLEX_MODE_TAG						0x01
+#define FAPI_SUBFRAME_PCFICH_POWER_OFFSET_TAG				0x02
+#define FAPI_SUBFRAME_PB_TAG								0x03
+#define FAPI_SUBFRAME_DL_CYCLIC_PREFIX_TYPE_TAG				0x04
+#define FAPI_SUBFRAME_UL_CYCLIC_PREFIX_TYPE_TAG				0x05
+#define FAPI_RF_DL_CHANNEL_BANDWIDTH_TAG					0x0A
+#define FAPI_RF_UL_CHANNEL_BANDWIDTH_TAG					0x0B
+#define FAPI_RF_REFERENCE_SIGNAL_POWER_TAG					0x0C
+#define FAPI_RF_TX_ANTENNA_PORTS_TAG						0x0D
+#define FAPI_RF_RX_ANTENNA_PORTS_TAG						0x0E
+#define FAPI_PHICH_RESOURCE_TAG								0x14
+#define FAPI_PHICH_DURATION_TAG								0x15
+#define FAPI_PHICH_POWER_OFFSET_TAG							0x16
+#define FAPI_SCH_PRIMARY_SYNC_SIGNAL_TAG					0x1E
+#define FAPI_SCH_SECONDARY_SYNC_SIGNAL_TAG					0x1F
+#define FAPI_SCH_PHYSICAL_CELL_ID_TAG						0x20
+#define FAPI_PRACH_CONFIGURATION_INDEX_TAG					0x28
+#define FAPI_PRACH_ROOT_SEQUENCE_INDEX_TAG					0x29
+#define FAPI_PRACH_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG	0x2A
+#define FAPI_PRACH_HIGH_SPEED_FLAG_TAG						0x2B
+#define FAPI_PRACH_FREQUENCY_OFFSET_TAG						0x2C
+#define FAPI_PUSCH_HOPPING_MODE_TAG							0x32
+#define FAPI_PUSCH_HOPPING_OFFSET_TAG						0x33
+#define FAPI_PUSCH_NUMBER_OF_SUBBANDS_TAG					0x34
+#define FAPI_PUCCH_DELTA_PUCCH_SHIFT_TAG					0x3C
+#define FAPI_PUCCH_N_CQI_RB_TAG								0x3D
+#define FAPI_PUCCH_N_AN_CS_TAG								0x3E
+#define FAPI_PUCCH_N1_PUCCH_AN_TAG							0x3F
+#define FAPI_SRS_BANDWIDTH_CONFIGURATION_TAG				0x46
+#define FAPI_SRS_MAX_UP_PTS_TAG								0x47
+#define FAPI_SRS_SUBFRAME_CONFIGURATION_TAG					0x48
+#define FAPI_SRS_ACK_NACK_SRS_SIMULTANEOUS_TX_TAG			0x49
+#define FAPI_UL_REF_SIG_UPLINK_RS_HOPPING_TAG				0x50
+#define FAPI_UL_REF_SIG_GROUP_ASSIGNMENT_TAG				0x51
+#define FAPI_UL_REF_SIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG			0x52
+#define FAPI_TDD_SUBFRAME_ASSIGNMENT_TAG					0x5A
+#define FAPI_TDD_SPECIAL_SUBFRAME_PATTERNS_TAG				0x5B
+
+#define FAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG	0x64
+#define FAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG	0x65
+#define FAPI_LAA_CONFIG_PD_THRESHOLD_TAG					0x66
+#define FAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG				0x67
+#define FAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG				0x68
+#define FAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG			0x69
+#define FAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG		0x6A
+#define FAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG		0x6B
+
+#define FAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLED_R13_TAG						0x78
+#define FAPI_EMTC_CONFIG_PRACH_CAT_M_ROOT_SEQUENCY_INDEX_TAG					0x79
+#define FAPI_EMTC_CONFIG_PRACH_CAT_M_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG	0x7A
+#define FAPI_EMTC_CONFIG_PRACH_CAT_M_HIGH_SPEED_FLAG_TAG						0x7B
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG							0x7C
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG				0x7D
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG					0x7E
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG	0x7F
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG		0x80
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG					0x81
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG					0x82
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG							0x83
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG				0x84
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG					0x85
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG	0x86
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG		0x87
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG					0x88
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG					0x89
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG							0x8A
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG				0x8B
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG					0x8C
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG	0x8D
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG		0x8E
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG					0x8F
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG					0x90
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG							0x91
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG				0x92
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG					0x93
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG	0x94
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG		0x95
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG					0x96
+#define FAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG					0x97
+#define FAPI_EMTC_CONFIG_PRACH_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG	0x98
+#define FAPI_EMTC_CONFIG_PRACH_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG	0x99
+
+#define FAPI_NB_IOT_OPERATING_MODE_TAG											0xA5
+#define FAPI_NB_IOT_ANCHOR_TAG													0xA6
+#define FAPI_NB_IOT_PRB_INDEX_TAG												0xA7
+#define FAPI_NB_IOT_CONTROL_REGION_SIZE_TAG										0xA8
+#define FAPI_NB_IOT_ASSUMED_CRS_APS_TAG											0xA9
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_ENABLE_TAG									0xAA
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_SF_PERIODCITY_TAG							0xAB
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_START_TIME_TAG								0xAC
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_SUBCARRIER_OFFSET_TAG						0xAD
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_NUMBER_OF_SUBCARRIERS_TAG					0xAE
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_CP_LENGTH_TAG								0xAD
+#define FAPI_NB_IOT_NPRACH_CONFIG_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG		0xB0
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_ENABLE_TAG									0xB1
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_SF_PERIODCITY_TAG							0xB2
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_START_TIME_TAG								0xB3
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_SUBCARRIER_OFFSET_TAG						0xB4
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_NUMBER_OF_SUBCARRIERS_TAG					0xB5
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_CP_LENGTH_TAG								0xB6
+#define FAPI_NB_IOT_NPRACH_CONFIG_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG		0xB7
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_ENABLE_TAG									0xB8
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_SF_PERIODCITY_TAG							0xB9
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_START_TIME_TAG								0xBA
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_SUBCARRIER_OFFSET_TAG						0xBB
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_NUMBER_OF_SUBCARRIERS_TAG					0xBC
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_CP_LENGTH_TAG								0xBD
+#define FAPI_NB_IOT_NPRACH_CONFIG_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG		0xBE
+
+#define FAPI_NB_IOT_THREE_TONE_BASE_SEQUENCE_TAG			0xBF
+#define FAPI_NB_IOT_SIX_TONE_BASE_SEQUENCE_TAG				0xC0
+#define FAPI_NB_IOT_TWELVE_TONE_BASE_SEQUENCE_TAG			0xC1
+#define FAPI_NB_IOT_THREE_TONE_CYCLIC_SHIFT_TAG				0xC2
+#define FAPI_NB_IOT_SIX_TONE_CYCLIC_SHIFT_TAG				0xC3
+#define FAPI_NB_IOT_DL_GAP_CONFIG_ENABLE_TAG				0xC4
+#define FAPI_NB_IOT_DL_GAP_THRESHOLD_TAG					0xC5
+#define FAPI_NB_IOT_DL_GAP_PERIODICITY_TAG					0xC6
+#define FAPI_NB_IOT_DL_GAP_DURATION_COEFFICIENT_TAG			0xC7
+
+//...
+#define FAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG		0xC8
+#define FAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG		0xC9
+#define FAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG		0xCA
+#define FAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG		0xCB
+#define FAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG	0xCC
+#define FAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG		0xCD
+#define FAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG			0xCE
+#define FAPI_PHY_CAPABILITIES_LAA_SUPPORT_TAG				0xD1
+#define FAPI_PHY_CAPABILITIES_LAA_PD_SENSING_LBT_SUPPORT_TAG 0xD2
+#define FAPI_PHY_CAPABILITIES_LAA_MULTI_CARRIER_LBT_SUPPORT_TAG	0xD3
+#define FAPI_PHY_CAPABILITIES_LAA_PARTIAL_SF_SUPPORT_TAG	0xD4
+#define FAPI_PHY_CAPABILITIES_NB_IOT_SUPPORT_TAG			0xD5
+#define FAPI_PHY_CAPABILITIES_NB_IOT_OPERATING_MODE_CAPABILITY_TAG 0xD6
+
+#define FAPI_PHY_CAPABILITIES_DATA_REPORT_MODE_TAG			0xF0
+#define FAPI_PHY_SFN_SF_TAG									0xF1
+#define FAPI_PHY_STATE_TAG									0xFA
+
+#define FAPI_MSG_OK											0x0
+#define FAPI_MSG_INVALID_STATE								0x1
+#define FAPI_MSG_INVALID_CONFIG								0x2
+#define FAPI_MSG_SFN_OUT_OF_SYNC							0x3
+#define FAPI_MSG_SUBFRAME_ERR								0x4
+#define FAPI_MSG_BCH_MISSING								0x5
+#define FAPI_MSG_INVALID_SFN								0x6
+#define FAPI_MSG_HI_ERR										0x7
+#define FAPI_MSG_TX_ERR										0x8
+
+#define FAPI_MSG_LBT_NO_PDU_IN_DL_REQ						0x9
+#define FAPI_MSG_LBT_NO_VALID_CONFIG_REQ_RECIEVED			0xA
+#define FAPI_MSG_FAPI_E_LBT_SF_SFN_PASSED_END_SF_SFN		0xB
+#define FAPI_MSG_FAPI_E_LBT_OVERLAP							0xC
+#define FAPI_MSG_BCH_PRESENT								0xD
+#define FAPI_MSG_NBIOT_UNEXPECTED_REQ						0xE
+
+
+// TODO : Work out what the correct maximums should be
+
+// Number of UL/DL configurations, I, as defined by 36.212 section 5.3.3.1.4
+// todo : work out what the max is
+#define FAPI_MAX_UL_DL_CONFIGURATIONS						4
+#define FAPI_MAX_NUM_PHYSICAL_ANTENNAS						4
+#define FAPI_MAX_NUM_SCHEDULED_UES							8
+#define FAPI_MAX_NUM_SUBBANDS								8
+#define FAPI_MAX_ANTENNA_PORT_COUNT							2
+	
+	
+typedef struct {
+	uint8_t message_id;
+	uint16_t length;
+} fapi_header_t;
+
+typedef struct {
+	uint8_t tag;
+	uint8_t length;
+	uint16_t value;
+} fapi_tlv_t;
+
+typedef struct {
+	fapi_header_t header;
+} fapi_param_req_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint8_t error_code;
+	uint8_t number_of_tlvs;
+	fapi_tlv_t tlvs[255];
+} fapi_param_resp_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint8_t number_of_tlvs;
+	fapi_tlv_t tlvs[255];
+} fapi_config_req_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint8_t error_code;
+	uint8_t number_of_invalid_tlvs;
+	uint8_t number_of_missing_tlvs;
+	fapi_tlv_t tlvs[255];
+} fapi_config_resp_t;
+
+typedef struct {
+	fapi_header_t header;
+} fapi_start_req_t;
+
+typedef struct {
+	fapi_header_t header;
+} fapi_stop_req_t;
+
+typedef struct {
+	fapi_header_t header;
+} fapi_stop_ind_t;
+
+typedef struct {
+	uint16_t received_sfn_sf;
+	uint16_t expected_sfn_sf;
+} fapi_sfn_out_of_sync_error_ind_t;
+
+typedef struct {
+	uint16_t received_sfn_sf;
+	uint16_t expected_sfn_sf;
+} fapi_invalid_sfn_error_ind_t;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t direction;
+	uint16_t rnti;
+	uint8_t pdu_type;
+} fapi_pdu_error_ind_t;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t phich_lowest_ul_rb_index;
+} fapi_hi_error_ind_t;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t pdu_index;
+} fapi_tx_error_ind_t;	
+
+typedef struct {
+	fapi_header_t header;
+	uint8_t message_id;
+	uint8_t error_code;
+	union 
+	{
+		fapi_sfn_out_of_sync_error_ind_t	out_of_sync_err;
+		fapi_invalid_sfn_error_ind_t		invalid_sfn_err;
+		fapi_pdu_error_ind_t				pdu_err;
+		fapi_hi_error_ind_t					hi_err;
+		fapi_tx_error_ind_t					tx_err;	
+	};
+} fapi_error_ind_t;
+
+typedef struct {
+	uint32_t handle;
+	uint16_t rnti;
+} fapi_rx_ue_information_t;
+
+typedef struct {
+	uint8_t ul_cqi;
+	uint8_t channel;
+} fapi_ul_cqi_information_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+} fapi_subframe_ind_t;
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+} fapi_harq_ind_rel8_tdd_harq_data_bundling_t;
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+	uint8_t value_2;
+	uint8_t value_3;
+} fapi_harq_ind_rel8_tdd_harq_data_multiplexing_t;
+
+typedef struct { 
+	uint8_t value_0;
+} fapi_harq_ind_rel8_tdd_harq_data_special_bundling_t;
+
+typedef struct { 
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		fapi_harq_ind_rel8_tdd_harq_data_bundling_t			bundling;
+		fapi_harq_ind_rel8_tdd_harq_data_multiplexing_t		multiplex;
+		fapi_harq_ind_rel8_tdd_harq_data_special_bundling_t	special_bundling;
+	} harq_data;
+} fapi_harq_ind_rel8_tdd_pdu_t;
+
+typedef struct { 
+	uint8_t value_0;
+} fapi_harq_ind_rel8_tdd_harq_data_t;
+
+
+typedef struct {
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		fapi_harq_ind_rel8_tdd_harq_data_t	bundling;
+		fapi_harq_ind_rel8_tdd_harq_data_t	multiplex;
+		fapi_harq_ind_rel8_tdd_harq_data_special_bundling_t	special_bundling;
+		fapi_harq_ind_rel8_tdd_harq_data_t	channel_selection;
+		fapi_harq_ind_rel8_tdd_harq_data_t	format_3;
+	} harq_data[21];
+} fapi_harq_ind_rel9_tdd_pdu_t;
+
+typedef struct {
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	union{
+		fapi_harq_ind_rel8_tdd_harq_data_t					bundling;
+		fapi_harq_ind_rel8_tdd_harq_data_t					multiplex;
+		fapi_harq_ind_rel8_tdd_harq_data_special_bundling_t	special_bundling;
+		fapi_harq_ind_rel8_tdd_harq_data_t					channel_selection;
+		fapi_harq_ind_rel8_tdd_harq_data_t			format_3;
+		fapi_harq_ind_rel8_tdd_harq_data_t			format_4;
+		fapi_harq_ind_rel8_tdd_harq_data_t			format_5;
+	} harq_data[22];
+} fapi_harq_ind_rel13_tdd_pdu_t;
+
+typedef struct {
+	uint8_t harq_tb_1;
+	uint8_t harq_tb_2;
+} fapi_harq_ind_rel8_fdd_pdu_t;
+
+typedef struct {
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	uint8_t harq_tb_n[10];
+} fapi_harq_ind_rel9_fdd_pdu_t;
+
+typedef struct {
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	uint8_t harq_tb_n[22];
+} fapi_harq_ind_rel13_fdd_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	union {
+		fapi_harq_ind_rel8_tdd_pdu_t	rel8_tdd_pdu;
+		fapi_harq_ind_rel9_tdd_pdu_t	rel9_tdd_pdu;
+		fapi_harq_ind_rel13_tdd_pdu_t	rel13_tdd_pdu;
+		fapi_harq_ind_rel8_fdd_pdu_t	rel8_fdd_pdu;
+		fapi_harq_ind_rel9_fdd_pdu_t	rel9_fdd_pdu;
+		fapi_harq_ind_rel13_fdd_pdu_t	rel13_fdd_pdu;
+	};
+	fapi_ul_cqi_information_t ul_cqi_info;
+} fapi_harq_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_harqs;
+	fapi_harq_ind_pdu_t pdus[32];
+} fapi_harq_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_harq_ind_body_t body;
+} fapi_harq_ind_t;
+
+typedef struct {
+	uint8_t crc_flag;
+} fapi_crc_ind_rel8_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	fapi_crc_ind_rel8_pdu_t rel8_pdu;
+} fapi_crc_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_crcs;
+	fapi_crc_ind_pdu_t pdus[32];
+} fapi_crc_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_crc_ind_body_t body;
+} fapi_crc_ind_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint16_t timing_advance;
+} fapi_rx_ulsch_ind_rel8_pdu_t;
+
+typedef struct {
+	uint16_t timing_advance_r9;
+} fapi_rx_ulsch_ind_rel9_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	fapi_rx_ulsch_ind_rel8_pdu_t rel8_pdu;
+	fapi_rx_ulsch_ind_rel9_pdu_t rel9_pdu;
+} fapi_rx_ulsch_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_pdus;
+	fapi_rx_ulsch_ind_pdu_t pdus[32];
+	void* data[32];
+} fapi_rx_ulsch_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_rx_ulsch_ind_body_t body;
+} fapi_rx_ulsch_ind_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t ri;
+	uint16_t timing_advance;
+} fapi_rx_cqi_ind_rel8_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t number_of_cc_reported;
+	uint8_t ri[5];
+	uint16_t timing_advance;
+	uint16_t timing_advance_r9;
+} fapi_rx_cqi_ind_rel9_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	fapi_rx_cqi_ind_rel8_pdu_t rel8_pdu;
+	fapi_rx_cqi_ind_rel9_pdu_t rel9_pdu;
+	fapi_ul_cqi_information_t ul_cqi_info;
+} fapi_rx_cqi_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_pdus;
+	fapi_rx_cqi_ind_pdu_t pdus[32];
+	uint8_t* data[32];
+} fapi_rx_cqi_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_rx_cqi_ind_body_t body;
+} fapi_rx_cqi_ind_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	fapi_ul_cqi_information_t ul_cqi_info;
+} fapi_rx_sr_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_srs;
+	fapi_rx_sr_ind_pdu_t pdus[32];
+} fapi_rx_sr_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_rx_sr_ind_body_t body;
+} fapi_rx_sr_ind_t;
+
+typedef struct {
+	uint16_t rnti;
+	uint8_t preamble;
+	uint16_t timing_advance;
+} fapi_rach_ind_pdu_rel8_t;
+
+typedef struct {
+	uint16_t timing_advance_r9;
+} fapi_rach_ind_pdu_rel9_t;
+
+typedef struct {
+	uint8_t rach_resource_type;
+} fapi_rach_ind_pdu_rel13_t;
+
+typedef struct {
+	fapi_rach_ind_pdu_rel8_t rel8_pdu;
+	fapi_rach_ind_pdu_rel9_t rel9_pdu;
+	fapi_rach_ind_pdu_rel13_t rel13_pdu;
+} fapi_rach_ind_pdu_t;
+
+typedef struct {
+	uint8_t number_of_preambles;
+	fapi_rach_ind_pdu_t pdus[32];
+} fapi_rach_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_rach_ind_body_t body;
+} fapi_rach_ind_t;
+
+
+typedef struct {
+	uint16_t doppler_estimation;
+	uint16_t timing_advance;
+	uint8_t number_of_resource_blocks;
+	uint8_t rb_start;
+	uint8_t snr[100];
+} fapi_srs_ind_rel8_pdu_t;
+
+typedef struct { 
+	uint16_t timing_advance_r9;
+} fapi_srs_ind_rel9_pdu_t;
+
+typedef struct { 
+	uint8_t uppts_symbol;
+} fapi_srs_ind_rel10_tdd_pdu_t;
+
+typedef struct {
+	uint16_t ul_rtoa;
+} fapi_srs_ind_rel11_pdu_t;
+
+typedef struct {
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_atennas;
+	struct {
+		uint8_t subband_index;
+		uint16_t channel[FAPI_MAX_NUM_PHYSICAL_ANTENNAS];
+	} subands[FAPI_MAX_NUM_SUBBANDS];
+} fapi_ttd_channel_measurement_t;
+
+typedef struct {
+	fapi_rx_ue_information_t		rx_ue_info;
+	fapi_srs_ind_rel8_pdu_t 		rel8_pdu;
+	fapi_srs_ind_rel9_pdu_t 		rel9_pdu;
+	fapi_srs_ind_rel10_tdd_pdu_t	rel10_tdd_pdu;
+	fapi_srs_ind_rel11_pdu_t		rel11_pdu;
+	fapi_ttd_channel_measurement_t tdd_channel_measurement;
+} fapi_srs_ind_pdu_t;
+
+typedef struct {
+	uint8_t number_of_ues;
+	fapi_srs_ind_pdu_t pdus[32];
+} fapi_srs_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_srs_ind_body_t body;
+} fapi_srs_ind_t;
+
+
+typedef struct {
+	uint32_t handle;
+	uint32_t result;
+	uint32_t lte_txop_symbols;
+	uint32_t initial_partial_sf;
+} fapi_lbt_dl_pdsch_rsp_rel13_pdu_t;
+
+typedef struct {
+	fapi_lbt_dl_pdsch_rsp_rel13_pdu_t	rel13_pdu;
+} fapi_lbt_dl_pdsch_rsp_pdu_t;
+
+typedef struct {
+	uint32_t handle;
+	uint32_t result;
+} fapi_lbt_dl_drs_rsp_rel13_pdu_t;
+
+typedef struct {
+	fapi_lbt_dl_drs_rsp_rel13_pdu_t 	rel13_pdu;
+} fapi_lbt_dl_drs_rsp_pdu_t;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		fapi_lbt_dl_pdsch_rsp_pdu_t		lbt_pdsch_rsp_pdu;
+		fapi_lbt_dl_drs_rsp_pdu_t		lbt_drs_rsp_pdu;
+	};
+} fapi_lbt_dl_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_pdus;
+	fapi_lbt_dl_ind_pdu_t pdus[32];
+} fapi_lbt_dl_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_lbt_dl_ind_body_t body;
+} fapi_lbt_dl_ind_t;
+
+typedef struct {
+	uint8_t harq_tb1;
+} fapi_nb_harq_ind_rel13_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	union {
+		fapi_nb_harq_ind_rel13_pdu_t	rel13_pdu;
+	};
+	fapi_ul_cqi_information_t ul_cqi_info;
+} fapi_nb_harq_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_harqs;
+	fapi_nb_harq_ind_pdu_t pdus[32];
+} fapi_nb_harq_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_nb_harq_ind_body_t body;
+} fapi_nb_harq_ind_t;
+
+typedef struct {
+	uint16_t rnti;
+	uint8_t initial_sc;
+	uint16_t timing_advance;
+	uint8_t nrach_cs_level;
+} fapi_nrach_ind_rel13_pdu_t;
+
+typedef struct {
+	fapi_rx_ue_information_t rx_ue_info;
+	union {
+		fapi_nrach_ind_rel13_pdu_t	rel13_pdu;
+	};
+	fapi_ul_cqi_information_t ul_cqi_info;
+} fapi_nrach_ind_pdu_t;
+
+typedef struct {
+	uint16_t number_of_initial_scs_detected;
+	fapi_nrach_ind_pdu_t pdus[32];
+} fapi_nrach_ind_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_nrach_ind_body_t body;
+} fapi_nrach_ind_t;
+
+//------------------------------------------------------------------------------
+
+typedef struct {
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs_1;
+	uint8_t redundancy_version_1;
+	uint8_t new_data_indicator_1;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t mcs_2;
+	uint8_t redundancy_version_2;
+	uint8_t new_data_indictor_2;
+	uint8_t harq_process;
+	uint8_t tpmi;
+	uint8_t pmi;
+	uint8_t precoding_information;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index;
+	uint8_t n_gap;
+	uint8_t transport_block_size_index;
+	uint8_t downlink_power_offset;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t rnti_type;
+	uint16_t transmission_power;
+} fapi_dl_config_dci_rel8_pdu_t;
+
+typedef struct {
+	uint8_t mcch_flag;
+	uint8_t mcch_change_notification;
+	uint8_t scrambling_identity;
+} fapi_dl_config_dci_rel9_pdu_t;
+
+typedef struct {
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t antenna_ports_scrambling_and_layers;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_dl_rb;
+} fapi_dl_config_dci_rel10_pdu_t;
+
+typedef struct {
+	uint8_t harq_ack_resource_offset;
+	uint8_t pdsch_re_mapping_quasi_co_location_indicator;
+} fapi_dl_config_dci_rel11_pdu_t;
+
+typedef struct {
+	uint8_t primary_cell_type;
+	uint8_t ul_dl_configuration_flag;
+	uint8_t number_ul_dl_configurations;
+	uint8_t ul_dl_configuration_indication[FAPI_MAX_UL_DL_CONFIGURATIONS];
+} fapi_dl_config_dci_rel12_pdu_t;
+
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t scheduled_ues;
+	uint16_t precoding_value[FAPI_MAX_NUM_PHYSICAL_ANTENNAS][FAPI_MAX_NUM_SCHEDULED_UES];
+} fapi_dl_config_dci_dl_tpm_subband_info_t;
+
+typedef struct {
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_antennas;
+	fapi_dl_config_dci_dl_tpm_subband_info_t subband_info[FAPI_MAX_NUM_SUBBANDS];
+} fapi_dl_config_dci_dl_tpm_t;
+
+typedef struct {
+	uint8_t laa_end_partial_sf_flag;
+	uint8_t laa_end_partial_sf_configuration;
+	uint8_t initial_lbt_sf;
+	uint8_t codebook_size_determination;
+	uint8_t drms_table_flag;
+	uint8_t tpm_struct_flag;
+	fapi_dl_config_dci_dl_tpm_t tpm;
+} fapi_dl_config_dci_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_dci_rel8_pdu_t 	rel8_pdu;
+	fapi_dl_config_dci_rel9_pdu_t 	rel9_pdu;
+	fapi_dl_config_dci_rel10_pdu_t	rel10_pdu;
+	fapi_dl_config_dci_rel11_pdu_t	rel11_pdu;
+	fapi_dl_config_dci_rel12_pdu_t	rel12_pdu;
+	fapi_dl_config_dci_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_dci_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+} fapi_dl_config_bch_rel8_pdu_t;
+
+typedef struct {
+	fapi_dl_config_bch_rel8_pdu_t rel8_pdu;
+} fapi_dl_config_bch_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint16_t transmission_power;
+	uint16_t mbsfn_area_id;
+} fapi_dl_config_mch_rel8_pdu_t;
+
+typedef struct {
+	fapi_dl_config_mch_rel8_pdu_t rel8_pdu;
+} fapi_dl_config_mch_pdu_t;
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t num_atennas;
+	uint16_t bf_value[8];
+} fapi_dl_config_bf_vector_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint8_t redundacy_version;
+	uint8_t transport_blocks;
+	uint8_t transport_block_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t nunber_of_subands;
+	uint8_t codebook_index[13];
+	uint8_t ue_category_capacity;
+	uint8_t p_a;
+	uint8_t delta_power_offset_index;
+	uint8_t n_gap;
+	uint8_t n_prb;
+	uint8_t transmission_mode;
+	uint8_t num_bf_prb_per_subband;
+	uint8_t num_bf_vecitor;
+	fapi_dl_config_bf_vector_t bf_vector[8];
+} fapi_dl_config_dlsch_rel8_pdu_t;
+
+typedef struct {
+	uint8_t nscid;
+} fapi_dl_config_dlsch_rel9_pdu_t;
+
+typedef struct {
+	uint8_t csi_rs_flag;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_nzp_configuration;
+	uint8_t csi_rs_resource_config[4];
+	uint8_t pdsch_start;
+} fapi_dl_config_dlsch_rel10_pdu_t;
+
+typedef struct {
+	uint8_t drms_config_flag;
+	uint16_t drms_scrambling;
+	uint8_t csi_config_flag;
+	uint16_t csi_scrambling;
+	uint8_t pdsch_re_mapping_flag;
+	uint8_t pdsch_re_mapping_atenna_ports;
+	uint8_t pdsch_re_mapping_freq_shift;
+} fapi_dl_config_dlsch_rel11_pdu_t;
+
+typedef struct {
+	uint8_t altcqi_table_r12;
+	uint8_t maxlayers;
+	uint8_t n_dl_harq;
+} fapi_dl_config_dlsch_rel12_pdu_t;
+
+typedef struct {
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+	uint8_t ue_type;
+	uint8_t pdsch_payload_type;
+	uint16_t initial_transmission_sf_io;
+	uint8_t drms_table_flag;
+} fapi_dl_config_dlsch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_dlsch_rel8_pdu_t rel8_pdu;
+	fapi_dl_config_dlsch_rel9_pdu_t rel9_pdu;
+	fapi_dl_config_dlsch_rel10_pdu_t rel10_pdu;
+	fapi_dl_config_dlsch_rel11_pdu_t rel11_pdu;
+	fapi_dl_config_dlsch_rel12_pdu_t rel12_pdu;
+	fapi_dl_config_dlsch_rel13_pdu_t rel13_pdu;
+} fapi_dl_config_dlsch_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t p_rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t number_of_transport_blocks;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t ue_category_capacity;
+	uint8_t p_a;
+	uint16_t transmission_power;
+	uint8_t n_prb;
+	uint8_t n_gap;
+} fapi_dl_config_pch_rel8_pdu_t;
+
+typedef struct {
+	uint8_t ue_mode;
+	uint16_t initial_transmission_sf_io;
+} fapi_dl_config_pch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_pch_rel8_pdu_t	rel8_pdu;
+	fapi_dl_config_pch_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_pch_pdu_t;
+
+typedef struct {
+	uint16_t transmission_power;
+	uint8_t prs_bandwidth;
+	uint8_t prs_cyclic_prefix_type;
+	uint8_t prs_muting;
+} fapi_dl_config_prs_rel9_pdu_t;
+
+typedef struct {
+	fapi_dl_config_prs_rel9_pdu_t	rel9_pdu;
+} fapi_dl_config_prs_pdu_t;
+
+typedef struct {
+	uint8_t csi_rs_antenna_port_count_r10;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t transmission_power;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_of_nzp_configuration;
+	uint8_t csi_rs_resource_config[8];
+} fapi_dl_config_csi_rs_rel10_pdu_t;
+
+typedef struct {
+	uint8_t csi_rs_class;
+	uint8_t cdm_type;
+	uint8_t num_bf_vector;
+	struct {
+		uint8_t csi_rs_resource_index;
+		uint16_t bf_value[FAPI_MAX_ANTENNA_PORT_COUNT];
+	} bf_vector[8];
+}fapi_dl_config_csi_rs_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_csi_rs_rel10_pdu_t	rel10_pdu;
+	fapi_dl_config_csi_rs_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_csi_rs_pdu_t;
+
+typedef struct {
+	uint8_t edpcch_resource_assigenment_flag;
+	uint16_t edpcch_id;
+	uint8_t epdcch_start_symbol;
+	uint8_t epdcch_num_prb;
+	uint8_t epdcch_prb_index[8];
+	fapi_dl_config_bf_vector_t bf_vector;
+} fapi_dl_config_edpcch_rel11_params_t;
+
+typedef struct {
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+} fapi_dl_config_edpcch_rel13_params_t;
+
+typedef struct {
+	fapi_dl_config_dci_rel8_pdu_t			rel8_pdu;
+	fapi_dl_config_dci_rel9_pdu_t			rel9_pdu;
+	fapi_dl_config_dci_rel10_pdu_t			rel10_pdu;
+	fapi_dl_config_dci_rel11_pdu_t			rel11_pdu;
+	fapi_dl_config_dci_rel12_pdu_t			rel12_pdu;
+	fapi_dl_config_dci_rel13_pdu_t			rel13_pdu;
+	fapi_dl_config_edpcch_rel11_params_t	rel8_params;
+	fapi_dl_config_edpcch_rel13_params_t	rel13_params;
+} fapi_dl_config_edpcch_pdu_t;
+
+typedef struct {
+	uint8_t mpdcch_narrow_band;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_tansmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggregation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint16_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t pdsch_reptition_levels;
+	uint8_t redundancy_version;
+	uint8_t new_data_indicator;
+	uint8_t harq_process;
+	uint8_t tpmi_length;
+	uint8_t tpmi;
+	uint8_t pmi_flag;
+	uint8_t pmi;
+	uint8_t harq_resource_offset;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index_length;
+	uint8_t downlink_assignment_index;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t starting_ce_level;
+	uint8_t srs_request;
+	uint8_t antenna_ports_and_scrambling_identity_flag;
+	uint8_t antenna_ports_and_scrambling_identity;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t paging_direct_indication_differentiation_flag;
+	uint8_t direct_indication;
+	uint8_t total_dci_length_including_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[8];
+} fapi_dl_config_mdpcch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_mdpcch_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_mdpcch_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+	uint16_t hyper_sfn_2_lsbs;
+} fapi_dl_config_nbch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_nbch_rel13_pdu_t		rel13_pdu;
+} fapi_dl_config_nbch_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t dci_format;
+	uint8_t scheduling_delay;
+	uint8_t resource_assignment;
+	uint8_t repetition_number;
+	uint8_t mcs;
+	uint8_t new_data_indicator;
+	uint8_t harq_ack_resource;
+	uint8_t npdcch_order_indication;
+	uint8_t starting_number_of_nprach_repetitions;
+	uint8_t subcarrier_indication_of_nprach;
+	uint8_t paging_direct_indication_differentation_flag;
+	uint8_t direct_indication;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t total_dci_length_including_padding;
+} fapi_dl_config_npdcch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_npdcch_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_npdcch_pdu_t;
+
+typedef struct {
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint16_t resource_assignment;
+	uint16_t repetition_number;
+	uint8_t modulation;
+	uint8_t number_of_subframes_for_resource_assignment;
+	uint8_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+} fapi_dl_config_ndlsch_rel13_pdu_t;
+
+typedef struct {
+	fapi_dl_config_ndlsch_rel13_pdu_t	rel13_pdu;
+} fapi_dl_config_ndlsch_pdu_t;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union
+	{
+		fapi_dl_config_dci_pdu_t	dci_dl_pdu;
+		fapi_dl_config_bch_pdu_t	bch_pdu;
+		fapi_dl_config_mch_pdu_t	mch_pdu;
+		fapi_dl_config_dlsch_pdu_t	dlsch_pdu;
+		fapi_dl_config_pch_pdu_t	pch_pdu;
+		fapi_dl_config_prs_pdu_t	prs_pdu;
+		fapi_dl_config_csi_rs_pdu_t	csirs_pdu;
+		fapi_dl_config_edpcch_pdu_t edpcch_pdu;
+		fapi_dl_config_mdpcch_pdu_t mdpcch_pdu;
+		fapi_dl_config_nbch_pdu_t   nbch_pdu;
+		fapi_dl_config_npdcch_pdu_t npdcch_pdu;
+		fapi_dl_config_ndlsch_pdu_t ndlsch_pdu;
+	};
+} fapi_dl_config_req_pdu_t;
+
+typedef struct {
+	uint8_t number_of_pdcch_ofdm_symbols;
+	uint8_t number_of_dcis;
+	uint16_t number_of_pdus;
+	uint8_t number_of_pdsch_rntis;
+	uint16_t transmission_power_for_pcfich;
+	fapi_dl_config_req_pdu_t pdus[32];
+} fapi_dl_config_req_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	uint16_t length;
+	fapi_dl_config_req_body_t body;
+} fapi_dl_config_req_t;
+
+typedef struct {
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t modulation_type;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication;
+	uint8_t redundancy_version;
+	uint8_t harq_process_number;
+	uint8_t ul_tx_mode;
+	uint8_t current_tx_nb;
+	uint8_t n_srs;
+} fapi_ul_config_req_ulsch_rel8_pdu_t;
+
+typedef struct {
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t transport_blocks;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t disable_sequence_hopping_flag;
+} fapi_ul_config_req_ulsch_rel10_pdu_t;
+
+typedef struct {
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+	uint8_t dmrs_config_flag;
+	uint16_t ndmrs_csh_identity;
+} fapi_ul_config_req_ulsch_rel11_pdu_t;
+
+typedef struct {
+	uint8_t  ue_type;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+	uint16_t initial_transmission_sf_io;
+	uint8_t  empty_symbols_due_to_re_tunning;
+} fapi_ul_config_req_ulsch_rel13_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_rel8_pdu_t 	rel8_pdu;
+	fapi_ul_config_req_ulsch_rel10_pdu_t	rel10_pdu;
+	fapi_ul_config_req_ulsch_rel11_pdu_t	rel11_pdu;
+	fapi_ul_config_req_ulsch_rel13_pdu_t	rel13_pdu;
+} fapi_ul_config_req_ulsch_pdu_t;
+
+typedef struct { 
+	uint8_t dl_cqi_pmi_size_rank_1;
+	uint8_t dl_cqi_pmi_size_rank_greater_1;
+	uint8_t ri_size;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+} fapi_ul_config_cqi_ri_rel8_information_t;
+
+typedef struct {
+	uint8_t dl_cqi_pmi_ri_size;
+	uint8_t control_type;
+} fapi_ul_config_periodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	uint8_t number_of_cc;
+	struct {
+		uint8_t ri_size;
+		uint8_t dl_cqi_pmi_size;
+	} cc[5];
+} fapi_ul_config_aperiodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	uint8_t report_type;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+	union {
+		fapi_ul_config_periodic_cqi_pmi_ri_report_t periodic_cqi_pmi_ri_report;
+		fapi_ul_config_aperiodic_cqi_pmi_ri_report_t aperiodic_cqi_pmi_ri_report;
+	};
+} fapi_ul_config_cqi_ri_rel9_information_t;
+
+typedef struct {
+	uint16_t dl_cqi_pmi_ri_size_2;
+} fapi_ul_config_periodic_cqi_pmi_ri_report_re13_t;
+
+typedef struct {
+} fapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t;
+
+
+typedef struct {
+	union {
+		fapi_ul_config_periodic_cqi_pmi_ri_report_re13_t periodic_cqi_pmi_ri_report;
+		fapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t aperiodic_cqi_pmi_ri_report;
+	};
+} fapi_ul_config_cqi_ri_rel13_information_t;
+
+typedef struct {
+	fapi_ul_config_cqi_ri_rel8_information_t	rel8_info;
+	fapi_ul_config_cqi_ri_rel9_information_t	rel9_cqi_ri_info;
+	fapi_ul_config_cqi_ri_rel13_information_t	rel13_cqi_ri_info;
+} fapi_ul_config_cqi_ri_information_t;
+
+typedef struct { 
+	uint8_t n_srs_initial;
+	uint8_t initial_number_of_resource_blocks;
+} fapi_ul_config_init_tx_rel8_params_t;
+
+typedef struct {
+	fapi_ul_config_init_tx_rel8_params_t rel8_params;
+} fapi_ul_config_init_tx_params_t;
+
+typedef struct { 
+	uint8_t harq_size;
+	uint8_t delta_offset_harq;
+	uint8_t ack_nack_mode;
+} fapi_ul_config_harq_rel10_information_t;
+
+typedef struct {
+	uint16_t harq_size_2;
+	uint8_t delta_offset_harq_2;
+} fapi_ul_config_harq_rel13_information_t;
+
+typedef struct {
+	fapi_ul_config_harq_rel10_information_t rel10_info;
+	fapi_ul_config_harq_rel13_information_t rel13_info;
+} fapi_ul_config_harq_information_t;
+
+typedef struct { 
+	uint32_t handle;
+	uint16_t rnti;
+} fapi_ul_config_req_ue_rel8_info_t;
+
+typedef struct {
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+} fapi_ul_config_req_ue_rel11_info_t;
+
+typedef struct {
+	uint8_t  ue_type;
+	uint8_t  empty_symbols;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+} fapi_ul_config_req_ue_rel13_info_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_rel8_info_t rel8_info;
+	fapi_ul_config_req_ue_rel11_info_t rel11_info;
+	fapi_ul_config_req_ue_rel13_info_t rel13_info;
+} fapi_ul_config_req_ue_info_t;
+
+typedef struct { 
+	uint16_t pucch_index;
+	uint8_t dl_cqi_pmi_size;
+} fapi_ul_config_req_cqi_rel8_info_t;
+
+typedef struct {
+	uint8_t number_of_pucch_resource;
+	uint16_t pucch_index_p1;
+} fapi_ul_config_req_cqi_rel10_info_t;
+
+typedef struct {
+	uint8_t csi_mode;
+	uint16_t dl_cqi_pmi_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} fapi_ul_config_req_cqi_rel13_info_t;
+
+typedef struct {
+	fapi_ul_config_req_cqi_rel8_info_t rel8_info;
+	fapi_ul_config_req_cqi_rel10_info_t rel10_info;
+	fapi_ul_config_req_cqi_rel13_info_t rel13_info;
+} fapi_ul_config_req_cqi_info_t;
+
+typedef struct { 
+	uint16_t pucch_index;
+} fapi_ul_config_req_sr_rel8_info_t;
+
+typedef struct {
+	uint8_t number_of_pucch_resources;
+	uint16_t pucch_index_p1;
+} fapi_ul_config_req_sr_rel10_info_t;
+
+typedef struct {
+	fapi_ul_config_req_sr_rel8_info_t rel8_info;
+	fapi_ul_config_req_sr_rel10_info_t rel10_info;
+} fapi_ul_config_req_sr_info_t;
+
+typedef struct {
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} fapi_ul_config_req_harq_rel10_tdd_info_t;
+
+typedef struct {
+	uint16_t n_pucch_1_0;
+	uint8_t harq_size;
+} fapi_ul_config_req_harq_rel8_fdd_info_t;
+
+typedef struct {
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} fapi_ul_config_req_harq_rel9_fdd_info_t;
+
+typedef struct {
+	uint8_t  num_ant_ports;
+	uint16_t n_pucch_2_0;
+	uint16_t n_pucch_2_1;
+	uint16_t n_pucch_2_2;
+	uint16_t n_pucch_2_3;	
+} fapi_ul_config_req_harq_rel11_fdd_tdd_info_t;
+
+typedef struct {
+	uint16_t  harq_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} fapi_ul_config_req_harq_rel13_fdd_tdd_info_t;
+
+typedef struct {
+	fapi_ul_config_req_harq_rel10_tdd_info_t		rel10_tdd_info;
+	fapi_ul_config_req_harq_rel8_fdd_info_t			rel8_fdd_info;
+	fapi_ul_config_req_harq_rel9_fdd_info_t			rel9_fdd_info;
+	fapi_ul_config_req_harq_rel11_fdd_tdd_info_t	rel11_fdd_tdd_info;
+	fapi_ul_config_req_harq_rel13_fdd_tdd_info_t	rel13_fdd_tdd_info;
+} fapi_ul_config_req_harq_info_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_cqi_ri_information_t cqi_ri_info;
+	fapi_ul_config_init_tx_params_t		init_tx_params;
+} fapi_ul_config_req_ulsch_cqi_ri_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_harq_information_t	harq_info;
+	fapi_ul_config_init_tx_params_t		init_tx_params;
+} fapi_ul_config_req_ulsch_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_cqi_ri_information_t cqi_ri_info;
+	fapi_ul_config_harq_information_t	harq_info;
+	fapi_ul_config_init_tx_params_t		init_tx_params;
+} fapi_ul_config_req_ulsch_cqi_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_cqi_info_t		cqi_info;
+} fapi_ul_config_req_uci_cqi_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_sr_info_t		sr_info;
+} fapi_ul_config_req_uci_sr_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_harq_info_t		harq_info;
+} fapi_ul_config_req_uci_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_sr_info_t		sr_info;
+	fapi_ul_config_req_harq_info_t		harq_info;
+} fapi_ul_config_req_uci_sr_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_cqi_info_t		cqi_info;
+	fapi_ul_config_req_harq_info_t		harq_info;
+} fapi_ul_config_req_uci_cqi_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_cqi_info_t		cqi_info;
+	fapi_ul_config_req_sr_info_t		sr_info;
+} fapi_ul_config_req_uci_cqi_sr_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+	fapi_ul_config_req_cqi_info_t		cqi_info;
+	fapi_ul_config_req_sr_info_t		sr_info;
+	fapi_ul_config_req_harq_info_t		harq_info;
+} fapi_ul_config_req_uci_cqi_sr_harq_pdu_t;
+
+typedef struct {
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t srs_bandwidth;
+	uint8_t frqeuency_domain_position;
+	uint8_t srs_hopping_bandwidth;
+	uint8_t transmission_comb;
+	uint16_t srs_config_index;
+	uint8_t sounding_reference_cyclic_shift;
+} fapi_ul_config_req_srs_rel8_pdu_t;
+
+typedef struct { 
+	uint8_t antenna_port;
+} fapi_ul_config_req_srs_rel10_pdu_t;
+
+typedef struct {
+	uint8_t number_of_combs;
+} fapi_ul_config_req_srs_rel13_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_srs_rel8_pdu_t rel8_pdu;
+	fapi_ul_config_req_srs_rel10_pdu_t rel10_pdu;
+	fapi_ul_config_req_srs_rel13_pdu_t rel13_pdu;
+} fapi_ul_config_req_srs_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ue_info_t		ue_info;
+} fapi_ul_config_req_harq_buffer_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_req_cqi_info_t 	csi_information;
+} fapi_ul_config_req_ulsch_uci_csi_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_req_harq_info_t		harq_information;
+} fapi_ul_config_req_ulsch_uci_harq_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_ulsch_pdu_t		ulsch_pdu;
+	fapi_ul_config_req_cqi_info_t 		csi_information;
+	fapi_ul_config_req_harq_info_t		harq_information;
+} fapi_ul_config_req_ulsch_csi_uci_harq_pdu_t;
+
+typedef struct {
+	uint8_t harq_ack_resource;
+} fapi_ul_config_req_nb_harq_rel13_info_t;
+
+typedef struct {
+	fapi_ul_config_req_nb_harq_rel13_info_t	nb_harq_pdu_rel13;
+} fapi_ul_config_req_nb_harq_info_t;
+
+typedef struct {
+	uint8_t nulsch_format;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indication;
+	uint8_t n_srs;
+	uint16_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	fapi_ul_config_req_ue_info_t ue_information;
+	fapi_ul_config_req_nb_harq_info_t nb_harq_information;
+} fapi_ul_config_req_nulsch_rel13_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_nulsch_rel13_pdu_t	nulsch_pdu_rel13;
+} fapi_ul_config_req_nulsch_pdu_t;
+
+typedef struct {
+	uint8_t nprach_config_0;
+	uint8_t nprach_config_1;
+	uint8_t nprach_config_2;
+} fapi_ul_config_req_nrach_rel13_pdu_t;
+
+typedef struct {
+	fapi_ul_config_req_nrach_rel13_pdu_t	nrach_pdu_rel13;
+} fapi_ul_config_req_nrach_pdu_t;
+
+typedef struct { 
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union
+	{
+		fapi_ul_config_req_ulsch_pdu_t				ulsch_pdu;
+		fapi_ul_config_req_ulsch_cqi_ri_pdu_t		ulsch_cqi_ri_pdu;
+		fapi_ul_config_req_ulsch_harq_pdu_t			ulsch_harq_pdu;
+		fapi_ul_config_req_ulsch_cqi_harq_pdu_t		ulsch_cqi_harq_pdu;
+		fapi_ul_config_req_uci_cqi_pdu_t			uci_cqi_pdu;
+		fapi_ul_config_req_uci_sr_pdu_t				uci_sr_pdu;
+		fapi_ul_config_req_uci_harq_pdu_t			uci_harq_pdu;
+		fapi_ul_config_req_uci_sr_harq_pdu_t		uci_sr_harq_pdu;
+		fapi_ul_config_req_uci_cqi_harq_pdu_t		uci_cqi_harq_pdu;
+		fapi_ul_config_req_uci_cqi_sr_pdu_t			uci_cqi_sr_pdu;
+		fapi_ul_config_req_uci_cqi_sr_harq_pdu_t	uci_cqi_sr_harq_pdu;
+		fapi_ul_config_req_srs_pdu_t				srs_pdu;
+		fapi_ul_config_req_harq_buffer_pdu_t		harq_buffer_pdu;
+		fapi_ul_config_req_ulsch_uci_csi_pdu_t		ulsch_uci_csi_pdu;
+		fapi_ul_config_req_ulsch_uci_harq_pdu_t		ulsch_uci_harq_pdu;
+		fapi_ul_config_req_ulsch_csi_uci_harq_pdu_t	ulsch_csi_uci_harq_pdu;
+		fapi_ul_config_req_nulsch_pdu_t				nulsch_pdu;
+		fapi_ul_config_req_nrach_pdu_t				nrach_pdu;
+	};
+} fapi_ul_config_req_pdu_t;
+
+typedef struct {
+	uint8_t number_of_pdus;
+	uint8_t rach_prach_frequency_resources;
+	uint8_t srs_present;
+	fapi_ul_config_req_pdu_t* pdus;
+} fapi_ul_config_req_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	uint16_t length;
+	fapi_ul_config_req_body_t body;
+} fapi_ul_config_req_t;
+
+typedef struct { 
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint8_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t mcs_1;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_flags;
+	uint8_t new_data_indication_1;
+	uint8_t ue_tx_antenna_selection;
+	uint8_t tpc;
+	uint8_t cqi_csi_request;
+	uint8_t ul_index;
+	uint8_t dl_assignment_index;
+	uint32_t tpc_bitmap;
+	uint16_t transmission_power;
+} fapi_hi_dci0_req_dci0_rel8_pdu_t;
+
+typedef struct {
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t size_of_cqi_csi_feild;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t resource_allocation_flag;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t mcs_2;
+	uint8_t new_data_indication_2;
+	uint8_t number_of_antenna_ports;
+	uint8_t tpmi;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_ul_rb;
+} fapi_hi_dci0_req_dci0_rel10_pdu_t;
+
+typedef struct {
+	uint8_t pscch_resource;
+	uint8_t time_resource_pattern;
+} fapi_hi_dci0_req_dci0_rel12_pdu_t;
+
+typedef struct {
+	fapi_hi_dci0_req_dci0_rel8_pdu_t rel8_pdu;
+	fapi_hi_dci0_req_dci0_rel10_pdu_t rel10_pdu;
+	fapi_hi_dci0_req_dci0_rel12_pdu_t rel12_pdu;
+} fapi_hi_dci0_req_dci0_pdu_t;
+
+typedef struct {
+	uint8_t resource_block_start;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t hi_value;
+	uint8_t i_phich;
+	uint16_t transmission_power;
+} fapi_hi_dci0_req_hi_rel8_pdu_t;
+
+typedef struct {
+	uint8_t flag_tb2;
+	uint8_t hi_value_2;
+} fapi_hi_dci0_req_hi_rel10_pdu_t;
+
+typedef struct {
+	fapi_hi_dci0_req_hi_rel8_pdu_t rel8_pdu;
+	fapi_hi_dci0_req_hi_rel10_pdu_t rel10_pdu;
+} fapi_hi_dci0_req_hi_pdu_t;
+
+typedef struct {
+	fapi_dl_config_dci_rel8_pdu_t			edpcch_dci_pdu_rel8;
+	fapi_dl_config_dci_rel10_pdu_t			edpcch_dci_pdu_rel10;
+	fapi_dl_config_edpcch_rel11_params_t	edpcch_parameters_rel11;
+} fapi_hi_dci0_req_epdcch_dci_ul_pdu_t;
+
+typedef struct {
+	uint8_t mpdcch_narrowband;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_transmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggreagation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t mcs;
+	uint8_t pusch_repetition_levels;
+	uint8_t frequency_hopping_flag;
+	uint8_t new_data_indication;
+	uint8_t harq_process;
+	uint8_t redudency_version;
+	uint8_t tpc;
+	uint8_t csi_request;
+	uint8_t ul_inex;
+	uint8_t dai_presence_flag;
+	uint8_t dl_assignment_index;
+	uint8_t srs_request;
+	uint8_t dci_subframe_repetition_number;
+	uint32_t tcp_bitmap;
+	uint8_t total_dci_length_include_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[FAPI_MAX_ANTENNA_PORT_COUNT];
+} fapi_hi_dci0_req_mpdcch_dci_ul_rel13_pdu_t;
+
+typedef struct {
+	fapi_hi_dci0_req_mpdcch_dci_ul_rel13_pdu_t	mpdcch_dci_pdu_rel13;
+} fapi_hi_dci0_req_mpdcch_dci_ul_pdu_t;
+
+typedef struct {
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t scheduling_delay;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indicator;
+	uint8_t dci_subframe_repetition_number;
+} fapi_hi_dci0_req_npdcch_dci_ul_rel13_pdu_t;
+
+typedef struct {
+	fapi_hi_dci0_req_npdcch_dci_ul_rel13_pdu_t	npdcch_dci_pdu_rel13;
+} fapi_hi_dci0_req_npdcch_dci_ul_pdu_t;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union 
+	{
+		fapi_hi_dci0_req_hi_pdu_t				hi_pdu;
+		fapi_hi_dci0_req_dci0_pdu_t				dci0_pdu;
+		fapi_hi_dci0_req_epdcch_dci_ul_pdu_t	edpcch_dci_ul_pdu;
+		fapi_hi_dci0_req_mpdcch_dci_ul_pdu_t	mdpcch_dci_ul_pdu;
+		fapi_hi_dci0_req_npdcch_dci_ul_pdu_t	ndpcch_dci_ul_pdu;
+	};
+} fapi_hi_dci0_req_pdu_t;
+
+typedef struct {
+	uint16_t sfn_sf;
+	uint8_t number_of_dci;
+	uint8_t number_of_hi;
+	fapi_hi_dci0_req_pdu_t* pdus;
+} fapi_hi_dci0_req_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_hi_dci0_req_body_t body;
+} fapi_hi_dci0_req_t;
+
+typedef struct {
+	uint16_t tag;
+	uint16_t length;
+	uint32_t* value;
+} fapi_tx_req_pdu_tlv_t;
+
+typedef struct {
+	uint16_t pdu_length;
+	uint16_t pdu_index;
+	uint32_t num_tlv;
+	fapi_tx_req_pdu_tlv_t tlvs[32];
+} fapi_tx_req_pdu_t;
+
+typedef struct {
+	uint16_t number_of_pdus;
+	fapi_tx_req_pdu_t* pdus;
+} fapi_tx_req_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	fapi_tx_req_body_t body;
+} fapi_tx_req_t;
+
+typedef struct {
+	uint32_t handle;
+	uint32_t mp_cca;
+	uint32_t n_cca;
+	uint32_t offset;
+	uint32_t lte_txop_sf;
+	uint16_t txop_sfn_sf_end;
+	uint32_t lbt_mode;
+} fapi_lbt_pdsch_req_rel13_pdu_t;
+
+typedef struct {
+	fapi_lbt_pdsch_req_rel13_pdu_t	rel13_pdu;
+} fapi_lbt_pdsch_req_pdu_t;
+
+typedef struct {
+	uint32_t handle;
+	uint32_t offset;
+	uint16_t sfn_sf_end;
+	uint32_t lbt_mode;
+} fapi_lbt_drs_req_rel13_pdu_t;
+
+typedef struct {
+	fapi_lbt_drs_req_rel13_pdu_t	rel13_pdu;
+} fapi_lbt_drs_req_pdu_t;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		fapi_lbt_pdsch_req_pdu_t	lbt_pdsch_req_pdu;
+		fapi_lbt_drs_req_pdu_t		lbt_drs_req_pdu;
+	};
+} fapi_lbt_dl_config_req_pdu_t;
+
+typedef struct {
+	uint16_t number_of_pdus;
+	fapi_lbt_dl_config_req_pdu_t pdus[32];
+} fapi_lbt_dl_config_req_body_t;
+
+typedef struct {
+	fapi_header_t header;
+	uint16_t sfn_sf;
+	uint16_t length;
+	fapi_lbt_dl_config_req_body_t body;
+} fapi_lbt_dl_config_req_t;
+
+//------------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/nfapi/open-nFAPI/pnf_sim/inc/fapi_stub.h b/nfapi/open-nFAPI/pnf_sim/inc/fapi_stub.h
new file mode 100644
index 0000000000..10df46e7ab
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf_sim/inc/fapi_stub.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _FAPI_STUB_H_
+#define _FAPI_STUB_H_
+
+#include "fapi_interface.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct fapi fapi_t;
+
+typedef struct fapi {
+	void* user_data;
+} fapi_t;
+
+typedef struct {
+	int (*fapi_param_response)(fapi_t* fapi, fapi_param_resp_t* resp);
+	int (*fapi_config_response)(fapi_t* fapi, fapi_config_resp_t* resp);
+
+	int (*fapi_subframe_ind)(fapi_t* fapi, fapi_subframe_ind_t* ind);
+
+	int (*fapi_harq_ind)(fapi_t* fapi, fapi_harq_ind_t* ind);
+	int (*fapi_crc_ind)(fapi_t* fapi, fapi_crc_ind_t* ind);
+	int (*fapi_rx_ulsch_ind)(fapi_t* fapi, fapi_rx_ulsch_ind_t* ind);
+	int (*fapi_rx_cqi_ind)(fapi_t* fapi, fapi_rx_cqi_ind_t* ind);
+	int (*fapi_rx_sr_ind)(fapi_t* fapi, fapi_rx_sr_ind_t* ind);
+	int (*fapi_rach_ind)(fapi_t* fapi, fapi_rach_ind_t* ind);
+	int (*fapi_srs_ind)(fapi_t* fapi, fapi_srs_ind_t* ind);
+	
+	int (*fapi_lbt_dl_ind)(fapi_t* fapi, fapi_lbt_dl_ind_t* ind);
+	int (*fapi_nb_harq_ind)(fapi_t* fapi, fapi_nb_harq_ind_t* ind);
+	int (*fapi_nrach_ind)(fapi_t* fapi, fapi_nrach_ind_t* ind);
+
+} fapi_cb_t;
+
+typedef struct {
+
+	uint16_t duplex_mode;
+	uint16_t dl_channel_bw_support;
+	uint16_t ul_channel_bw_support;
+} fapi_config_t;
+
+fapi_t* fapi_create(fapi_cb_t* callbacks, fapi_config_t* config);
+
+void fapi_start_data(fapi_t* fapi, unsigned rx_port, const char* tx_address, unsigned tx_port);
+
+int fapi_param_request(fapi_t* fapi, fapi_param_req_t* req);
+int fapi_config_request(fapi_t* fapi, fapi_config_req_t* req);
+int fapi_start_request(fapi_t* fapi, fapi_start_req_t* req);
+
+int fapi_dl_config_request(fapi_t* fapi, fapi_dl_config_req_t* req);
+int fapi_ul_config_request(fapi_t* fapi, fapi_ul_config_req_t* req);
+int fapi_hi_dci0_request(fapi_t* fapi, fapi_hi_dci0_req_t* req);
+int fapi_tx_request(fapi_t* fapi, fapi_tx_req_t* req);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp
new file mode 100644
index 0000000000..df0ca12305
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "fapi_stub.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <mutex>
+#include <queue>
+#include <list>
+
+struct phy_pdu
+{
+	phy_pdu() : buffer_len(1500), buffer(0), len(0)
+	{
+		buffer = (char*) malloc(buffer_len);
+	}
+	
+	virtual ~phy_pdu()
+	{
+		free(buffer);
+	}
+
+
+	unsigned buffer_len;
+	char* buffer;
+	unsigned len;
+};
+
+class fapi_private 
+{
+		std::mutex mutex;
+		std::queue<phy_pdu*> rx_buffer;
+
+		std::queue<phy_pdu*> free_store;
+	public:
+
+		fapi_private()
+			: byte_count(0), tick(0), first_dl_config(false)
+		{
+		}
+
+		phy_pdu* allocate_phy_pdu()
+		{
+			phy_pdu* pdu = 0;
+			mutex.lock();
+			if(free_store.empty())
+			{
+				pdu = new phy_pdu();
+			}
+			else
+			{
+				pdu = free_store.front();
+				free_store.pop();
+			}
+			mutex.unlock();
+			return pdu;
+		}
+
+		void release_phy_pdu(phy_pdu* pdu)
+		{
+			mutex.lock();
+			free_store.push(pdu);
+			mutex.unlock();
+		}
+
+		bool rx_buffer_empty()
+		{
+			bool empty;
+			mutex.lock();
+			empty = rx_buffer.empty();
+			mutex.unlock();
+
+			return empty;
+		}
+		
+
+		void push_rx_buffer(phy_pdu* buff)
+		{
+			mutex.lock();
+			rx_buffer.push(buff);
+			mutex.unlock();
+		}
+
+		phy_pdu* pop_rx_buffer()
+		{
+			phy_pdu* buff = 0;
+			mutex.lock();
+			if(!rx_buffer.empty())
+			{
+				buff = rx_buffer.front();
+				rx_buffer.pop();
+			}
+			mutex.unlock();
+			return buff;
+		}
+
+		uint32_t byte_count;
+		uint32_t tick;
+		bool first_dl_config;
+
+};
+
+extern "C"
+{
+	typedef struct fapi_internal
+	{
+		fapi_t _public;
+
+		fapi_cb_t callbacks;
+
+		uint8_t state;
+		fapi_config_t config;
+
+		int rx_sock;
+		int tx_sock;
+		struct sockaddr_in tx_addr;
+
+		uint32_t tx_byte_count;
+		uint32_t tick;
+		
+		fapi_private* fapi;
+
+	} fapi_internal_t;
+}
+
+extern void set_thread_priority(int);
+/*
+{
+	pthread_attr_t ptAttr;
+	
+	struct sched_param schedParam;
+	schedParam.__sched_priority = 79;
+	sched_setscheduler(0, SCHED_RR, &schedParam);
+
+	pthread_attr_setschedpolicy(&ptAttr, SCHED_RR);
+
+	pthread_attr_setinheritsched(&ptAttr, PTHREAD_EXPLICIT_SCHED);
+
+	struct sched_param thread_params;
+	thread_params.sched_priority = 20;
+	pthread_attr_setschedparam(&ptAttr, &thread_params);
+}
+*/
+
+void send_uplink_indications(fapi_internal_t* instance, uint16_t sfn_sf)
+{
+	fapi_harq_ind_t harq_ind;
+	(instance->callbacks.fapi_harq_ind)(&(instance->_public), &harq_ind);
+
+	fapi_crc_ind_t crc_ind;
+	crc_ind.header.message_id = FAPI_CRC_INDICATION;
+	crc_ind.header.length = 0; //??;
+	crc_ind.sfn_sf = sfn_sf;
+	crc_ind.body.number_of_crcs = 1;
+	crc_ind.body.pdus[0].rx_ue_info.handle = 0; //??
+	crc_ind.body.pdus[0].rx_ue_info.rnti = 0; //??
+	crc_ind.body.pdus[0].rel8_pdu.crc_flag = 1;
+
+	(instance->callbacks.fapi_crc_ind)(&(instance->_public), &crc_ind);
+
+	if(!instance->fapi->rx_buffer_empty())
+	{
+		fapi_rx_ulsch_ind_t rx_ind;
+		memset(&rx_ind, 0, sizeof(rx_ind));
+		rx_ind.header.message_id = FAPI_RX_ULSCH_INDICATION;
+		rx_ind.sfn_sf = sfn_sf;
+
+
+		phy_pdu* buff = 0;
+		int i = 0;
+		std::list<phy_pdu*> free_list;
+		do
+		{
+			buff = instance->fapi->pop_rx_buffer();
+			if(buff != 0)
+			{
+				if(buff->len == 0)
+				{
+					printf("[FAPI] Buffer length = 0\n");
+				}
+
+				rx_ind.body.pdus[i].rx_ue_info.handle = 0xDEADBEEF;
+				rx_ind.body.pdus[i].rx_ue_info.rnti = 0x4242;
+
+				rx_ind.body.pdus[i].rel8_pdu.length = buff->len;
+				//rx_ind.pdus[i].rel8_pdu.data_offset;
+				//rx_ind.pdus[i].rel8_pdu.ul_cqi;
+				//rx_ind.pdus[i].rel8_pdu.timing_advance;
+
+				rx_ind.body.data[i] = buff->buffer;
+
+				rx_ind.body.number_of_pdus++;
+				i++;
+
+				instance->fapi->byte_count += buff->len;
+
+				free_list.push_back(buff);
+			}
+		}while(buff != 0 && i < 8);
+
+		(instance->callbacks.fapi_rx_ulsch_ind)(&(instance->_public), &rx_ind);
+
+		for(phy_pdu* pdu : free_list)
+		{
+			instance->fapi->release_phy_pdu(pdu);
+			//free(tx_req.tx_request_body.tx_pdu_list[j].segments[0].segment_data);
+		}
+	}
+	else
+	{
+		fapi_rx_ulsch_ind_t rx_ind;
+		memset(&rx_ind, 0, sizeof(rx_ind));
+		rx_ind.header.message_id = FAPI_RX_ULSCH_INDICATION;
+		rx_ind.sfn_sf = sfn_sf;
+		(instance->callbacks.fapi_rx_ulsch_ind)(&(instance->_public), &rx_ind);
+	}
+
+	
+	fapi_rx_cqi_ind_t cqi_ind;
+	cqi_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_rx_cqi_ind)(&(instance->_public), &cqi_ind);
+
+	fapi_rx_sr_ind_t sr_ind;
+	sr_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_rx_sr_ind)(&(instance->_public), &sr_ind);
+
+	fapi_rach_ind_t rach_ind;
+	rach_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_rach_ind)(&(instance->_public), &rach_ind);
+
+	fapi_srs_ind_t srs_ind;
+	srs_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_srs_ind)(&(instance->_public), &srs_ind);
+	/*
+	nfapi_lbt_dl_indication_t lbt_ind;
+	memset(&lbt_ind, 0, sizeof(lbt_ind));
+	lbt_ind.header.message_id = NFAPI_LBT_DL_INDICATION;
+	lbt_ind.header.phy_id = config->phy_id;
+	lbt_ind.sfn_sf = sfn_sf;
+	nfapi_pnf_p7_lbt_dl_ind(config, &lbt_ind);
+
+	vendor_ext_p7_ind ve_p7_ind;
+	memset(&ve_p7_ind, 0, sizeof(ve_p7_ind));
+	ve_p7_ind.header.message_id = P7_VENDOR_EXT_IND;
+	ve_p7_ind.header.phy_id = config->phy_id;
+	ve_p7_ind.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_p7_vendor_extension(config, &(ve_p7_ind.header));
+	*/
+	
+	fapi_nb_harq_ind_t nb_harq_ind;
+	nb_harq_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_nb_harq_ind)(&(instance->_public), &nb_harq_ind);
+
+	fapi_nrach_ind_t nrach_ind;
+	nrach_ind.sfn_sf = sfn_sf;
+	(instance->callbacks.fapi_nrach_ind)(&(instance->_public), &nrach_ind);
+
+}
+
+void* fapi_thread_start(void* ptr)
+{
+	set_thread_priority(81);
+
+	fapi_internal_t* instance = (fapi_internal_t*)ptr;
+	uint16_t sfn_sf_dec = 0;
+	uint32_t last_tv_usec = 0;
+	uint32_t last_tv_sec = 0;
+
+	uint32_t millisec;
+	uint32_t last_millisec = -1;
+	uint16_t catchup = 0;
+
+	while(1)
+	{
+		// get the time
+		struct timeval sf_start;
+		(void)gettimeofday(&sf_start, NULL);
+		
+		uint16_t sfn_sf = ((((sfn_sf_dec) / 10) << 4) | (((sfn_sf_dec) - (((sfn_sf_dec) / 10) * 10)) & 0xF));
+		// increment the sfn/sf - for the next subframe
+		sfn_sf_dec++;
+		if(sfn_sf_dec > 10239)
+			sfn_sf_dec = 0;
+
+	
+		fapi_subframe_ind_t ind;
+		ind.sfn_sf = sfn_sf;
+
+		if(instance->fapi->first_dl_config)
+			send_uplink_indications(instance, sfn_sf);
+
+		if(instance->tick == 1000)
+		{
+			if(instance->tx_byte_count > 0)
+			{
+				printf("[FAPI] Tx rate %d bytes/sec\n", instance->tx_byte_count);
+				instance->tx_byte_count = 0;
+			}
+			
+			instance->tick = 0;
+		}
+
+		instance->tick++;
+
+		(instance->callbacks.fapi_subframe_ind)(&(instance->_public), &ind);
+
+		{
+			phy_pdu* pdu = instance->fapi->allocate_phy_pdu();
+			int len = recvfrom(instance->rx_sock, pdu->buffer, pdu->buffer_len, MSG_DONTWAIT, 0, 0);
+			if(len > 0)
+			{
+				pdu->len = len;
+				instance->fapi->push_rx_buffer(pdu);
+			}
+			else
+			{
+				instance->fapi->release_phy_pdu(pdu);
+			}
+		}
+		
+
+		if(catchup)
+		{
+			catchup--;
+		}
+		else
+		{
+			struct timespec now_ts;
+			struct timespec sleep_ts;
+			struct timespec sleep_rem_ts;
+
+			// get the current time
+			clock_gettime(CLOCK_MONOTONIC, &now_ts);
+
+
+			// determine how long to sleep before the start of the next 1ms
+			sleep_ts.tv_sec = 0;
+			sleep_ts.tv_nsec = 1e6 - (now_ts.tv_nsec % 1000000);
+
+			int nanosleep_result = nanosleep(&sleep_ts, &sleep_rem_ts);
+
+			if(nanosleep_result != 0)
+				printf("*** nanosleep failed or was interrupted\n");
+
+
+			clock_gettime(CLOCK_MONOTONIC, &now_ts);
+			millisec = now_ts.tv_nsec / 1e6;
+
+			if(last_millisec != -1 && ((last_millisec + 1 ) % 1000) != millisec)
+			{
+				printf("*** missing millisec %d %d\n", last_millisec, millisec);
+				catchup = millisec - last_millisec - 1;
+			}
+
+			last_millisec = millisec;
+		}
+	}
+}
+
+extern "C"
+{
+	fapi_t* fapi_create(fapi_cb_t* callbacks, fapi_config_t* config)
+	{
+		fapi_internal_t* instance = (fapi_internal*)calloc(1, sizeof(fapi_internal_t));
+		instance->callbacks = *callbacks;
+		instance->config = *config;
+		instance->state = 0;
+
+		instance->fapi = new fapi_private();
+
+		return (fapi_t*)instance;
+	}
+	
+	void fapi_destroy(fapi_t* fapi)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+		
+		delete instance->fapi;
+		free(instance);
+	}
+
+	void* fapi_rx_thread_start(void* ptr)
+	{
+		set_thread_priority(60);
+
+		fapi_internal_t* instance = (fapi_internal_t*)ptr;
+
+		while(1)
+		{
+			phy_pdu* pdu = instance->fapi->allocate_phy_pdu();
+			int len = recvfrom(instance->rx_sock, pdu->buffer, pdu->buffer_len, 0, 0, 0);
+			if(len > 0)
+			{
+				pdu->len = len;
+				instance->fapi->push_rx_buffer(pdu);
+			}
+			else
+			{
+				instance->fapi->release_phy_pdu(pdu);
+			}
+
+		}
+	}
+
+	void fapi_start_data(fapi_t* fapi, unsigned rx_port, const char* tx_address, unsigned tx_port)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+
+		printf("[FAPI] Rx Data from %d\n", rx_port);
+		printf("[FAPI] Tx Data to %s:%d\n", tx_address, tx_port);
+
+		instance->rx_sock = socket(AF_INET, SOCK_DGRAM, 0);
+		
+		if(instance->rx_sock < 0)
+		{
+			printf("[FAPI] Failed to create socket\n");
+			return;
+		}
+
+		struct sockaddr_in addr;
+		memset(&addr, 0, sizeof(addr));
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(rx_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+		
+		int bind_result = bind(instance->rx_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+		
+		if(bind_result == -1)
+		{
+			printf("[FAPI] Failed to bind to port %d\n", rx_port);
+			close(instance->rx_sock);
+			return ;
+		}
+
+		instance->tx_sock = socket(AF_INET, SOCK_DGRAM, 0);
+		instance->tx_addr.sin_family = AF_INET;
+		instance->tx_addr.sin_port = htons(tx_port);
+		instance->tx_addr.sin_addr.s_addr = inet_addr(tx_address);
+
+	}
+
+
+	void fill_tlv(fapi_tlv_t tlvs[], uint8_t count, uint8_t tag, uint8_t len, uint16_t value)
+	{
+		tlvs[count].tag = tag;
+		tlvs[count].value = value;
+		tlvs[count].length = len;
+		
+	}
+
+	int fapi_param_request(fapi_t* fapi, fapi_param_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+			
+		fapi_param_resp_t resp;
+		resp.header.message_id = FAPI_PARAM_RESPONSE;
+
+		resp.error_code = FAPI_MSG_OK;
+
+		resp.number_of_tlvs = 0;
+		fill_tlv(resp.tlvs, resp.number_of_tlvs++, FAPI_PHY_STATE_TAG, 2, instance->state);
+
+
+		if(instance->state == 0)
+		{
+			if(instance->config.duplex_mode == 0)
+			{
+				// -- TDD
+				// Downlink Bandwidth Support
+				// Uplink Bandwidth Support
+				// Downlink Modulation Support
+				// Uplink Modulation Support
+				// PHY Antenna Capability
+				// Release Capability
+				// MBSFN Capability
+			}
+			else if(instance->config.duplex_mode == 1)
+			{
+				// -- FDD
+				// Downlink Bandwidth Support
+				fill_tlv(resp.tlvs, resp.number_of_tlvs++, FAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, 2, instance->config.dl_channel_bw_support);
+				// Uplink Bandwidth Support
+				fill_tlv(resp.tlvs, resp.number_of_tlvs++, FAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, 2, instance->config.ul_channel_bw_support);
+				// Downlink Modulation Support
+				// Uplink Modulation Support
+				// PHY Antenna Capability
+				// Release Capability
+				// MBSFN Capability
+				// LAA Capability
+			}
+		}
+		else
+		{
+			if(instance->config.duplex_mode == 0)
+			{
+				// -- TDD
+				// Downlink Bandwidth Support
+				// Uplink Bandwidth Support
+				// Downlink Modulation Support
+				// Uplink Modulation Support
+				// PHY Antenna Capability
+				// Release Capability
+				// MBSFN Capability
+				// Duplexing Mode
+				// PCFICH Power Offset
+				// P-B
+				// DL Cyclic Prefix Type
+				// UL Cyclic Prefix Type
+				// RF Config
+				// PHICH Config
+				// SCH Config
+				// PRACH Config
+				// PUSCH Config
+				// PUCCH Config
+				// SRS Config
+				// Uplink Reference Signal Config
+				// TDD Frame Structure Config
+				// Data Report Mode
+			}
+			else if(instance->config.duplex_mode == 1)
+			{
+				// FDD
+				// Downlink Bandwidth Support
+				// Uplink Bandwidth Support
+				// Downlink Modulation Support
+				// Uplink Modulation Support
+				// PHY Antenna Capability
+				// Release Capability
+				// MBSFN Capability
+				// LAA Capability
+				// Duplexing Mode
+				// PCFICH Power Offset
+				// P-B
+				// DL Cyclic Prefix Type
+				// UL Cyclic Prefix Type
+				// RF Config
+				// PHICH Config
+				// SCH Config
+				// PRACH Config
+				// PUSCH Config
+				// PUCCH Config
+				// SRS Config
+				// Uplink Reference Signal Config
+				// Data Report Mode
+			}
+		}
+
+
+		//todo fill
+		(instance->callbacks.fapi_param_response)(fapi, &resp);
+
+		return 0;
+	}
+
+	int fapi_config_request(fapi_t* fapi, fapi_config_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+			
+		fapi_config_resp_t resp;
+		resp.header.message_id = FAPI_CONFIG_RESPONSE;
+		resp.error_code = FAPI_MSG_OK;
+
+		(instance->callbacks.fapi_config_response)(fapi, &resp);
+		return 0;
+	}
+
+	int fapi_start_request(fapi_t* fapi, fapi_start_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+			
+		pthread_t fapi_thread;
+		pthread_create(&fapi_thread, NULL, &fapi_thread_start, instance);
+		
+		return 0;
+	}
+
+	int fapi_dl_config_request(fapi_t* fapi, fapi_dl_config_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+		instance->fapi->first_dl_config = true;
+		return 0;
+	}
+	int fapi_ul_config_request(fapi_t* fapi, fapi_ul_config_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+		return 0;
+	}
+	int fapi_hi_dci0_request(fapi_t* fapi, fapi_hi_dci0_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+		return 0;
+	}
+	int fapi_tx_request(fapi_t* fapi, fapi_tx_req_t* req)
+	{
+		fapi_internal_t* instance = (fapi_internal_t*)fapi;
+
+		for(int i = 0; i < req->body.number_of_pdus; ++i)
+		{
+			uint16_t len = req->body.pdus[i].pdu_length;
+			uint32_t* data = req->body.pdus[i].tlvs[0].value;
+			//printf("[FAPI] sfnsf:%d len:%d\n", req->sfn_sf,len);
+			//
+			instance->tx_byte_count += len;
+
+			int sendto_result = sendto(instance->tx_sock, data, len, 0, (struct sockaddr*)&(instance->tx_addr), sizeof(instance->tx_addr));
+			
+			if(sendto_result == -1)
+			{
+				// error
+			}
+		}
+
+		return 0;
+	}
+}
+
diff --git a/nfapi/open-nFAPI/pnf_sim/src/main.cpp b/nfapi/open-nFAPI/pnf_sim/src/main.cpp
new file mode 100644
index 0000000000..e2622cf3c3
--- /dev/null
+++ b/nfapi/open-nFAPI/pnf_sim/src/main.cpp
@@ -0,0 +1,2285 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include "debug.h"
+#include "nfapi_pnf_interface.h"
+#include "nfapi.h"
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <assert.h>
+#include <arpa/inet.h>
+
+#include <boost/foreach.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/exception/diagnostic_information.hpp> 
+#include <boost/exception_ptr.hpp> 
+
+
+#include <vendor_ext.h>
+
+#include "fapi_stub.h"
+#include "pool.h"
+
+
+#include <mutex>
+#include <list>
+#include <queue>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <stdlib.h>
+
+#define NUM_P5_PHY 2
+
+uint16_t phy_antenna_capability_values[] = { 1, 2, 4, 8, 16 };
+
+static uint32_t rand_range(uint32_t min, uint32_t max)
+{
+	return ((rand() % (max + 1 - min)) + min);
+}
+
+
+
+extern "C" nfapi_pnf_param_response_t g_pnf_param_resp;
+
+extern "C" {
+
+
+void* pnf_allocate(size_t size)
+{
+	return (void*)memory_pool::allocate(size);
+}
+
+void pnf_deallocate(void* ptr)
+{
+	memory_pool::deallocate((uint8_t*)ptr);
+}
+
+
+int read_xml(const char *xml_file);
+
+};
+
+class udp_data
+{
+	public:
+		bool enabled;
+		uint32_t rx_port;
+		uint32_t tx_port;
+		std::string tx_addr;
+};
+
+class phy_info
+{
+	public:
+
+		phy_info()
+			: first_subframe_ind(0), fapi(0),
+			  dl_ues_per_subframe(0), ul_ues_per_subframe(0), 
+			  timing_window(0), timing_info_mode(0), timing_info_period(0)
+		{
+			index = 0;
+			id = 0;
+
+			local_port = 0;
+			remote_addr = 0;
+			remote_port = 0;
+	
+			duplex_mode = 0;
+			dl_channel_bw_support = 0;
+			ul_channel_bw_support = 0;
+			num_dl_layers_supported = 0;
+			num_ul_layers_supported = 0;
+			release_supported = 0;
+			nmm_modes_supported = 0;
+		}
+
+		uint16_t index;
+		uint16_t id;
+		std::vector<uint8_t> rfs;
+		std::vector<uint8_t> excluded_rfs;
+
+		udp_data udp;
+
+		std::string local_addr;
+		int local_port;
+
+		char* remote_addr;
+		int remote_port;
+
+		uint8_t duplex_mode;
+		uint16_t dl_channel_bw_support;
+		uint16_t ul_channel_bw_support;
+		uint8_t num_dl_layers_supported;
+		uint8_t num_ul_layers_supported;
+		uint16_t release_supported;
+		uint8_t nmm_modes_supported;
+
+		uint8_t dl_ues_per_subframe;
+		uint8_t ul_ues_per_subframe;
+
+		uint8_t first_subframe_ind;
+
+		// timing information recevied from the vnf
+		uint8_t timing_window;
+		uint8_t timing_info_mode;
+		uint8_t timing_info_period;
+
+		fapi_t* fapi;
+
+};
+
+class rf_info
+{
+	public:
+		uint16_t index;
+		uint16_t band;
+		int16_t max_transmit_power;
+		int16_t min_transmit_power;
+		uint8_t num_antennas_supported;
+		uint32_t min_downlink_frequency;
+		uint32_t max_downlink_frequency;
+		uint32_t max_uplink_frequency;
+		uint32_t min_uplink_frequency;
+};
+
+
+class pnf_info
+{
+	public:
+
+		pnf_info() 
+		: release(13), wireshark_test_mode(0),
+		  max_total_power(0), oui(0)
+					
+		{
+			release = 0;
+	
+			sync_mode = 0;
+			location_mode = 0;
+			dl_config_timing = 0;
+			ul_config_timing = 0;
+			tx_timing = 0;
+			hi_dci0_timing = 0;
+	
+			max_phys = 0;
+			max_total_bw = 0;
+			max_total_dl_layers = 0;
+			max_total_ul_layers = 0;
+			shared_bands = 0;
+			shared_pa = 0;
+			
+		}
+
+		int release;
+		std::vector<phy_info> phys;
+		std::vector<rf_info> rfs;
+
+		uint8_t sync_mode;
+		uint8_t location_mode;
+		uint8_t location_coordinates[6];
+		uint32_t dl_config_timing;
+		uint32_t ul_config_timing;
+		uint32_t tx_timing;
+		uint32_t hi_dci0_timing;
+
+		uint16_t max_phys;
+		uint16_t max_total_bw;
+		uint16_t max_total_dl_layers;
+		uint16_t max_total_ul_layers;
+		uint8_t shared_bands;
+		uint8_t shared_pa;
+		int16_t max_total_power;
+		uint8_t oui;
+		
+		uint8_t wireshark_test_mode;
+
+};
+
+struct pnf_phy_user_data_t
+{
+	uint16_t phy_id;
+	nfapi_pnf_config_t* config;
+	phy_info* phy;
+	nfapi_pnf_p7_config_t* p7_config;
+};
+
+int read_pnf_xml(pnf_info& pnf, const char* xml_file)
+{
+	try
+	{
+		std::ifstream input(xml_file);
+	
+		using boost::property_tree::ptree;
+		ptree pt;
+	
+		read_xml(input, pt);
+		
+		pnf.wireshark_test_mode = pt.get<unsigned>("pnf.wireshark_test_mode", 0);
+	
+		
+		pnf.sync_mode = pt.get<unsigned>("pnf.sync_mode");
+		pnf.location_mode= pt.get<unsigned>("pnf.location_mode");
+		//pnf.sync_mode = pt.get<unsigned>("pnf.location_coordinates");
+	
+		pnf.dl_config_timing= pt.get<unsigned>("pnf.dl_config_timing");
+		pnf.ul_config_timing = pt.get<unsigned>("pnf.ul_config_timing");
+		pnf.tx_timing = pt.get<unsigned>("pnf.tx_timing");
+		pnf.hi_dci0_timing = pt.get<unsigned>("pnf.hi_dci0_timing");
+	
+		pnf.max_phys = pt.get<unsigned>("pnf.max_phys");
+		pnf.max_total_bw = pt.get<unsigned>("pnf.max_total_bandwidth");
+		pnf.max_total_dl_layers = pt.get<unsigned>("pnf.max_total_num_dl_layers");
+		pnf.max_total_ul_layers = pt.get<unsigned>("pnf.max_total_num_ul_layers");
+	
+		pnf.shared_bands = pt.get<unsigned>("pnf.shared_bands");
+		pnf.shared_pa = pt.get<unsigned>("pnf.shared_pas");
+	
+		pnf.max_total_power = pt.get<signed>("pnf.maximum_total_power");
+	
+		//"oui");
+	
+		for(const auto& v : pt.get_child("pnf.phys"))
+		{
+			if(v.first == "phy")
+			{
+				phy_info phy;
+				
+				
+					
+				phy.index = v.second.get<unsigned>("index");
+				phy.local_port = v.second.get<unsigned>("port");
+				phy.local_addr = v.second.get<std::string>("address");
+				phy.duplex_mode = v.second.get<unsigned>("duplex_mode");
+	
+				phy.dl_channel_bw_support = v.second.get<unsigned>("downlink_channel_bandwidth_support");
+				phy.ul_channel_bw_support = v.second.get<unsigned>("uplink_channel_bandwidth_support");
+				phy.num_dl_layers_supported = v.second.get<unsigned>("number_of_dl_layers");
+				phy.num_ul_layers_supported = v.second.get<unsigned>("number_of_ul_layers");
+				phy.release_supported = v.second.get<unsigned>("3gpp_release_supported");
+				phy.nmm_modes_supported = v.second.get<unsigned>("nmm_modes_supported");
+	
+				for(const auto& v2 : v.second.get_child("rfs"))
+				{
+					if(v2.first == "index")
+						phy.rfs.push_back(v2.second.get_value<unsigned>());
+				}
+				for(const auto& v2 : v.second.get_child("excluded_rfs"))
+				{
+					if(v2.first == "index")
+						phy.excluded_rfs.push_back(v2.second.get_value<unsigned>());
+				}
+	
+				boost::optional<const boost::property_tree::ptree&> d = v.second.get_child_optional("data.udp");
+				if(d.is_initialized())
+				{
+					phy.udp.enabled = true;
+					phy.udp.rx_port = d.get().get<unsigned>("rx_port");
+					phy.udp.tx_port = d.get().get<unsigned>("tx_port");
+					phy.udp.tx_addr = d.get().get<std::string>("tx_addr");
+				}
+				else
+				{
+					phy.udp.enabled = false;
+				}
+	
+				phy.dl_ues_per_subframe = v.second.get<unsigned>("dl_ues_per_subframe");
+				phy.ul_ues_per_subframe = v.second.get<unsigned>("ul_ues_per_subframe");
+	
+				pnf.phys.push_back(phy);
+			}
+		}	
+		for(const auto& v : pt.get_child("pnf.rfs"))
+		{
+			if(v.first == "rf")
+			{
+				rf_info rf;
+	
+				rf.index = v.second.get<unsigned>("index");
+				rf.band = v.second.get<unsigned>("band");
+				rf.max_transmit_power = v.second.get<signed>("max_transmit_power");
+				rf.min_transmit_power = v.second.get<signed>("min_transmit_power");
+				rf.num_antennas_supported = v.second.get<unsigned>("num_antennas_supported");
+				rf.min_downlink_frequency = v.second.get<unsigned>("min_downlink_frequency");
+				rf.max_downlink_frequency = v.second.get<unsigned>("max_downlink_frequency");
+				rf.min_uplink_frequency = v.second.get<unsigned>("max_uplink_frequency");
+				rf.max_uplink_frequency = v.second.get<unsigned>("min_uplink_frequency");
+	
+				pnf.rfs.push_back(rf);
+			}
+		}	
+	}
+	catch(std::exception& e)
+	{
+		printf("%s", e.what());
+		return -1;
+	}
+	catch(boost::exception& e)
+	{
+		printf("%s", boost::diagnostic_information(e).c_str());
+		return -1;
+	}
+	
+	return 0;
+}
+
+
+
+void pnf_sim_trace(nfapi_trace_level_t level, const char* message, ...)
+{
+	va_list args;
+	va_start(args, message);
+	vprintf(message, args);
+	va_end(args);
+}
+
+void set_thread_priority(int priority)
+{
+	//printf("%s(priority:%d)\n", __FUNCTION__, priority);
+
+	pthread_attr_t ptAttr;
+	
+	struct sched_param schedParam;
+	schedParam.__sched_priority = priority; //79;
+	if(sched_setscheduler(0, SCHED_RR, &schedParam) != 0)
+	{
+		printf("failed to set SCHED_RR\n");
+	}
+
+	if(pthread_attr_setschedpolicy(&ptAttr, SCHED_RR) != 0)
+	{
+		printf("failed to set pthread SCHED_RR %d\n", errno);
+	}
+
+	pthread_attr_setinheritsched(&ptAttr, PTHREAD_EXPLICIT_SCHED);
+
+	struct sched_param thread_params;
+	thread_params.sched_priority = 20;
+	if(pthread_attr_setschedparam(&ptAttr, &thread_params) != 0)
+	{
+		printf("failed to set sched param\n");
+	}
+}
+
+
+void* pnf_p7_thread_start(void* ptr)
+{
+	set_thread_priority(79);
+
+	nfapi_pnf_p7_config_t* config = (nfapi_pnf_p7_config_t*)ptr;
+	nfapi_pnf_p7_start(config);
+	
+	return 0;
+}
+
+
+
+int pnf_param_request(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req)
+{
+	printf("[PNF_SIM] pnf param request\n");
+
+	nfapi_pnf_param_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+	
+	resp.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG;
+	resp.pnf_param_general.nfapi_sync_mode = pnf->sync_mode;
+	resp.pnf_param_general.location_mode = pnf->location_mode;
+	//uint8_t location_coordinates[NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH];
+	resp.pnf_param_general.dl_config_timing = pnf->dl_config_timing;
+	resp.pnf_param_general.tx_timing = pnf->tx_timing;
+	resp.pnf_param_general.ul_config_timing = pnf->ul_config_timing;
+	resp.pnf_param_general.hi_dci0_timing = pnf->hi_dci0_timing;
+	resp.pnf_param_general.maximum_number_phys = pnf->max_phys;
+	resp.pnf_param_general.maximum_total_bandwidth = pnf->max_total_bw;
+	resp.pnf_param_general.maximum_total_number_dl_layers = pnf->max_total_dl_layers;
+	resp.pnf_param_general.maximum_total_number_ul_layers = pnf->max_total_ul_layers;
+	resp.pnf_param_general.shared_bands = pnf->shared_bands;
+	resp.pnf_param_general.shared_pa = pnf->shared_pa;
+	resp.pnf_param_general.maximum_total_power = pnf->max_total_power;
+	//uint8_t oui[NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH];
+
+	resp.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG;
+	resp.pnf_phy.number_of_phys = pnf->phys.size();
+	
+	for(int i = 0; i < pnf->phys.size(); ++i)
+	{
+		resp.pnf_phy.phy[i].phy_config_index = pnf->phys[i].index; 
+		resp.pnf_phy.phy[i].downlink_channel_bandwidth_supported = pnf->phys[i].dl_channel_bw_support;
+		resp.pnf_phy.phy[i].uplink_channel_bandwidth_supported = pnf->phys[i].ul_channel_bw_support;
+		resp.pnf_phy.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported;
+		resp.pnf_phy.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported;
+		resp.pnf_phy.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported;
+		resp.pnf_phy.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported;
+
+		resp.pnf_phy.phy[i].number_of_rfs = pnf->phys[i].rfs.size();
+		for(int j = 0; j < pnf->phys[i].rfs.size(); ++j)
+		{
+			resp.pnf_phy.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j];
+		}
+
+		resp.pnf_phy.phy[i].number_of_rf_exclusions = pnf->phys[i].excluded_rfs.size();
+		for(int j = 0; j < pnf->phys[i].excluded_rfs.size(); ++j)
+		{
+			resp.pnf_phy.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j];
+		}
+	}
+
+
+	resp.pnf_rf.tl.tag = NFAPI_PNF_RF_TAG;
+	resp.pnf_rf.number_of_rfs = pnf->rfs.size();
+
+	for(int i = 0; i < pnf->rfs.size(); ++i)
+	{
+		resp.pnf_rf.rf[i].rf_config_index = pnf->rfs[i].index; 
+		resp.pnf_rf.rf[i].band = pnf->rfs[i].band;
+		resp.pnf_rf.rf[i].maximum_transmit_power = pnf->rfs[i].max_transmit_power; 
+		resp.pnf_rf.rf[i].minimum_transmit_power = pnf->rfs[i].min_transmit_power;
+		resp.pnf_rf.rf[i].number_of_antennas_suppported = pnf->rfs[i].num_antennas_supported;
+		resp.pnf_rf.rf[i].minimum_downlink_frequency = pnf->rfs[i].min_downlink_frequency;
+		resp.pnf_rf.rf[i].maximum_downlink_frequency = pnf->rfs[i].max_downlink_frequency;
+		resp.pnf_rf.rf[i].minimum_uplink_frequency = pnf->rfs[i].min_uplink_frequency;
+		resp.pnf_rf.rf[i].maximum_uplink_frequency = pnf->rfs[i].max_uplink_frequency;
+	}
+
+	if(pnf->release >= 10)
+	{
+		resp.pnf_phy_rel10.tl.tag = NFAPI_PNF_PHY_REL10_TAG;
+		resp.pnf_phy_rel10.number_of_phys = pnf->phys.size();
+		
+		for(int i = 0; i < pnf->phys.size(); ++i)
+		{
+			resp.pnf_phy_rel10.phy[i].phy_config_index = pnf->phys[i].index; 
+			resp.pnf_phy_rel10.phy[i].transmission_mode_7_supported = 0;
+			resp.pnf_phy_rel10.phy[i].transmission_mode_8_supported = 1;
+			resp.pnf_phy_rel10.phy[i].two_antenna_ports_for_pucch = 0;
+			resp.pnf_phy_rel10.phy[i].transmission_mode_9_supported = 1;
+			resp.pnf_phy_rel10.phy[i].simultaneous_pucch_pusch = 0;
+			resp.pnf_phy_rel10.phy[i].four_layer_tx_with_tm3_and_tm4 = 1;
+
+		}
+	}
+
+	if(pnf->release >= 11)
+	{
+		resp.pnf_phy_rel11.tl.tag = NFAPI_PNF_PHY_REL11_TAG;
+		resp.pnf_phy_rel11.number_of_phys = pnf->phys.size();
+		
+		for(int i = 0; i < pnf->phys.size(); ++i)
+		{
+			resp.pnf_phy_rel11.phy[i].phy_config_index = pnf->phys[i].index; 
+			resp.pnf_phy_rel11.phy[i].edpcch_supported = 0;
+			resp.pnf_phy_rel11.phy[i].multi_ack_csi_reporting = 1;
+			resp.pnf_phy_rel11.phy[i].pucch_tx_diversity = 0;
+			resp.pnf_phy_rel11.phy[i].ul_comp_supported = 1;
+			resp.pnf_phy_rel11.phy[i].transmission_mode_5_supported = 0;
+		}
+	}
+
+	if(pnf->release >= 12)
+	{
+		resp.pnf_phy_rel12.tl.tag = NFAPI_PNF_PHY_REL12_TAG;
+		resp.pnf_phy_rel12.number_of_phys = pnf->phys.size();
+		
+		for(int i = 0; i < pnf->phys.size(); ++i)
+		{
+			resp.pnf_phy_rel12.phy[i].phy_config_index = pnf->phys[i].index; 
+			resp.pnf_phy_rel12.phy[i].csi_subframe_set = 0;
+			resp.pnf_phy_rel12.phy[i].enhanced_4tx_codebook = 2; // yes this is invalid
+			resp.pnf_phy_rel12.phy[i].drs_supported = 0;
+			resp.pnf_phy_rel12.phy[i].ul_64qam_supported = 1;
+			resp.pnf_phy_rel12.phy[i].transmission_mode_10_supported = 0;
+			resp.pnf_phy_rel12.phy[i].alternative_bts_indices = 1;
+		}
+	}
+
+	if(pnf->release >= 13)
+	{
+		resp.pnf_phy_rel13.tl.tag = NFAPI_PNF_PHY_REL13_TAG;
+		resp.pnf_phy_rel13.number_of_phys = pnf->phys.size();
+		
+		for(int i = 0; i < pnf->phys.size(); ++i)
+		{
+			resp.pnf_phy_rel13.phy[i].phy_config_index = pnf->phys[i].index; 
+			resp.pnf_phy_rel13.phy[i].pucch_format4_supported = 0;
+			resp.pnf_phy_rel13.phy[i].pucch_format5_supported = 1;
+			resp.pnf_phy_rel13.phy[i].more_than_5_ca_support = 0;
+			resp.pnf_phy_rel13.phy[i].laa_supported = 1;
+			resp.pnf_phy_rel13.phy[i].laa_ending_in_dwpts_supported = 0;
+			resp.pnf_phy_rel13.phy[i].laa_starting_in_second_slot_supported = 1;
+			resp.pnf_phy_rel13.phy[i].beamforming_supported = 0;
+			resp.pnf_phy_rel13.phy[i].csi_rs_enhancement_supported = 1;
+			resp.pnf_phy_rel13.phy[i].drms_enhancement_supported = 0;
+			resp.pnf_phy_rel13.phy[i].srs_enhancement_supported = 1;
+		}
+		
+		resp.pnf_phy_rel13_nb_iot.tl.tag = NFAPI_PNF_PHY_REL13_NB_IOT_TAG;
+		resp.pnf_phy_rel13_nb_iot.number_of_phys = pnf->phys.size();		
+		
+		for(int i = 0; i < pnf->phys.size(); ++i)
+		{
+			resp.pnf_phy_rel13_nb_iot.phy[i].phy_config_index = pnf->phys[i].index; 
+			
+			resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rfs = pnf->phys[i].rfs.size();
+			for(int j = 0; j < pnf->phys[i].rfs.size(); ++j)
+			{
+				resp.pnf_phy_rel13_nb_iot.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j];
+			}
+	
+			resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rf_exclusions = pnf->phys[i].excluded_rfs.size();
+			for(int j = 0; j < pnf->phys[i].excluded_rfs.size(); ++j)
+			{
+				resp.pnf_phy_rel13_nb_iot.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j];
+			}
+			
+			resp.pnf_phy_rel13_nb_iot.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported;
+			resp.pnf_phy_rel13_nb_iot.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported;
+			resp.pnf_phy_rel13_nb_iot.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported;
+			resp.pnf_phy_rel13_nb_iot.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported;
+
+		}
+	}
+
+
+	nfapi_pnf_pnf_param_resp(config, &resp);
+	
+	return 0;
+}
+
+int pnf_config_request(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req)
+{
+	printf("[PNF_SIM] pnf config request\n");
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+
+	for(int i = 0; i < req->pnf_phy_rf_config.number_phy_rf_config_info; ++i)
+	{
+		auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+								  { return item.index == req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index; });
+
+		if(found != pnf->phys.end())
+		{
+			phy_info& phy = (*found);
+			phy.id = req->pnf_phy_rf_config.phy_rf_config[i].phy_id;
+			printf("[PNF_SIM] pnf config request assigned phy_id %d to phy_config_index %d\n", phy.id, req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index);
+		}
+		else
+		{
+			// did not find the phy
+			printf("[PNF_SIM] pnf config request did not find phy_config_index %d\n", req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index);
+		}
+
+	}
+
+	nfapi_pnf_config_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_config_resp(config, &resp);
+
+	return 0;
+}
+
+int fapi_param_response(fapi_t* fapi, fapi_param_resp_t* resp)
+{
+	printf("[PNF_SIM] fapi param response\n");
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_param_response_t nfapi_resp;
+
+	memset(&nfapi_resp, 0, sizeof(nfapi_resp));
+	nfapi_resp.header.message_id = NFAPI_PARAM_RESPONSE;
+	nfapi_resp.header.phy_id = data->phy_id;
+	nfapi_resp.error_code = resp->error_code;
+
+	for(int i = 0; i < resp->number_of_tlvs; ++i)
+	{
+		switch(resp->tlvs[i].tag)
+		{
+			case FAPI_PHY_STATE_TAG:
+				nfapi_resp.l1_status.phy_state.tl.tag = NFAPI_L1_STATUS_PHY_STATE_TAG;
+				nfapi_resp.l1_status.phy_state.value = resp->tlvs[i].value;
+				nfapi_resp.num_tlv++;
+				break;
+
+			case FAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG:
+				nfapi_resp.phy_capabilities.dl_bandwidth_support.tl.tag = NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG;
+				nfapi_resp.phy_capabilities.dl_bandwidth_support.value = resp->tlvs[i].value;
+				nfapi_resp.num_tlv++;
+				break;
+
+			case FAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG:
+				nfapi_resp.phy_capabilities.ul_bandwidth_support.tl.tag = NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG;
+				nfapi_resp.phy_capabilities.ul_bandwidth_support.value = resp->tlvs[i].value;
+				nfapi_resp.num_tlv++;
+				break;
+		}
+	}
+	
+	if(1)
+	{
+		// just code to populate all the tlv for testing with wireshark
+		// todo : these should be move up so that they are populated by fapi
+		
+		nfapi_resp.phy_capabilities.dl_modulation_support.tl.tag = NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG;
+		nfapi_resp.phy_capabilities.dl_modulation_support.value = rand_range(0, 0x0F);
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phy_capabilities.ul_modulation_support.tl.tag = NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG;
+		nfapi_resp.phy_capabilities.ul_modulation_support.value = rand_range(0, 0x07);
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phy_capabilities.phy_antenna_capability.tl.tag = NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG;
+		nfapi_resp.phy_capabilities.phy_antenna_capability.value = phy_antenna_capability_values[rand_range(0, 4)];
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phy_capabilities.release_capability.tl.tag = NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG;
+		nfapi_resp.phy_capabilities.release_capability.value = rand_range(0, 0x3F);
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phy_capabilities.mbsfn_capability.tl.tag = NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG;
+		nfapi_resp.phy_capabilities.mbsfn_capability.value = rand_range(0, 1);
+		nfapi_resp.num_tlv++;
+		
+		
+		nfapi_resp.laa_capability.laa_support.tl.tag = NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG;
+		nfapi_resp.laa_capability.laa_support.value = rand_range(0, 1);
+		nfapi_resp.num_tlv++;
+		nfapi_resp.laa_capability.pd_sensing_lbt_support.tl.tag = NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG;
+		nfapi_resp.laa_capability.pd_sensing_lbt_support.value = rand_range(0, 1);		
+		nfapi_resp.num_tlv++;
+		nfapi_resp.laa_capability.multi_carrier_lbt_support.tl.tag = NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG;
+		nfapi_resp.laa_capability.multi_carrier_lbt_support.value = rand_range(0, 0x0F);		
+		nfapi_resp.num_tlv++;
+		nfapi_resp.laa_capability.partial_sf_support.tl.tag = NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG;
+		nfapi_resp.laa_capability.partial_sf_support.value = rand_range(0, 1);		
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.nb_iot_capability.nb_iot_support.tl.tag = NFAPI_LAA_CAPABILITY_NB_IOT_SUPPORT_TAG;
+		nfapi_resp.nb_iot_capability.nb_iot_support.value = rand_range(0, 2);		
+		nfapi_resp.num_tlv++;
+		nfapi_resp.nb_iot_capability.nb_iot_operating_mode_capability.tl.tag = NFAPI_LAA_CAPABILITY_NB_IOT_OPERATING_MODE_CAPABILITY_TAG;
+		nfapi_resp.nb_iot_capability.nb_iot_operating_mode_capability.value = rand_range(0, 1);		
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.subframe_config.duplex_mode.tl.tag = NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.subframe_config.pcfich_power_offset.tl.tag = NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.subframe_config.pb.tl.tag = NFAPI_SUBFRAME_CONFIG_PB_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.subframe_config.dl_cyclic_prefix_type.tl.tag = NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.subframe_config.ul_cyclic_prefix_type.tl.tag = NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG;
+		nfapi_resp.num_tlv++;		
+		
+		nfapi_resp.rf_config.dl_channel_bandwidth.tl.tag = NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.rf_config.ul_channel_bandwidth.tl.tag = NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.rf_config.reference_signal_power.tl.tag = NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.rf_config.tx_antenna_ports.tl.tag = NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.rf_config.rx_antenna_ports.tl.tag = NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.phich_config.phich_resource.tl.tag = NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phich_config.phich_duration.tl.tag = NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.phich_config.phich_power_offset.tl.tag = NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.sch_config.primary_synchronization_signal_epre_eprers.tl.tag = NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.sch_config.secondary_synchronization_signal_epre_eprers.tl.tag = NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.sch_config.physical_cell_id.tl.tag = NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.prach_config.configuration_index.tl.tag = NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.prach_config.root_sequence_index.tl.tag = NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.prach_config.zero_correlation_zone_configuration.tl.tag = NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.prach_config.high_speed_flag.tl.tag = NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.prach_config.frequency_offset.tl.tag = NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.pusch_config.hopping_mode.tl.tag = NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.pusch_config.hopping_offset.tl.tag = NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.pusch_config.number_of_subbands.tl.tag = NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.pucch_config.delta_pucch_shift.tl.tag = NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.pucch_config.n_cqi_rb.tl.tag = NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.pucch_config.n_an_cs.tl.tag = NFAPI_PUCCH_CONFIG_N_AN_CS_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.pucch_config.n1_pucch_an.tl.tag = NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.srs_config.bandwidth_configuration.tl.tag = NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.srs_config.max_up_pts.tl.tag = NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.srs_config.srs_subframe_configuration.tl.tag = NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.srs_config.srs_acknack_srs_simultaneous_transmission.tl.tag = NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.uplink_reference_signal_config.uplink_rs_hopping.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.uplink_reference_signal_config.group_assignment.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.uplink_reference_signal_config.cyclic_shift_1_for_drms.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.tdd_frame_structure_config.subframe_assignment.tl.tag = NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.tdd_frame_structure_config.special_subframe_patterns.tl.tag = NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG;
+		nfapi_resp.num_tlv++;
+		
+		nfapi_resp.l23_config.data_report_mode.tl.tag = NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG;
+		nfapi_resp.num_tlv++;
+		nfapi_resp.l23_config.sfnsf.tl.tag = NFAPI_L23_CONFIG_SFNSF_TAG;
+		nfapi_resp.num_tlv++;
+	}
+		
+
+	{
+		//if(phy->state == NFAPI_PNF_PHY_IDLE)
+		//if(nfapi_resp.l1_status.phy_state.value == NFAPI_PNF_PHY_IDLE)
+		{
+			// -- NFAPI
+			// Downlink UEs per Subframe
+			nfapi_resp.nfapi_config.dl_ue_per_sf.tl.tag = NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG;
+			nfapi_resp.nfapi_config.dl_ue_per_sf.value = data->phy->dl_ues_per_subframe;
+			nfapi_resp.num_tlv++;
+			// Uplink UEs per Subframe
+			nfapi_resp.nfapi_config.ul_ue_per_sf.tl.tag = NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG;
+			nfapi_resp.nfapi_config.ul_ue_per_sf.value = data->phy->ul_ues_per_subframe;
+			nfapi_resp.num_tlv++;
+			// nFAPI RF Bands
+			nfapi_resp.nfapi_config.rf_bands.tl.tag = NFAPI_PHY_RF_BANDS_TAG;
+			nfapi_resp.nfapi_config.rf_bands.number_rf_bands = 2;
+			nfapi_resp.nfapi_config.rf_bands.rf_band[0] = 23;
+			nfapi_resp.nfapi_config.rf_bands.rf_band[1] = 7;
+			
+			// P7 PNF Address IPv4
+			nfapi_resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
+			struct sockaddr_in pnf_p7_sockaddr;
+			pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(data->phy->local_addr.c_str());
+			memcpy(&(nfapi_resp.nfapi_config.p7_pnf_address_ipv4.address[0]), &pnf_p7_sockaddr.sin_addr.s_addr, 4);
+			nfapi_resp.num_tlv++;
+			// P7 PNF Address IPv6
+			// P7 PNF Port
+			nfapi_resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
+			nfapi_resp.nfapi_config.p7_pnf_port.value = data->phy->local_port;
+			nfapi_resp.num_tlv++;
+			// NMM GSM Frequency Bands
+			nfapi_resp.nfapi_config.nmm_gsm_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG;
+			nfapi_resp.nfapi_config.nmm_gsm_frequency_bands.number_of_rf_bands = 1;
+			nfapi_resp.nfapi_config.nmm_gsm_frequency_bands.bands[0] = 23;
+			nfapi_resp.num_tlv++;
+			// NMM UMTS Frequency Bands
+			nfapi_resp.nfapi_config.nmm_umts_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG;
+			nfapi_resp.nfapi_config.nmm_umts_frequency_bands.number_of_rf_bands = 1;
+			nfapi_resp.nfapi_config.nmm_umts_frequency_bands.bands[0] = 23;
+			nfapi_resp.num_tlv++;
+			// NMM LTE Frequency Bands
+			nfapi_resp.nfapi_config.nmm_lte_frequency_bands.tl.tag = NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG;
+			nfapi_resp.nfapi_config.nmm_lte_frequency_bands.number_of_rf_bands = 1;
+			nfapi_resp.nfapi_config.nmm_lte_frequency_bands.bands[0] = 23;
+			nfapi_resp.num_tlv++;
+			// NMM Uplink RSSI supported
+			nfapi_resp.nfapi_config.nmm_uplink_rssi_supported.tl.tag = NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG;
+			nfapi_resp.nfapi_config.nmm_uplink_rssi_supported.value = 1;
+			nfapi_resp.num_tlv++;
+
+		}
+	}
+
+
+		
+	nfapi_pnf_param_resp(data->config, &nfapi_resp);
+
+	return 0;
+}
+
+int fapi_config_response(fapi_t* fapi, fapi_config_resp_t* resp)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_config_response_t nfapi_resp;
+	memset(&nfapi_resp, 0, sizeof(nfapi_resp));
+	nfapi_resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+	nfapi_resp.header.phy_id = data->phy_id;
+	nfapi_resp.error_code = resp->error_code;
+	nfapi_pnf_config_resp(data->config, &nfapi_resp);
+
+	return 0;
+}
+
+int fapi_subframe_ind(fapi_t* fapi, fapi_subframe_ind_t* resp)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	if(data->phy->first_subframe_ind == 0)
+	{
+		printf("Sending nfapi_pnf_start_resp phy_id:%d\n", data->phy_id);
+		nfapi_start_response_t start_resp;
+		memset(&start_resp, 0, sizeof(start_resp));
+		start_resp.header.message_id = NFAPI_START_RESPONSE;
+		start_resp.header.phy_id = data->phy_id;
+		start_resp.error_code = NFAPI_MSG_OK;
+		nfapi_pnf_start_resp(data->config, &start_resp);
+		
+		data->phy->first_subframe_ind = 1;
+
+		if(data->phy->udp.enabled)
+		{
+			fapi_start_data(fapi, 
+							data->phy->udp.rx_port, 
+							data->phy->udp.tx_addr.c_str(), 
+							data->phy->udp.tx_port);
+		}
+	
+	}
+
+
+	nfapi_pnf_p7_subframe_ind(data->p7_config, data->phy_id, resp->sfn_sf);
+	
+	return 0;
+
+}
+
+int fapi_harq_ind(fapi_t* fapi, fapi_harq_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_harq_indication_t harq_ind;
+	memset(&harq_ind, 0, sizeof(harq_ind));
+	harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
+	harq_ind.header.phy_id = data->p7_config->phy_id;
+	harq_ind.sfn_sf = ind->sfn_sf;
+
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+		harq_ind.harq_indication_body.number_of_harqs = 1;
+	
+		nfapi_harq_indication_pdu_t pdus[harq_ind.harq_indication_body.number_of_harqs];
+		memset(&pdus, 0, sizeof(pdus));
+		
+		pdus[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+		pdus[0].rx_ue_information.handle = rand_range(0, 9999);
+		pdus[0].rx_ue_information.rnti = rand_range(1, 65535);
+		
+		
+		
+		pdus[0].harq_indication_tdd_rel8.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL8_TAG;
+		pdus[0].harq_indication_tdd_rel8.mode = rand_range(0, 4);
+		pdus[0].harq_indication_tdd_rel8.number_of_ack_nack = rand_range(1, 4);
+		
+		switch(pdus[0].harq_indication_tdd_rel8.mode)
+		{
+			case 0:
+			{
+				pdus[0].harq_indication_tdd_rel8.harq_data.bundling.value_0 = rand_range(1, 7);
+				pdus[0].harq_indication_tdd_rel8.harq_data.bundling.value_1 = rand_range(1, 7);
+			}
+			break;
+			case 1:
+			{
+				pdus[0].harq_indication_tdd_rel8.harq_data.multiplex.value_0 = rand_range(1, 7);
+				pdus[0].harq_indication_tdd_rel8.harq_data.multiplex.value_1 = rand_range(1, 7);
+				pdus[0].harq_indication_tdd_rel8.harq_data.multiplex.value_2 = rand_range(1, 7);
+				pdus[0].harq_indication_tdd_rel8.harq_data.multiplex.value_3 = rand_range(1, 7);
+			}
+			break;
+			case 2:
+			{
+				pdus[0].harq_indication_tdd_rel8.harq_data.special_bundling.value_0 = rand_range(1, 7);
+			}
+			break;
+		};
+		
+		
+		pdus[0].harq_indication_tdd_rel9.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL9_TAG;
+		pdus[0].harq_indication_tdd_rel9.mode = rand_range(0, 4);
+		pdus[0].harq_indication_tdd_rel9.number_of_ack_nack = 1;
+		
+		switch(pdus[0].harq_indication_tdd_rel9.mode)
+		{
+			case 0:
+			{		
+				pdus[0].harq_indication_tdd_rel9.harq_data[0].bundling.value_0 = rand_range(1, 7);
+			}
+			break;
+			case 1:
+			{
+				pdus[0].harq_indication_tdd_rel9.harq_data[0].multiplex.value_0 = rand_range(1, 7);
+			}
+			break;
+			case 2:
+			{
+				pdus[0].harq_indication_tdd_rel9.harq_data[0].special_bundling.value_0 = rand_range(1, 7);
+			}
+			break;
+			case 3:
+			{
+				pdus[0].harq_indication_tdd_rel9.harq_data[0].channel_selection.value_0 = rand_range(1, 7);
+			}
+			break;
+			case 4:
+			{
+				pdus[0].harq_indication_tdd_rel9.harq_data[0].format_3.value_0 = rand_range(1, 7);
+			}
+			break;
+		};
+
+	
+	
+		pdus[0].harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
+		pdus[0].harq_indication_tdd_rel13.mode = rand_range(0, 6);
+		pdus[0].harq_indication_tdd_rel13.number_of_ack_nack = 1;
+
+		switch(pdus[0].harq_indication_tdd_rel13.mode)
+		{
+			case 0:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = rand_range(1, 7);		
+			}
+			break;
+			case 1:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = rand_range(1, 7);
+			}
+			break;			
+			case 2:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].special_bundling.value_0 = rand_range(1, 7);
+			}
+			break;			
+			case 3:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].channel_selection.value_0 = rand_range(1, 7);
+			}
+			break;			
+			case 4:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].format_3.value_0 = rand_range(1, 7);
+			}
+			break;			
+			case 5:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].format_4.value_0 = rand_range(1, 7);
+			}
+			break;			
+			case 6:
+			{
+				pdus[0].harq_indication_tdd_rel13.harq_data[0].format_5.value_0 = rand_range(1, 7);
+			}
+			break;			
+		};
+	
+		pdus[0].harq_indication_fdd_rel8.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL8_TAG;
+		pdus[0].harq_indication_fdd_rel8.harq_tb1 = rand_range(1, 7);
+		pdus[0].harq_indication_fdd_rel8.harq_tb2 = rand_range(1, 7);
+		
+		pdus[0].harq_indication_fdd_rel9.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL9_TAG;
+		pdus[0].harq_indication_fdd_rel9.mode = rand_range(0, 2);
+		pdus[0].harq_indication_fdd_rel9.number_of_ack_nack = 2;
+		pdus[0].harq_indication_fdd_rel9.harq_tb_n[0] = rand_range(1, 7);
+		pdus[0].harq_indication_fdd_rel9.harq_tb_n[1] = rand_range(1, 7);
+	
+		pdus[0].harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
+		pdus[0].harq_indication_fdd_rel13.mode = rand_range(0, 2);
+		pdus[0].harq_indication_fdd_rel13.number_of_ack_nack = 2;
+		pdus[0].harq_indication_fdd_rel13.harq_tb_n[0] = rand_range(1, 7);
+		pdus[0].harq_indication_fdd_rel13.harq_tb_n[1] = rand_range(1, 7);
+	
+		pdus[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+		pdus[0].ul_cqi_information.ul_cqi = rand_range(0,255);
+		pdus[0].ul_cqi_information.channel	 = rand_range(0, 1);
+
+		harq_ind.harq_indication_body.harq_pdu_list = pdus;
+		
+		nfapi_pnf_p7_harq_ind(data->p7_config, &harq_ind);	
+	}
+	else
+	{
+
+		harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+		harq_ind.harq_indication_body.number_of_harqs = 8;
+	
+		nfapi_harq_indication_pdu_t pdus[8];
+		memset(&pdus, 0, sizeof(pdus));
+	
+		for(int i = 0; i < 8; ++i)
+		{
+			pdus[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+			pdus[i].rx_ue_information.handle = 0xFF;
+			pdus[i].rx_ue_information.rnti = i;
+	
+			pdus[i].harq_indication_fdd_rel8.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL8_TAG;
+			pdus[i].harq_indication_fdd_rel8.harq_tb1 = 1;
+			pdus[i].harq_indication_fdd_rel8.harq_tb2 = 2;
+		}
+	
+		harq_ind.harq_indication_body.harq_pdu_list = pdus;
+		
+		nfapi_pnf_p7_harq_ind(data->p7_config, &harq_ind);	
+	}
+	
+	return 0;	
+}
+
+int fapi_crc_ind(fapi_t* fapi, fapi_crc_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_crc_indication_t crc_ind;
+	memset(&crc_ind, 0, sizeof(crc_ind));
+	crc_ind.header.message_id = NFAPI_CRC_INDICATION;
+	crc_ind.header.phy_id = data->p7_config->phy_id;
+	crc_ind.sfn_sf = ind->sfn_sf;
+	
+	
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		crc_ind.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG;
+		crc_ind.crc_indication_body.number_of_crcs = 1;
+		
+		nfapi_crc_indication_pdu_t pdus[crc_ind.crc_indication_body.number_of_crcs];
+		memset(&pdus, 0, sizeof(pdus));
+		
+		pdus[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+		pdus[0].rx_ue_information.handle = rand_range(0, 9999);
+		pdus[0].rx_ue_information.rnti = rand_range(1, 65535);
+		
+		pdus[0].crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG;
+		pdus[0].crc_indication_rel8.crc_flag = rand_range(0, 1);
+		
+		crc_ind.crc_indication_body.crc_pdu_list = pdus;
+		nfapi_pnf_p7_crc_ind(data->p7_config, &crc_ind);
+	}
+	else
+	{
+		crc_ind.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG;
+		crc_ind.crc_indication_body.number_of_crcs = ind->body.number_of_crcs;
+	
+		crc_ind.crc_indication_body.crc_pdu_list = (nfapi_crc_indication_pdu_t*)malloc(sizeof(nfapi_crc_indication_pdu_t) * ind->body.number_of_crcs);
+	
+		for(int i = 0; i < ind->body.number_of_crcs; ++i)
+		{
+			crc_ind.crc_indication_body.crc_pdu_list[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+			crc_ind.crc_indication_body.crc_pdu_list[i].rx_ue_information.handle = ind->body.pdus[i].rx_ue_info.handle;
+			crc_ind.crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti = ind->body.pdus[i].rx_ue_info.rnti;
+			crc_ind.crc_indication_body.crc_pdu_list[i].crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG;
+			crc_ind.crc_indication_body.crc_pdu_list[i].crc_indication_rel8.crc_flag = ind->body.pdus[i].rel8_pdu.crc_flag;
+		}
+	
+		nfapi_pnf_p7_crc_ind(data->p7_config, &crc_ind);
+	
+		free(crc_ind.crc_indication_body.crc_pdu_list);
+	}
+	
+	return 0;
+}
+int fapi_rx_ulsch_ind(fapi_t* fapi, fapi_rx_ulsch_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_rx_indication_t rx_ind;
+	memset(&rx_ind, 0, sizeof(rx_ind));
+	rx_ind.header.message_id = NFAPI_RX_ULSCH_INDICATION;
+	rx_ind.header.phy_id = data->p7_config->phy_id;
+	rx_ind.sfn_sf = ind->sfn_sf;
+	
+	if(1)//((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
+		rx_ind.rx_indication_body.number_of_pdus = 1;
+		
+		uint8_t rx_data[1024];
+		
+		nfapi_rx_indication_pdu_t pdus[rx_ind.rx_indication_body.number_of_pdus];
+		memset(&pdus, 0, sizeof(pdus));
+		
+                strcpy((char*)rx_data, (char*)"123456789");
+
+		for(int i = 0; i < rx_ind.rx_indication_body.number_of_pdus;++i)
+		{
+		
+			pdus[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+			pdus[i].rx_ue_information.handle = rand_range(0, 9999);
+			pdus[i].rx_ue_information.rnti = rand_range(1, 65535);
+			
+			pdus[i].rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
+			pdus[i].rx_indication_rel8.length = 10;//rand_range(0, 1024);
+			pdus[i].rx_indication_rel8.offset = 0;//djp - 1;
+			pdus[i].rx_indication_rel8.ul_cqi = rand_range(0, 255);
+			pdus[i].rx_indication_rel8.timing_advance = rand_range(0, 63);
+			
+			//pdus[i].rx_indication_rel9.tl.tag = NFAPI_RX_INDICATION_REL9_TAG;
+			//pdus[i].rx_indication_rel9.timing_advance_r9 = rand_range(0, 7690);
+			
+			pdus[i].data = &rx_data[0];
+		}
+		
+		rx_ind.rx_indication_body.rx_pdu_list = pdus;
+		
+		nfapi_pnf_p7_rx_ind(data->p7_config, &rx_ind);
+	}
+	else
+	{
+
+		rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
+		rx_ind.rx_indication_body.number_of_pdus = ind->body.number_of_pdus;
+	
+		rx_ind.rx_indication_body.rx_pdu_list = (nfapi_rx_indication_pdu_t*)malloc(sizeof(nfapi_rx_indication_pdu_t) * ind->body.number_of_pdus);
+	
+		for(int i = 0; i < ind->body.number_of_pdus; ++i)
+		{
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.handle = ind->body.pdus[i].rx_ue_info.handle;
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length = ind->body.pdus[i].rel8_pdu.length;
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.offset = 1;
+			rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel9.tl.tag = 0;
+			rx_ind.rx_indication_body.rx_pdu_list[i].data = (uint8_t*)ind->body.data[i];
+	
+		}
+		
+		nfapi_pnf_p7_rx_ind(data->p7_config, &rx_ind);
+	
+		free(rx_ind.rx_indication_body.rx_pdu_list);
+	}
+	
+	return 0;
+
+}
+int fapi_rx_cqi_ind(fapi_t* fapi, fapi_rx_cqi_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_cqi_indication_t cqi_ind;
+	memset(&cqi_ind, 0, sizeof(cqi_ind));
+	cqi_ind.header.message_id = NFAPI_RX_CQI_INDICATION;
+	cqi_ind.header.phy_id = data->p7_config->phy_id;
+	cqi_ind.sfn_sf = ind->sfn_sf;
+	
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		cqi_ind.cqi_indication_body.tl.tag = NFAPI_CQI_INDICATION_BODY_TAG;
+		cqi_ind.cqi_indication_body.number_of_cqis = 3;
+		
+		nfapi_cqi_indication_pdu_t cqi_pdu_list[cqi_ind.cqi_indication_body.number_of_cqis];
+		memset(&cqi_pdu_list, 0, sizeof(cqi_pdu_list));
+		nfapi_cqi_indication_raw_pdu_t cqi_raw_pdu_list[cqi_ind.cqi_indication_body.number_of_cqis];
+		//memset(&cqi_raw_pdu_list, 0, sizeof(cqi_raw_pdu_list));
+		
+		
+		for(int i = 0; i < cqi_ind.cqi_indication_body.number_of_cqis; ++i)
+		{
+			cqi_pdu_list[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+			cqi_pdu_list[i].rx_ue_information.handle = rand_range(0, 9999);
+			cqi_pdu_list[i].rx_ue_information.rnti = rand_range(1, 65535);
+			
+			uint8_t rel8_or_9 = rand_range(0, 1);
+			
+			if(rel8_or_9)
+			{
+				cqi_pdu_list[i].cqi_indication_rel8.tl.tag = NFAPI_CQI_INDICATION_REL8_TAG;
+				cqi_pdu_list[i].cqi_indication_rel8.length = 8; //rand_range(1, 12);		
+				cqi_pdu_list[i].cqi_indication_rel8.data_offset = 1; //rand_range(0, 1);		
+				cqi_pdu_list[i].cqi_indication_rel8.ul_cqi = 0;
+				cqi_pdu_list[i].cqi_indication_rel8.ri = rand_range(0, 4);		
+				cqi_pdu_list[i].cqi_indication_rel8.timing_advance = rand_range(0, 63);		
+			}
+			else
+			{
+				cqi_pdu_list[i].cqi_indication_rel9.tl.tag = NFAPI_CQI_INDICATION_REL9_TAG;
+				cqi_pdu_list[i].cqi_indication_rel9.length = 8; //rand_range(1, 12);		
+				cqi_pdu_list[i].cqi_indication_rel9.data_offset = 1; //rand_range(0, 1);		
+				cqi_pdu_list[i].cqi_indication_rel9.ul_cqi = 0; //rand_range(0, 1);		
+				cqi_pdu_list[i].cqi_indication_rel9.number_of_cc_reported = 1;
+				cqi_pdu_list[i].cqi_indication_rel9.ri[0] = rand_range(0, 8);		
+				cqi_pdu_list[i].cqi_indication_rel9.timing_advance = rand_range(0, 63);		
+				cqi_pdu_list[i].cqi_indication_rel9.timing_advance_r9 = rand_range(0, 7690);
+			}
+			
+			cqi_pdu_list[i].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+			cqi_pdu_list[i].ul_cqi_information.ul_cqi = rand_range(0,255);
+			cqi_pdu_list[i].ul_cqi_information.channel = rand_range(0, 1);	
+		}
+		
+		cqi_ind.cqi_indication_body.cqi_pdu_list = cqi_pdu_list;
+		cqi_ind.cqi_indication_body.cqi_raw_pdu_list = cqi_raw_pdu_list;
+		
+		nfapi_pnf_p7_cqi_ind(data->p7_config, &cqi_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_cqi_ind(data->p7_config, &cqi_ind);
+	}
+	
+	return 0;
+}
+int fapi_rx_sr_ind(fapi_t* fapi, fapi_rx_sr_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_sr_indication_t sr_ind;
+	memset(&sr_ind, 0, sizeof(sr_ind));
+	sr_ind.header.message_id = NFAPI_RX_SR_INDICATION;
+	sr_ind.header.phy_id = data->p7_config->phy_id;
+	sr_ind.sfn_sf = ind->sfn_sf;
+	
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		sr_ind.sr_indication_body.tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
+		sr_ind.sr_indication_body.number_of_srs = 1;
+		
+		nfapi_sr_indication_pdu_t pdus[sr_ind.sr_indication_body.number_of_srs];
+		memset(&pdus, 0, sizeof(pdus));
+		
+		pdus[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+		pdus[0].rx_ue_information.handle = rand_range(0, 9999);
+		pdus[0].rx_ue_information.rnti = rand_range(1, 65535);
+		
+		pdus[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+		pdus[0].ul_cqi_information.ul_cqi = rand_range(0,255);
+		pdus[0].ul_cqi_information.channel = rand_range(0, 1);			
+		
+		sr_ind.sr_indication_body.sr_pdu_list = pdus;
+		
+		nfapi_pnf_p7_sr_ind(data->p7_config, &sr_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_sr_ind(data->p7_config, &sr_ind);	
+	}
+	
+	return 0;
+}
+
+int fapi_rach_ind(fapi_t* fapi, fapi_rach_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_rach_indication_t rach_ind;
+	memset(&rach_ind, 0, sizeof(rach_ind));
+	rach_ind.header.message_id = NFAPI_RACH_INDICATION;
+	rach_ind.header.phy_id = data->p7_config->phy_id;
+	rach_ind.sfn_sf = ind->sfn_sf;
+	
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG;
+		rach_ind.rach_indication_body.number_of_preambles = 1;
+	
+		nfapi_preamble_pdu_t pdus[rach_ind.rach_indication_body.number_of_preambles];
+		memset(&pdus, 0, sizeof(pdus));
+		
+		pdus[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG;
+		pdus[0].preamble_rel8.rnti = rand_range(1, 65535);
+		pdus[0].preamble_rel8.preamble = rand_range(0, 63);
+		pdus[0].preamble_rel8.timing_advance = rand_range(0, 1282);
+		pdus[0].preamble_rel9.tl.tag = NFAPI_PREAMBLE_REL9_TAG;
+		pdus[0].preamble_rel9.timing_advance_r9 = rand_range(0, 7690);
+		pdus[0].preamble_rel13.tl.tag = NFAPI_PREAMBLE_REL13_TAG;
+		pdus[0].preamble_rel13.rach_resource_type = rand_range(0, 4);
+			
+		rach_ind.rach_indication_body.preamble_list = pdus;
+		nfapi_pnf_p7_rach_ind(data->p7_config, &rach_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_rach_ind(data->p7_config, &rach_ind);
+	}
+	
+	return 0;
+}
+
+int fapi_srs_ind(fapi_t* fapi, fapi_srs_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+
+	nfapi_srs_indication_t srs_ind;
+	memset(&srs_ind, 0, sizeof(srs_ind));
+	srs_ind.header.message_id = NFAPI_SRS_INDICATION;
+	srs_ind.header.phy_id = data->p7_config->phy_id;
+	srs_ind.sfn_sf = ind->sfn_sf;
+
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		srs_ind.srs_indication_body.tl.tag = NFAPI_SRS_INDICATION_BODY_TAG;
+		srs_ind.srs_indication_body.number_of_ues = 1;
+		
+		nfapi_srs_indication_pdu_t pdus[srs_ind.srs_indication_body.number_of_ues];
+		memset(&pdus, 0, sizeof(pdus));		
+		
+		pdus[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+		pdus[0].rx_ue_information.handle = rand_range(0, 9999);
+		pdus[0].rx_ue_information.rnti = rand_range(1, 65535);
+				
+		pdus[0].srs_indication_fdd_rel8.tl.tag = NFAPI_SRS_INDICATION_FDD_REL8_TAG;
+		pdus[0].srs_indication_fdd_rel8.doppler_estimation = rand_range(0, 255);
+		pdus[0].srs_indication_fdd_rel8.timing_advance = rand_range(0, 63);
+		pdus[0].srs_indication_fdd_rel8.number_of_resource_blocks = 2; //rand_range(0, 255);
+		pdus[0].srs_indication_fdd_rel8.rb_start = rand_range(0, 245);
+		pdus[0].srs_indication_fdd_rel8.snr[0] = rand_range(0, 255);
+		pdus[0].srs_indication_fdd_rel8.snr[1] = rand_range(0, 255);
+		
+		pdus[0].srs_indication_fdd_rel9.tl.tag = NFAPI_SRS_INDICATION_FDD_REL9_TAG;
+		pdus[0].srs_indication_fdd_rel9.timing_advance_r9 = rand_range(0, 7690);
+		
+		pdus[0].srs_indication_tdd_rel10.tl.tag = NFAPI_SRS_INDICATION_TDD_REL10_TAG;
+		pdus[0].srs_indication_tdd_rel10.uppts_symbol = rand_range(0, 1);
+		
+		pdus[0].srs_indication_fdd_rel11.tl.tag = NFAPI_SRS_INDICATION_FDD_REL11_TAG;
+		pdus[0].srs_indication_fdd_rel11.ul_rtoa;		
+		
+		pdus[0].tdd_channel_measurement.tl.tag = NFAPI_TDD_CHANNEL_MEASUREMENT_TAG;
+		pdus[0].tdd_channel_measurement.num_prb_per_subband = rand_range(0, 255);
+		pdus[0].tdd_channel_measurement.number_of_subbands = 1;
+		pdus[0].tdd_channel_measurement.num_atennas = 2;
+		pdus[0].tdd_channel_measurement.subands[0].subband_index = rand_range(0, 255);
+		pdus[0].tdd_channel_measurement.subands[0].channel[0] = rand_range(0, 9999);
+		pdus[0].tdd_channel_measurement.subands[0].channel[1] = rand_range(0, 9999);
+	
+		srs_ind.srs_indication_body.srs_pdu_list = pdus;
+		nfapi_pnf_p7_srs_ind(data->p7_config, &srs_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_srs_ind(data->p7_config, &srs_ind);
+	}
+	
+	return 0;
+}
+
+int fapi_lbt_dl_ind(fapi_t* fapi, fapi_lbt_dl_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+	
+	nfapi_lbt_dl_indication_t lbt_dl_ind;
+	memset(&lbt_dl_ind, 0, sizeof(lbt_dl_ind));
+	lbt_dl_ind.header.message_id = NFAPI_LBT_DL_INDICATION;
+	lbt_dl_ind.header.phy_id = data->p7_config->phy_id;
+	lbt_dl_ind.sfn_sf = ind->sfn_sf;
+
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		lbt_dl_ind.lbt_dl_indication_body.tl.tag = NFAPI_LBT_DL_INDICATION_BODY_TAG;
+		lbt_dl_ind.lbt_dl_indication_body.number_of_pdus = 2;
+		
+		nfapi_lbt_dl_indication_pdu_t pdus[lbt_dl_ind.lbt_dl_indication_body.number_of_pdus];
+		memset(&pdus, 0, sizeof(pdus));	
+		
+		pdus[0].pdu_type = 0; // LBT_PDSCH_RSP PDU
+		pdus[0].pdu_size = 0;
+		pdus[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.tl.tag = NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG;
+		pdus[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.handle = 0xABCD;
+		pdus[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.result = rand_range(0, 1);
+		pdus[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.lte_txop_symbols = rand_range(0, 0xFFFF);
+		pdus[0].lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13.initial_partial_sf = rand_range(0, 1);
+		
+		pdus[1].pdu_type = 1; // LBT_DRS_RSP PDU
+		pdus[1].pdu_size = 0;
+		pdus[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.tl.tag = NFAPI_LBT_DRS_RSP_PDU_REL13_TAG;
+		pdus[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.handle = 0xABCD;
+		pdus[1].lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13.result = rand_range(0, 1);
+
+		lbt_dl_ind.lbt_dl_indication_body.lbt_indication_pdu_list = pdus;
+		nfapi_pnf_p7_lbt_dl_ind(data->p7_config, &lbt_dl_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_lbt_dl_ind(data->p7_config, &lbt_dl_ind);
+	}
+	
+	return 0;
+}
+
+int fapi_nb_harq_ind(fapi_t* fapi, fapi_nb_harq_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+	
+	nfapi_nb_harq_indication_t nb_harq_ind;
+	memset(&nb_harq_ind, 0, sizeof(nb_harq_ind));
+	nb_harq_ind.header.message_id = NFAPI_NB_HARQ_INDICATION;
+	nb_harq_ind.header.phy_id = data->p7_config->phy_id;
+	nb_harq_ind.sfn_sf = ind->sfn_sf;
+
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		
+		nb_harq_ind.nb_harq_indication_body.tl.tag = NFAPI_NB_HARQ_INDICATION_BODY_TAG;
+		nb_harq_ind.nb_harq_indication_body.number_of_harqs = 1;
+		
+		nfapi_nb_harq_indication_pdu_t pdus[nb_harq_ind.nb_harq_indication_body.number_of_harqs];
+		memset(&pdus, 0, sizeof(pdus));	
+		
+		pdus[0].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+		pdus[0].rx_ue_information.handle = rand_range(0, 0xFFFF);
+		pdus[0].rx_ue_information.rnti = rand_range(0, 65535);
+		
+		pdus[0].nb_harq_indication_fdd_rel13.tl.tag = NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG;
+		pdus[0].nb_harq_indication_fdd_rel13.harq_tb1 = rand_range(1, 7);
+		
+		pdus[0].ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+		pdus[0].ul_cqi_information.ul_cqi = rand_range(0, 255);
+		pdus[0].ul_cqi_information.channel = rand_range(0, 1);
+		
+		nb_harq_ind.nb_harq_indication_body.nb_harq_pdu_list = pdus;
+		nfapi_pnf_p7_nb_harq_ind(data->p7_config, &nb_harq_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_nb_harq_ind(data->p7_config, &nb_harq_ind);
+	}
+	
+	return 0;
+}
+
+int fapi_nrach_ind(fapi_t* fapi, fapi_nrach_ind_t* ind)
+{
+	pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)(fapi->user_data);
+	
+	nfapi_nrach_indication_t nrach_ind;
+	memset(&nrach_ind, 0, sizeof(nrach_ind));
+	nrach_ind.header.message_id = NFAPI_NRACH_INDICATION;
+	nrach_ind.header.phy_id = data->p7_config->phy_id;
+	nrach_ind.sfn_sf = ind->sfn_sf;
+
+	if(((pnf_info*)(data->config->user_data))->wireshark_test_mode)
+	{
+		nrach_ind.nrach_indication_body.tl.tag = NFAPI_NRACH_INDICATION_BODY_TAG;
+		nrach_ind.nrach_indication_body.number_of_initial_scs_detected = 1;
+		
+		nfapi_nrach_indication_pdu_t pdus[nrach_ind.nrach_indication_body.number_of_initial_scs_detected];
+		memset(&pdus, 0, sizeof(pdus));	
+		
+		pdus[0].nrach_indication_rel13.tl.tag = NFAPI_NRACH_INDICATION_REL13_TAG;
+		pdus[0].nrach_indication_rel13.rnti = rand_range(1, 65535);
+		pdus[0].nrach_indication_rel13.initial_sc = rand_range(0, 47);
+		pdus[0].nrach_indication_rel13.timing_advance = rand_range(0, 3840);
+		pdus[0].nrach_indication_rel13.nrach_ce_level = rand_range(0, 2);
+		
+		nrach_ind.nrach_indication_body.nrach_pdu_list = pdus;
+		
+		nfapi_pnf_p7_nrach_ind(data->p7_config, &nrach_ind);
+	}
+	else
+	{
+		nfapi_pnf_p7_nrach_ind(data->p7_config, &nrach_ind);
+	}	
+	
+	return 0;
+}
+
+int pnf_start_request(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req)
+{
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+
+	// start all phys that have been configured
+	for(phy_info& phy : pnf->phys)
+	{
+		if(phy.id != 0)
+		{
+	//auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+	//		{ return item.id == req->header.phy_id; });
+//
+//	if(found != pnf->phys.end())
+//	{
+//		phy_info& phy = (*found);
+
+			fapi_cb_t cb;
+			cb.fapi_param_response = &fapi_param_response;
+			cb.fapi_config_response = &fapi_config_response;
+			cb.fapi_subframe_ind = &fapi_subframe_ind;
+			cb.fapi_harq_ind = fapi_harq_ind;
+			cb.fapi_crc_ind = fapi_crc_ind;
+			cb.fapi_rx_ulsch_ind = fapi_rx_ulsch_ind;
+			cb.fapi_rx_cqi_ind = fapi_rx_cqi_ind;
+			cb.fapi_rx_sr_ind = fapi_rx_sr_ind;
+			cb.fapi_rach_ind = fapi_rach_ind;
+			cb.fapi_srs_ind = fapi_srs_ind;
+			
+			cb.fapi_lbt_dl_ind = fapi_lbt_dl_ind;
+			cb.fapi_nb_harq_ind = fapi_nb_harq_ind;
+			cb.fapi_nrach_ind = fapi_nrach_ind;
+			
+			
+
+			fapi_config_t c;
+			c.duplex_mode = phy.duplex_mode;
+			c.dl_channel_bw_support = phy.dl_channel_bw_support;
+			c.ul_channel_bw_support = phy.ul_channel_bw_support;
+
+			phy.fapi = fapi_create(&cb, &c);
+			printf("[PNF_SIM] staring fapi %p phy_id:%d\n", phy.fapi, phy.id);
+
+			pnf_phy_user_data_t* data = (pnf_phy_user_data_t*)malloc(sizeof(pnf_phy_user_data_t));
+			data->phy_id = phy.id;
+			data->config = config;
+			data->phy = &phy;
+
+			phy.fapi->user_data = data; 
+		}
+
+	}
+
+	nfapi_pnf_start_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_START_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_start_resp(config, &resp);
+
+	return 0;
+}
+
+int pnf_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_stop_request_t* req)
+{
+	printf("[PNF_SIM] pnf stop request\n");
+
+	nfapi_pnf_stop_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_pnf_stop_resp(config, &resp);
+
+	return 0;
+}
+
+int param_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req)
+{
+	printf("[PNF_SIM] param request phy_id:%d\n", req->header.phy_id);
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+
+	auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+								  { return item.id == req->header.phy_id; });
+
+	if(found != pnf->phys.end())
+	{
+		phy_info& phy_info = (*found);
+
+		fapi_param_req_t fapi_req;
+		fapi_req.header.message_id = req->header.message_id;
+		fapi_req.header.length = 0;
+
+		// convert nfapi to fapi
+
+		fapi_param_request(phy_info.fapi, &fapi_req);
+
+	}
+	else
+	{
+		// did not find the phy
+	}
+
+
+	printf("[PNF_SIM] param request .. exit\n");
+
+
+	return 0;
+}
+
+int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req)
+{
+	printf("[PNF_SIM] config request phy_id:%d\n", req->header.phy_id);
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+
+	auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+								  { return item.id == req->header.phy_id; });
+
+	if(found != pnf->phys.end())
+	{
+		phy_info& phy_info = (*found);
+
+
+		if(req->nfapi_config.timing_window.tl.tag == NFAPI_NFAPI_TIMING_WINDOW_TAG)
+		{
+			phy_info.timing_window = req->nfapi_config.timing_window.value;
+		}
+
+		if(req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NFAPI_TIMING_INFO_MODE_TAG)
+		{
+			printf("timing info mode provided\n");
+			phy_info.timing_info_mode = req->nfapi_config.timing_info_mode.value;
+		}
+		else 
+		{
+			phy_info.timing_info_mode = 0;
+			printf("NO timing info mode provided\n");
+		}
+
+		if(req->nfapi_config.timing_info_period.tl.tag == NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG)
+		{
+			printf("timing info period provided\n");
+			phy_info.timing_info_period = req->nfapi_config.timing_info_period.value;
+		}
+		else 
+		{
+			phy_info.timing_info_period = 0;
+		}
+
+		phy_info.remote_port = req->nfapi_config.p7_vnf_port.value;
+
+		struct sockaddr_in vnf_p7_sockaddr;
+		memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4);
+		phy_info.remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr);
+
+		printf("[PNF_SIM] %d vnf p7 %s:%d timing %d %d %d\n", phy_info.id, phy_info.remote_addr, phy_info.remote_port, 
+				phy_info.timing_window, phy_info.timing_info_mode, phy_info.timing_info_period);
+
+		fapi_config_req_t fapi_req;
+		fapi_config_request(phy_info.fapi, &fapi_req);
+	}
+
+	return 0;
+}
+
+nfapi_p7_message_header_t* phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t* msg_size)
+{
+	if(message_id == P7_VENDOR_EXT_REQ)
+	{
+		(*msg_size) = sizeof(vendor_ext_p7_req);
+		return (nfapi_p7_message_header_t*)malloc(sizeof(vendor_ext_p7_req));
+	}
+	
+	return 0;
+}
+
+void phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t* header)
+{
+	free(header);
+}
+
+int phy_dl_config_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req)
+{
+	//printf("[PNF_SIM] dl config request\n");
+
+	if(req->vendor_extension)
+		free(req->vendor_extension);
+
+	phy_info* phy = (phy_info*)(pnf_p7->user_data);
+
+	fapi_dl_config_req_t fapi_req;
+	// convert
+	fapi_dl_config_request(phy->fapi, &fapi_req);
+
+	return 0;
+}
+int phy_ul_config_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req)
+{
+	//printf("[PNF_SIM] ul config request\n");
+	phy_info* phy = (phy_info*)(pnf_p7->user_data);
+
+	fapi_ul_config_req_t fapi_req;
+	// convert
+	fapi_ul_config_request(phy->fapi, &fapi_req);
+
+	return 0;
+}
+int phy_hi_dci0_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req)
+{
+	//printf("[PNF_SIM] hi dci0 request\n");
+	phy_info* phy = (phy_info*)(pnf_p7->user_data);
+
+	fapi_hi_dci0_req_t fapi_req;
+	// convert
+	fapi_hi_dci0_request(phy->fapi, &fapi_req);
+	return 0;
+}
+int phy_tx_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req)
+{
+	//printf("[PNF_SIM] tx request\n");
+	phy_info* phy = (phy_info*)(pnf_p7->user_data);
+
+	fapi_tx_req_t fapi_req;
+	fapi_req.header.message_id = FAPI_TX_REQUEST;
+	fapi_req.sfn_sf = req->sfn_sf;
+	fapi_req.body.number_of_pdus = req->tx_request_body.number_of_pdus;
+
+	fapi_tx_req_pdu_t pdus[8];
+	fapi_req.body.pdus = &pdus[0];
+
+	for(int i = 0; i < fapi_req.body.number_of_pdus; ++i)
+	{
+		fapi_req.body.pdus[i].pdu_length = req->tx_request_body.tx_pdu_list[i].pdu_length;
+		fapi_req.body.pdus[i].pdu_index = req->tx_request_body.tx_pdu_list[i].pdu_index;
+		fapi_req.body.pdus[i].num_tlv = 1;
+		fapi_req.body.pdus[i].tlvs[0].value = (uint32_t*)req->tx_request_body.tx_pdu_list[i].segments[0].segment_data;
+
+		//if the pnf wants to retain the pointer then req->tx_request_body.tx_pdu_list[i].segments[0].segment_data should be set to 0
+
+
+	}
+
+	fapi_tx_request(phy->fapi, &fapi_req);
+/*
+	if(fapi_req.body.number_of_pdus > 0)
+	{
+		for(int i = 0; i < fapi_req.body.number_of_pdus; ++i)
+		{
+			//printf("freeing tx pdu %p\n", fapi_req.body.pdus[i].tlvs[0].value);
+			if(0)
+			{
+				free(fapi_req.body.pdus[i].tlvs[0].value);
+			}
+			else
+			{
+				pnf_deallocate(fapi_req.body.pdus[i].tlvs[0].value);
+			}
+		}
+	}
+*/	
+
+	return 0;
+}
+int phy_lbt_dl_config_req(nfapi_pnf_p7_config_t*, nfapi_lbt_dl_config_request_t* req)
+{
+	//printf("[PNF_SIM] lbt dl config request\n");
+	return 0;
+}
+
+int phy_vendor_ext(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg)
+{
+	if(msg->message_id == P7_VENDOR_EXT_REQ)
+	{
+		vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg;
+		//printf("[PNF_SIM] vendor request (1:%d 2:%d)\n", req->dummy1, req->dummy2);
+	}
+	else
+	{
+		printf("[PNF_SIM] unknown vendor ext\n");
+	}
+	return 0;
+}
+
+
+
+int phy_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* codex)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P7_VENDOR_EXT_IND)
+	{
+		vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)(header);
+		if(!push16(ind->error_code, ppWritePackedMsg, end))
+			return 0;
+		
+		return 1;
+	}
+	return -1;
+}
+
+int phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t* codec)
+{
+	if(header->message_id == P7_VENDOR_EXT_REQ)
+	{
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+		vendor_ext_p7_req* req = (vendor_ext_p7_req*)(header);
+		if(!(pull16(ppReadPackedMessage, &req->dummy1, end) &&
+			 pull16(ppReadPackedMessage, &req->dummy2, end)))
+			return 0;
+		return 1;
+	}
+	return -1;
+}
+
+int phy_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t* end, void** ve, nfapi_p7_codec_config_t* config)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_unpack_vendor_extension_tlv\n");
+
+	switch(tl->tag)
+	{
+		case VENDOR_EXT_TLV_1_TAG:
+			*ve = malloc(sizeof(vendor_ext_tlv_1));
+			if(!pull32(ppReadPackedMessage, &((vendor_ext_tlv_1*)(*ve))->dummy, end))
+				return 0;
+
+			return 1;
+			break;
+	}
+
+	return -1;
+}
+
+int phy_pack_vendor_extention_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p7_codec_config_t* config)
+{
+	//printf("%s\n", __FUNCTION__);
+	(void)ve;
+	(void)ppWritePackedMsg;
+	return -1;
+}
+
+int pnf_sim_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t *end, void** ve, nfapi_p4_p5_codec_config_t* config)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_sim_unpack_vendor_extension_tlv\n");
+
+	switch(tl->tag)
+	{
+		case VENDOR_EXT_TLV_2_TAG:
+			*ve = malloc(sizeof(vendor_ext_tlv_2));
+			if(!pull32(ppReadPackedMessage, &((vendor_ext_tlv_2*)(*ve))->dummy, end))
+				return 0;
+
+			return 1;
+			break;
+	}
+	
+	return -1;
+}
+
+int pnf_sim_pack_vendor_extention_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	//printf("%s\n", __FUNCTION__);
+	(void)ve;
+	(void)ppWritePackedMsg;
+	return -1;
+}
+int start_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req)
+{
+	printf("[PNF_SIM] start request phy_id:%d\n", req->header.phy_id);
+
+	pnf_info* pnf = (pnf_info*)(config->user_data);
+
+	auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+								  { return item.id == req->header.phy_id; });
+
+	if(found != pnf->phys.end())
+	{
+		phy_info& phy_info = (*found);
+
+
+		nfapi_pnf_p7_config_t* p7_config = nfapi_pnf_p7_config_create();
+
+		p7_config->phy_id = phy->phy_id;
+
+		p7_config->remote_p7_port = phy_info.remote_port;
+		p7_config->remote_p7_addr = phy_info.remote_addr;
+		p7_config->local_p7_port = phy_info.local_port;
+		p7_config->local_p7_addr = (char*)phy_info.local_addr.c_str();
+		p7_config->user_data = &phy_info;
+
+		p7_config->malloc = &pnf_allocate;
+		p7_config->free = &pnf_deallocate;
+		p7_config->codec_config.allocate = &pnf_allocate;
+		p7_config->codec_config.deallocate = &pnf_deallocate;
+		
+		p7_config->trace = &pnf_sim_trace;
+
+		phy->user_data = p7_config;
+
+		p7_config->subframe_buffer_size = phy_info.timing_window;
+		if(phy_info.timing_info_mode & 0x1)
+		{
+			p7_config->timing_info_mode_periodic = 1;
+			p7_config->timing_info_period = phy_info.timing_info_period;
+		}
+		
+		if(phy_info.timing_info_mode & 0x2)
+		{
+			p7_config->timing_info_mode_aperiodic = 1;
+		}
+
+		p7_config->dl_config_req = &phy_dl_config_req;
+		p7_config->ul_config_req = &phy_ul_config_req;
+		p7_config->hi_dci0_req = &phy_hi_dci0_req;
+		p7_config->tx_req = &phy_tx_req;
+		p7_config->lbt_dl_config_req = &phy_lbt_dl_config_req;
+
+		p7_config->vendor_ext = &phy_vendor_ext;
+
+		p7_config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext;
+		p7_config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext;
+
+		p7_config->codec_config.unpack_p7_vendor_extension = &phy_unpack_p7_vendor_extension;
+		p7_config->codec_config.pack_p7_vendor_extension = &phy_pack_p7_vendor_extension;
+		p7_config->codec_config.unpack_vendor_extension_tlv = &phy_unpack_vendor_extension_tlv;
+		p7_config->codec_config.pack_vendor_extension_tlv = &phy_pack_vendor_extention_tlv;
+
+		pthread_t p7_thread;
+		pthread_create(&p7_thread, NULL, &pnf_p7_thread_start, p7_config);
+
+
+		((pnf_phy_user_data_t*)(phy_info.fapi->user_data))->p7_config = p7_config;
+
+		fapi_start_req_t fapi_req;
+		fapi_start_request(phy_info.fapi, &fapi_req);
+
+	}
+
+	return 0;
+}
+
+int measurement_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_measurement_request_t* req)
+{
+	nfapi_measurement_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+	nfapi_pnf_measurement_resp(config, &resp);
+	return 0;
+}
+int rssi_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_rssi_request_t* req)
+{
+	nfapi_rssi_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_RSSI_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_rssi_resp(config, &resp);
+	
+	nfapi_rssi_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_RSSI_INDICATION;
+	ind.header.phy_id = req->header.phy_id;
+	ind.error_code = NFAPI_P4_MSG_OK;
+	ind.rssi_indication_body.tl.tag = NFAPI_RSSI_INDICATION_TAG;
+	ind.rssi_indication_body.number_of_rssi = 1;
+	ind.rssi_indication_body.rssi[0] = -42;
+	nfapi_pnf_rssi_ind(config, &ind);
+	return 0;
+}
+int cell_search_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_cell_search_request_t* req)
+{
+	nfapi_cell_search_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_cell_search_resp(config, &resp);
+	
+	nfapi_cell_search_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
+	ind.header.phy_id = req->header.phy_id;
+	ind.error_code = NFAPI_P4_MSG_OK;
+	
+	switch(req->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+		{
+			ind.lte_cell_search_indication.tl.tag = NFAPI_LTE_CELL_SEARCH_INDICATION_TAG;
+			ind.lte_cell_search_indication.number_of_lte_cells_found = 1;
+			ind.lte_cell_search_indication.lte_found_cells[0].pci = 123;
+			ind.lte_cell_search_indication.lte_found_cells[0].rsrp = 123;
+			ind.lte_cell_search_indication.lte_found_cells[0].rsrq = 123;
+			ind.lte_cell_search_indication.lte_found_cells[0].frequency_offset = 123;
+		}
+		break;
+		case NFAPI_RAT_TYPE_UTRAN:
+		{
+			ind.utran_cell_search_indication.tl.tag = NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG;
+			ind.utran_cell_search_indication.number_of_utran_cells_found = 1;
+			ind.utran_cell_search_indication.utran_found_cells[0].psc = 89;
+			ind.utran_cell_search_indication.utran_found_cells[0].rscp = 89;
+			ind.utran_cell_search_indication.utran_found_cells[0].ecno = 89;
+			ind.utran_cell_search_indication.utran_found_cells[0].frequency_offset = -89;
+			
+		}
+		break;
+		case NFAPI_RAT_TYPE_GERAN:
+		{
+			ind.geran_cell_search_indication.tl.tag = NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG;
+			ind.geran_cell_search_indication.number_of_gsm_cells_found = 1;
+			ind.geran_cell_search_indication.gsm_found_cells[0].bsic = 23;
+			ind.geran_cell_search_indication.gsm_found_cells[0].rxlev = 23;
+			ind.geran_cell_search_indication.gsm_found_cells[0].rxqual = 23;
+			ind.geran_cell_search_indication.gsm_found_cells[0].frequency_offset = -23;
+			ind.geran_cell_search_indication.gsm_found_cells[0].sfn_offset = 230;
+			
+		}
+		break;
+	}
+	
+	ind.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+	ind.pnf_cell_search_state.length = 3;
+	
+	nfapi_pnf_cell_search_ind(config, &ind);	
+	return 0;
+}
+int broadcast_detect_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_broadcast_detect_request_t* req)
+{
+	nfapi_broadcast_detect_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_broadcast_detect_resp(config, &resp);
+	
+	nfapi_broadcast_detect_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_BROADCAST_DETECT_INDICATION;
+	ind.header.phy_id = req->header.phy_id;
+	ind.error_code = NFAPI_P4_MSG_OK;
+	
+	switch(req->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+		{
+			ind.lte_broadcast_detect_indication.tl.tag = NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG;
+			ind.lte_broadcast_detect_indication.number_of_tx_antenna = 1;
+			ind.lte_broadcast_detect_indication.mib_length = 4;
+			//ind.lte_broadcast_detect_indication.mib...
+			ind.lte_broadcast_detect_indication.sfn_offset = 77;
+		
+		}
+		break;
+		case NFAPI_RAT_TYPE_UTRAN:
+		{
+			ind.utran_broadcast_detect_indication.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG;
+			ind.utran_broadcast_detect_indication.mib_length = 4;
+			//ind.utran_broadcast_detect_indication.mib...
+			ind.utran_broadcast_detect_indication.sfn_offset;
+			
+		}
+		break;
+	}
+	
+	ind.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+	ind.pnf_cell_broadcast_state.length = 3;
+	
+	nfapi_pnf_broadcast_detect_ind(config, &ind);	
+	return 0;
+}
+int system_information_schedule_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_schedule_request_t* req)
+{
+	nfapi_system_information_schedule_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_system_information_schedule_resp(config, &resp);
+	
+	nfapi_system_information_schedule_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION;
+	ind.header.phy_id = req->header.phy_id;
+	ind.error_code = NFAPI_P4_MSG_OK;
+	
+	ind.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
+	ind.lte_system_information_indication.sib_type = 3;
+	ind.lte_system_information_indication.sib_length = 5;
+	//ind.lte_system_information_indication.sib...
+	
+	nfapi_pnf_system_information_schedule_ind(config, &ind);		
+	return 0;
+}
+int system_information_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_request_t* req)
+{
+	nfapi_system_information_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_system_information_resp(config, &resp);
+	
+	nfapi_system_information_indication_t ind;
+	memset(&ind, 0, sizeof(ind));
+	ind.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
+	ind.header.phy_id = req->header.phy_id;
+	ind.error_code = NFAPI_P4_MSG_OK;
+	
+	switch(req->rat_type)
+	{
+		case NFAPI_RAT_TYPE_LTE:
+		{
+			ind.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
+			ind.lte_system_information_indication.sib_type = 1;
+			ind.lte_system_information_indication.sib_length = 3;
+			//ind.lte_system_information_indication.sib...
+		}
+		break;
+		case NFAPI_RAT_TYPE_UTRAN:
+		{
+			ind.utran_system_information_indication.tl.tag = NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG;
+			ind.utran_system_information_indication.sib_length = 3;
+			//ind.utran_system_information_indication.sib...
+			
+		}
+		break;
+		case NFAPI_RAT_TYPE_GERAN:
+		{
+			ind.geran_system_information_indication.tl.tag = NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG;
+			ind.geran_system_information_indication.si_length = 3;
+			//ind.geran_system_information_indication.si...
+			
+		}
+		break;
+	}
+		
+	
+	nfapi_pnf_system_information_ind(config, &ind);		
+
+	return 0;
+}
+int nmm_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nmm_stop_request_t* req)
+{
+	nfapi_nmm_stop_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
+	resp.header.phy_id = req->header.phy_id;
+	resp.error_code = NFAPI_P4_MSG_OK;
+	nfapi_pnf_nmm_stop_resp(config, &resp);
+	return 0;
+}
+	
+int vendor_ext(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF_SIM] P5 %s %p\n", __FUNCTION__, msg);
+
+	switch(msg->message_id)
+	{
+		case P5_VENDOR_EXT_REQ:
+			{
+				vendor_ext_p5_req* req = (vendor_ext_p5_req*)msg;
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF_SIM] P5 Vendor Ext Req (%d %d)\n", req->dummy1, req->dummy2);
+				// send back the P5_VENDOR_EXT_RSP
+				vendor_ext_p5_rsp rsp;
+				memset(&rsp, 0, sizeof(rsp));
+				rsp.header.message_id = P5_VENDOR_EXT_RSP;
+				rsp.error_code = NFAPI_MSG_OK;
+				nfapi_pnf_vendor_extension(config, &rsp.header, sizeof(vendor_ext_p5_rsp));
+			}
+			break;
+	}
+	
+	return 0;
+}
+
+nfapi_p4_p5_message_header_t* pnf_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t* msg_size)
+{
+	if(message_id == P5_VENDOR_EXT_REQ)
+	{
+		(*msg_size) = sizeof(vendor_ext_p5_req);
+		return (nfapi_p4_p5_message_header_t*)malloc(sizeof(vendor_ext_p5_req));
+	}
+	
+	return 0;
+}
+
+void pnf_sim_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t* header)
+{
+	free(header);
+}
+
+
+int pnf_sim_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P5_VENDOR_EXT_RSP)
+	{
+		vendor_ext_p5_rsp* rsp = (vendor_ext_p5_rsp*)(header);
+		return (!push16(rsp->error_code, ppWritePackedMsg, end));
+	}
+	return 0;
+}
+
+int pnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t* codec)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P5_VENDOR_EXT_REQ)
+	{
+		vendor_ext_p5_req* req = (vendor_ext_p5_req*)(header);
+		return (!(pull16(ppReadPackedMessage, &req->dummy1, end) &&
+	  			  pull16(ppReadPackedMessage, &req->dummy2, end)));
+		 
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s (%d %d)\n", __FUNCTION__, req->dummy1, req->dummy2);
+	}
+	return 0;
+}
+int main(int argc, char *argv[])
+{
+	if (argc < 3)
+	{
+		printf("Use parameters: <IP Address of VNF P5> <P5 Port> <Config File>\n");
+		return 0;
+	}
+
+	set_thread_priority(50);
+
+	pnf_info pnf;
+	if(read_pnf_xml(pnf, argv[3]) < 0)
+	{
+		printf("Failed to read xml file>\n");
+		return 0;
+	}
+
+
+	nfapi_pnf_config_t* config = nfapi_pnf_config_create();
+
+	config->vnf_ip_addr = argv[1];
+	config->vnf_p5_port = atoi(argv[2]);
+
+	config->pnf_param_req = &pnf_param_request;
+	config->pnf_config_req = &pnf_config_request;
+	config->pnf_start_req = &pnf_start_request;
+	config->pnf_stop_req = &pnf_stop_request;
+	config->param_req = &param_request;
+	config->config_req = &config_request;
+	config->start_req = &start_request;
+	
+	config->measurement_req = &measurement_request;
+	config->rssi_req = &rssi_request;
+	config->cell_search_req = &cell_search_request;
+	config->broadcast_detect_req = &broadcast_detect_request;
+	config->system_information_schedule_req = &system_information_schedule_request;
+	config->system_information_req = &system_information_request;
+	config->nmm_stop_req = &nmm_stop_request;
+	
+	config->vendor_ext = &vendor_ext;
+
+	config->trace = &pnf_sim_trace;
+
+	config->user_data = &pnf;
+
+	// To allow custom vendor extentions to be added to nfapi
+	config->codec_config.unpack_vendor_extension_tlv = &pnf_sim_unpack_vendor_extension_tlv;
+	config->codec_config.pack_vendor_extension_tlv = &pnf_sim_pack_vendor_extention_tlv;
+	
+	config->allocate_p4_p5_vendor_ext = &pnf_sim_allocate_p4_p5_vendor_ext;
+	config->deallocate_p4_p5_vendor_ext = &pnf_sim_deallocate_p4_p5_vendor_ext;
+
+	config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension;
+	config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension;
+
+	return nfapi_pnf_start(config);
+	
+}
diff --git a/nfapi/open-nFAPI/sim_common/Makefile.am b/nfapi/open-nFAPI/sim_common/Makefile.am
new file mode 100644
index 0000000000..771b768a16
--- /dev/null
+++ b/nfapi/open-nFAPI/sim_common/Makefile.am
@@ -0,0 +1,31 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AUTOMAKE_OPTIONS=subdir-objects
+
+AM_CFLAGS = -I$(top_srcdir)/sim_common/public_inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/nfapi/public_inc -g -Wall -Werror
+
+AM_CXXFLAGS = -I$(top_srcdir)/sim_common/public_inc -I$(top_srcdir)/common/public_inc -std=c++11 -I$(top_srcdir)/nfapi/public_inc $(BOOST_CPPFLAGS) -g -Wall -Werror
+noinst_LIBRARIES =libnfapi_sim_common.a
+#libnfapi_sim_common_a_SOURCES = src/xml_property_tree.cpp src/pool.cpp
+libnfapi_sim_common_a_SOURCES = src/pool.cpp
+
+libnfapi_sim_common_a_CFLAGS =$(AM_CFLAGS)
+libnfapi_sim_common_a_CXXFLAGS =$(AM_CXXFLAGS)
+
+lib_LTLIBRARIES =libnfapi_sim_common.la
+#libnfapi_sim_common_la_SOURCES = src/xml_property_tree.cpp
+libnfapi_sim_common_la_SOURCES = src/pool.cpp
diff --git a/nfapi/open-nFAPI/sim_common/inc/pool.h b/nfapi/open-nFAPI/sim_common/inc/pool.h
new file mode 100644
index 0000000000..8591d939f9
--- /dev/null
+++ b/nfapi/open-nFAPI/sim_common/inc/pool.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _POOL_H_
+#define _POOL_H_
+
+#include <mutex>
+#include <map>
+#include <queue>
+#include <cassert>
+
+
+class pool_config
+{
+    public:
+        
+        size_t size;
+        uint16_t initial_count;
+};
+
+class memory_pool
+{
+    std::mutex mutex;
+	std::map<size_t, std::queue<uint8_t*>> free_store;
+	std::map<size_t, uint16_t> allocated_store;
+	
+    void init(std::vector<pool_config> config)
+    {
+        printf("memory_pool::init\n");
+        		
+        for(pool_config c : config)
+        {
+            // todo : use the initial count to allocate initial pool memory
+            free_store.insert(std::pair<size_t, 
+                                        std::queue<uint8_t*>>
+                                            (c.size, std::queue<uint8_t*>()));
+			allocated_store.insert(std::pair<size_t, uint16_t>(c.size, 0));
+        }
+    }
+    
+    memory_pool()
+    {
+        std::vector<pool_config> config 
+        {
+            {8, 0}, {32, 0}, {64, 0}, {128, 0}, {256, 0}, 
+            {1024, 0}, {4096, 0}, {8912, 0}
+            
+        };
+        
+        init(config);
+    }
+    
+    
+    uint16_t determine_pool_size(size_t size)
+    {
+        for(auto pool : free_store)
+        {
+            if(pool.first >= size)
+                return pool.first;
+        }
+        
+        return 0;
+    }
+    
+    uint8_t* alloc(size_t size)
+    {
+        if(size == 0)
+            return 0;
+            
+        uint8_t* ptr = 0;
+        size_t psize = determine_pool_size(size + 4);
+        
+        if(psize == 0)
+        {
+            ptr =  (uint8_t*)malloc(size + 4);
+			memset(ptr, 0, size + 4);	
+        }
+        else
+        {
+            mutex.lock();
+            
+            auto it = free_store.find(psize);
+            
+            if(it == free_store.end())
+            {
+                // Unknown pool size
+   				ptr =  (uint8_t*)malloc(psize + 4);
+				memcpy(ptr, &psize, 4);
+            }
+            else
+            {
+                if(it->second.size() > 0)
+                {
+                    // Take from the pool
+                    ptr = (uint8_t*)(it->second.front());
+    				it->second.pop();
+                }
+                else
+                {
+                    // No memory left in pool
+                    ptr =  (uint8_t*)malloc(psize + 4);
+				    memcpy(ptr, &psize, 4);
+                }
+            }
+            
+            mutex.unlock();
+        }
+
+        return (ptr + 4);
+    }
+    
+    void dealloc(uint8_t* ptr)
+    {
+      	if(ptr == 0)
+			return;
+			
+		uint8_t* _ptr = (uint8_t*)ptr;
+
+        size_t psize;
+		memcpy(&psize, _ptr - 4, 4);
+		
+		if(psize == 0)
+		{
+		    free(_ptr - 4);
+		}
+		else
+		{
+		    mutex.lock();
+		    
+		    auto it = free_store.find(psize);
+			if(it == free_store.end())
+			{
+			    free(_ptr - 4);
+			}
+			else
+			{
+			    assert((_ptr - 4) != 0);    
+			    it->second.push(_ptr - 4);
+			}
+		    
+		    mutex.unlock();
+		}
+  
+    }
+    
+    public:
+    
+    memory_pool(memory_pool const&) = delete;
+    void operator=(memory_pool const&) = delete;
+    
+    /*! Get the memory_pool instance */
+    static memory_pool& instance()
+    {
+        static memory_pool instance;
+        return instance;
+    }    
+
+    /*! Allocate a buffer from the memory_pool is at least size */
+    static uint8_t* allocate(size_t size)
+    {
+        return instance().alloc(size);
+    }
+    
+    /*! Return the buffer to the memory_pool */
+    static void deallocate(uint8_t* ptr)
+    {
+        return instance().dealloc(ptr);
+    }
+        
+    
+};
+
+#endif // _POOL_H_
diff --git a/nfapi/open-nFAPI/sim_common/inc/vendor_ext.h b/nfapi/open-nFAPI/sim_common/inc/vendor_ext.h
new file mode 100644
index 0000000000..d0fd57837d
--- /dev/null
+++ b/nfapi/open-nFAPI/sim_common/inc/vendor_ext.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _VENDOR_EXT_H_
+#define _VENDOR_EXT_H_
+
+#include "nfapi_interface.h"
+
+typedef enum 
+{
+	P5_VENDOR_EXT_REQ = NFAPI_VENDOR_EXT_MSG_MIN,
+	P5_VENDOR_EXT_RSP,
+
+	P7_VENDOR_EXT_REQ,
+	P7_VENDOR_EXT_IND
+
+} vendor_ext_message_id_e;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint16_t dummy1;
+	uint16_t dummy2;
+} vendor_ext_p5_req;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint16_t error_code;
+} vendor_ext_p5_rsp;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t dummy1;
+	uint16_t dummy2;
+} vendor_ext_p7_req;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t error_code;
+} vendor_ext_p7_ind;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t dummy;
+} vendor_ext_tlv_1;
+
+#define VENDOR_EXT_TLV_1_TAG 0xF001
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t dummy;
+} vendor_ext_tlv_2;
+
+#define VENDOR_EXT_TLV_2_TAG 0xF002
+
+
+
+
+#endif // _VENDOR_EXT_
diff --git a/nfapi/open-nFAPI/sim_common/src/pool.cpp b/nfapi/open-nFAPI/sim_common/src/pool.cpp
new file mode 100644
index 0000000000..47d9cfa992
--- /dev/null
+++ b/nfapi/open-nFAPI/sim_common/src/pool.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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.
+ */
diff --git a/nfapi/open-nFAPI/vnf/Makefile.am b/nfapi/open-nFAPI/vnf/Makefile.am
new file mode 100644
index 0000000000..ae8d2bb3d6
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/Makefile.am
@@ -0,0 +1,43 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+
+AUTOMAKE_OPTIONS=subdir-objects
+
+AM_CPPFLAGS = -I$(top_srcdir)/vnf/inc\
+			  -I$(top_srcdir)/vnf/public_inc\
+			  -I$(top_srcdir)/nfapi/public_inc\
+			  -I$(top_srcdir)/common/public_inc\
+			  -Wall -Werror -g
+
+
+noinst_LIBRARIES = libnfapi_vnf.a
+
+libnfapi_vnf_a_SOURCES = src/vnf.c\
+						 src/vnf_p7.c\
+						 src/vnf_interface.c\
+						 src/vnf_p7_interface.c
+
+LDADD = -lsctp  ../common/bin/libnfapi_common.a
+
+libnfapi_vnf_a_CFLAGS =$(AM_CFLAGS)
+
+lib_LTLIBRARIES = libnfapi_vnf.la
+
+libnfapi_vnf_la_SOURCES =  src/vnf.c\
+						 src/vnf_p7.c\
+						 src/vnf_interface.c\
+						 src/vnf_p7_interface.c
diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h
new file mode 100644
index 0000000000..4fd8d2b91d
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/inc/vnf.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _VNF_H_
+#define _VNF_H_
+
+#include "nfapi_vnf_interface.h"
+
+typedef struct 
+{
+
+	nfapi_vnf_config_t _public;
+
+	uint8_t terminate;
+	uint8_t sctp;
+
+	uint8_t tx_message_buffer[NFAPI_MAX_PACKED_MESSAGE_SIZE];
+	uint16_t next_phy_id;
+	
+} vnf_t;
+
+
+int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len);
+int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len);
+
+int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf);
+
+void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info);
+nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id);
+void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node);
+nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx);
+#endif // _VNF_H_
diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h
new file mode 100644
index 0000000000..fc2ab4e6b5
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _VNF_P7_H_
+#define _VNF_P7_H_
+
+#include "nfapi_vnf_interface.h"
+
+#define TIMEHR_SEC(_time_hr) ((uint32_t)(_time_hr) >> 20)
+#define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF)
+#define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF))
+
+
+
+typedef struct {
+	uint8_t* buffer;
+	uint16_t length;
+} vnf_p7_rx_message_segment_t;
+
+typedef struct vnf_p7_rx_message vnf_p7_rx_message_t;
+
+typedef struct vnf_p7_rx_message {
+	uint8_t sequence_number;
+	uint8_t num_segments_received;
+	uint8_t num_segments_expected;
+
+	// the spec allows of upto 128 segments, this does seem excessive
+	vnf_p7_rx_message_segment_t segments[128];
+
+	uint32_t rx_hr_time;
+
+	vnf_p7_rx_message_t* next;
+} vnf_p7_rx_message_t;
+
+typedef struct {
+
+	vnf_p7_rx_message_t* msg_queue;
+
+} vnf_p7_rx_reassembly_queue_t;
+
+typedef struct nfapi_vnf_p7_connection_info {
+
+	/*! The PHY id */
+	int phy_id;
+
+
+	// this does not belong here...
+	uint8_t stream_id;
+
+	/*! Flag indicating the sync state of the P7 conenction */
+	uint8_t in_sync;
+
+	int dl_out_sync_offset; 
+	int dl_out_sync_period; // ms (as a pow2)
+
+	int dl_in_sync_offset; 
+	int dl_in_sync_period; // ms (as a pow2)
+
+	uint8_t filtered_adjust;
+	uint16_t min_sync_cycle_count;
+	uint32_t latency[8];
+	uint32_t average_latency;
+	int32_t sf_offset_filtered;
+	int32_t sf_offset_trend;
+	int32_t sf_offset;
+	uint16_t zero_count;
+	int32_t adjustment;
+	int32_t insync_minor_adjustment;
+	int32_t insync_minor_adjustment_duration;
+
+	uint32_t previous_t1;
+	uint32_t previous_t2;
+	int32_t previous_sf_offset_filtered;
+
+	int sfn_sf;
+
+	int socket;
+	struct sockaddr_in local_addr;
+	struct sockaddr_in remote_addr;
+	
+	vnf_p7_rx_reassembly_queue_t reassembly_queue;
+	uint8_t* reassembly_buffer;
+	uint32_t reassembly_buffer_size;
+
+	uint32_t sequence_number;
+
+	struct nfapi_vnf_p7_connection_info* next;
+
+} nfapi_vnf_p7_connection_info_t;
+
+typedef struct {
+
+	nfapi_vnf_p7_config_t _public;
+	
+	// private data
+	uint8_t terminate;
+	nfapi_vnf_p7_connection_info_t* p7_connections;
+	int socket;
+	uint32_t sf_start_time_hr;
+	uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info?
+	uint16_t rx_message_buffer_size;
+	
+} vnf_p7_t;
+
+uint32_t vnf_get_current_time_hr(void);
+
+uint16_t increment_sfn_sf(uint16_t sfn_sf);
+int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info);
+int send_mac_subframe_indications(vnf_p7_t* config);
+int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 );
+
+void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node);
+nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id);
+nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id);
+
+int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header);
+
+void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header);
+void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu);
+
+
+#endif // _VNF_P7_H_
diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
new file mode 100644
index 0000000000..462901391a
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
@@ -0,0 +1,995 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _NFAPI_VNF_INTERFACE_H_
+#define _NFAPI_VNF_INTERFACE_H_
+
+#include "nfapi_interface.h"
+#include "debug.h"
+
+#include "netinet/in.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define NFAPI_MAX_PACKED_MESSAGE_SIZE 8192
+
+/*! The nfapi VNF phy configuration information
+ */
+typedef struct nfapi_vnf_phy_info
+{
+	/*! The P5 Index */
+	int p5_idx;	//which p5 connection
+	/*! The PHY ID */
+	int phy_id; //phy_id
+
+	/*! Timing window */
+	uint8_t timing_window;
+	/*! Timing info mode */
+	uint8_t timing_info_mode;
+	/*! Timing info period */
+	uint8_t timing_info_period;
+
+	/*! P7 UDP socket information for the pnf */
+	struct sockaddr_in p7_pnf_address;
+	/*! P7 UDP socket information for the vnf */
+	struct sockaddr_in p7_vnf_address;
+
+	struct nfapi_vnf_phy_info* next;
+} nfapi_vnf_phy_info_t;
+
+/*! The nfapi VNF pnf configuration information
+ */
+typedef struct nfapi_vnf_pnf_info
+{
+	/*! The P5 Index */
+	int p5_idx;
+	/*! The P5 socket */
+	int p5_sock;
+	/*! Flag indicating if the pnf is connected */
+	uint8_t connected;
+
+	/*! P5 SCTP socket information for the pnf */
+	struct sockaddr_in p5_pnf_sockaddr;
+
+	/*! Flag indicating if this pnf should be deleted */
+	uint8_t to_delete;
+
+	struct nfapi_vnf_pnf_info* next;
+
+} nfapi_vnf_pnf_info_t;
+
+typedef struct nfapi_vnf_config nfapi_vnf_config_t;
+
+/*! The nfapi VNF configuration information
+ */
+typedef struct nfapi_vnf_config
+{
+	/*! A user define callback to override the default memory allocation */
+	void* (*malloc)(size_t size);
+	/*! A user define callback to override the default memory deallocation */
+	void (*free)(void*);
+	/*! A user define callback to handle trace from the pnf */
+	void (*trace)(nfapi_trace_level_t level, const char* message, ...);
+
+	/*! The port the VNF P5 SCTP connection listens on
+	 *
+	 *  By default this will be set to 7701. However this can be changed if
+	 *  required.
+	 */
+	int vnf_p5_port;
+
+	// todo : for enabling ipv4/ipv6
+	int vnf_ipv4;
+	int vnf_ipv6;
+
+	/*! List of connected pnfs */
+	nfapi_vnf_pnf_info_t* pnf_list;
+
+	/*! List of configured phys */
+	nfapi_vnf_phy_info_t* phy_list;
+
+	/*! Configuration options for the p4 p5 pack unpack functions */
+	nfapi_p4_p5_codec_config_t codec_config;
+	
+	/*! Optional user defined data that will be avaliable in the callbacks*/
+	void* user_data;
+
+	/*! \brief Callback indicating that a pnf has established connection 
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 used to indicate this pnf p5 connection
+	 * 
+	 *  The client is expected to send the PNF_PARAM.request in response to 
+	 *  the connection indication
+	 * 
+	 *  \todo Do we need to send the address information of the PNF?
+	 */
+	int (*pnf_connection_indication)(nfapi_vnf_config_t* config, int p5_idx);
+	
+	/*! \brief Callback indicating that a pnf has lost connection 
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 used to indicate this pnf p5 connection
+	 *
+	 *  The p5_idx may be used for future new p5 connections
+	 *
+	 *  The client is responsiable for communicating to the p7 instance(s) that
+	 *  may be associated with this p5 that they should be deleted using the 
+	 *  nfapi_vnf_p7_del_pnf functon
+	 * 
+	 */
+	int (*pnf_disconnect_indication)(nfapi_vnf_config_t* config, int p5_idx);
+
+	// p5 interface functions
+	
+	/*! \brief A callback to handle the PNF_PARAM.resp
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded PNF_PARAM.response. This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The PNF_PARAM.resp contains the capability of the PNF identified by the
+	 *  p5_idx. 
+	 *  
+	 *  The client is expected to send the PNF_CONFIG.request after receiving the
+	 *  PNF_PARAM.resp. This can be done in the call back. 
+	 *
+	 *  It is expected that the client when building the PNF_CONFIG.request will
+	 *  used the nfapi_vnf_allocate_phy() to allocate unique phy id for each FAPI
+	 *  instance the client wishes to create.
+	 *  
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*pnf_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_response_t* resp);
+	
+	/*! A callback for the PNF_CONFIG.resp 
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded PNF_CONFIG.response. This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The PNF_CONFIG.resp contains the result of the PNF_CONFIG.request for the 
+	  * PNF identified by the p5_idx. 
+	 *  
+	 *  The client is expected to send the PNF_START.request after receiving the
+	 *  PNF_PARAM.resp. This can be done in the call back. 
+	 *  
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*pnf_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* resp);
+	
+	/*! A callback for the PNF_START.resp
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded PNF_START.response. This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The PNF_START.resp contains the result of the PNF_START.request for the 
+	 *  PNF identified by the p5_idx. 
+	 *  
+	 *  The client is expected to send the PARAM.request for each FAPI instance 
+	 *  that has been created in the PNF. 
+	 *  
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp);
+	
+	/*! A callback for the PNF_STOP.resp
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded PNF_STOP.response. This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The PNF_STOP.response contains the result of the PNF_STOP.request for the 
+     *  PNF identified by the p5_idx. 
+	 *  
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*pnf_stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_response_t* resp);
+	
+	/*! A callback for the PARAM.resp
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded PARAM.resposne. This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The PARAM.request contains the capabilities of the FAPI instance identified
+	 *  by the phy_id
+	 *
+	 *  The client is expected to send the CONFIG.request after receiving the
+	 *  PARAM.response. This can be done in the call back. The PARAM.response 
+	 *  contains the PNF P7 address (ipv4 or ipv6) and port. This information 
+	 *  is used when calling the nfapi_vnf_p7_add_pnf()
+	 * 
+	 *  The client is responsible for identifing the VNF P7 ip address 
+	 *  (ipv4 or ipv6) and port for the VNF P7 entity which will be sent to the
+	 *  PNF P7 entity. That endpoint should be valid before send the 
+	 * CONFIG.request.
+	 * 
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* resp);
+	
+	/*! A callback for the CONFIG.response
+     *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded CONFIG.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The CONFIG.response contains the result of the CONFIG.request
+	 *
+	 * 
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* resp);
+	
+	/*! A callback for the START.resp
+     *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded START.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The START.response contains the result of the START.request
+	 *
+	 * 
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */
+	int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp);
+	
+	/*! A callback for the STOP.resp
+     *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded STOP.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The STOP.response contains the result of the STOP.request
+	 *
+	 * 
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_response_t* resp);
+	 
+	/*! A callback for the MEASUREMENT.resp 
+     *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded MEASUREMENT.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 *  
+	 *  The MEASUREMENT.response contains the result of the MEASUREMENT.request
+	 * 
+	 *  The resp may contain pointers to dyanmically allocated sub structures  
+	 *  such as the vendor_extention. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*measurement_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_response_t* resp);
+
+	// p4 interface functions
+	/*! A callback for the RSSI.resp 
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded RSSI.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 */
+	int (*rssi_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_response_t* resp);
+	
+	/*! A callback for the RSSI.indication
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded RSSI.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 */
+	int (*rssi_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_indication_t* ind);
+	
+	/*! A callback for the CELL_SEARCH.response
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded CELL_SEARCH.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 */
+	int (*cell_search_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_response_t* resp);
+	
+	/*! A callback for the CELL_SEARCH.indication
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded CELL_SEARCH.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 */
+	int (*cell_search_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_indication_t* ind);
+	
+	/*! A callback for the BROADCAST_DETECT.response
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded BROADCAST_DETECT.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	 */
+	int (*broadcast_detect_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_response_t* resp);
+	
+	/*! A callback for the BROADCAST_DETECT.indication
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded BROADCAST_DETECT.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	 
+	 */
+	int (*broadcast_detect_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_indication_t* ind);
+	
+	/*! A callback for the SYSTEM_INFORMATION_SCHEUDLE.response
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded SYSTEM_INFORMATION_SCHEUDLE.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	 
+	 */
+	int (*system_information_schedule_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_response_t* resp);
+	
+	/*! A callback for the SYSTEM_INFORMATION_SCHEUDLE.indication
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded SYSTEM_INFORMATION_SCHEUDLE.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	
+	 */
+	int (*system_information_schedule_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_indication_t* ind);
+	
+	/*! A callback for the SYSTEM_INFORMATION.response
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded SYSTEM_INFORMATION.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	
+	 */
+	int (*system_information_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_response_t* resp);
+	
+	/*! A callback for the SYSTEM_INFORMATION.indication
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded SYSTEM_INFORMATION.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.	
+	 */
+	int (*system_information_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_indication_t* ind);
+	
+	/*! A callback for the NMM_STOP.response
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded NMM_STOP.response This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.		
+	 */
+	int (*nmm_stop_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_response_t* resp);
+	
+
+	/*! A callback for any vendor extension message received
+	 *  \param config A pointer to the vnf configuration
+	 *  \param p5_idx The p5 index used to indicate a particular pnf p5 connection
+	 *  \param resp A data structure for the decoded vendor extention message 
+	 *  \return not currently used.	
+	 */
+	int (*vendor_ext)(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg);
+
+	/*! A callback to allocate vendor extension messages
+	 *  \param message_id The message is taken from the message header
+	 *  \param msg_size The is the vendor extention message that has been allocated. 
+	 *					The callee must set this value
+	 *	\return A pointer to an allocated vendor extention message
+	 */
+	nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
+	
+	/*! A callback to deallocate vendor extension messages
+	 *  \param header A pointer to an allocated vendor extention message
+	 */
+	void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header);
+
+
+
+
+	
+	
+} nfapi_vnf_config_t;
+
+/*! Creates and initialise the vnf config structure before use
+ * \return A pointer to a vnf config structure
+ */
+nfapi_vnf_config_t* nfapi_vnf_config_create(void);
+
+/*! Delete an vnf config
+ */
+void nfapi_vnf_config_destory(nfapi_vnf_config_t* config);
+
+
+/*! Start the VNF library. 
+ * \param config A pointer to a vnf config
+ * \return 0 means success, -1 failure
+ *
+ * The config should be initailize with port the vnf should listen on and
+ * the callback set to functions that will be called when a nFAPI message is 
+ * recevied before calling nfapi_vnf_start.
+ * 
+ * This function will not return untill nfapi_vnf_stop is called
+ */
+int nfapi_vnf_start(nfapi_vnf_config_t* config);
+
+/*! Stop the VNF library. 
+ * \param config A pointer to a vnf config
+ * \return 0 means success, -1 failure
+ * 
+ * This function will cause the nfapi_vnf_start function to return
+ */
+int nfapi_vnf_stop(nfapi_vnf_config_t* config);
+
+/*! Allocates a PHY ID for the PNF PHY instance managed by this VNF
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index return by the callbacks
+ * \param phy_id A pointer to a phy_id that will be set by this function
+ * \return  0 means success, -1 failure
+ * 
+ * Called before nfapi_vnf_config_req to allocate a vnf phy instance. This
+ * function will return unqiue phy_id to be used for this identify the phy
+ *
+ */
+int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy_id);
+
+// P5 Request functions
+//
+/*! Send the PNF_PARAM.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a PNF_PARAM.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req);
+
+/*! Send the PNF_CONFIG.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a PNF_CONFIG.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_config_request_t* req);
+
+/*! Send the PNF_START.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a PNF_START.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_start_request_t* req);
+
+/*! Send the PNF_STOP.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a PNF_STOP.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_stop_request_t* req);
+
+/*! Send the PARAM.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a PARAM.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req);
+
+/*! Send the CONFIG.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a CONFIG.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req);
+
+/*! Send the START.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a START.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req);
+
+/*! Send the STOP.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a STOP.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req);
+
+/*! Send the MEASUREMENT.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a MEASUREMENT.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req);
+
+// P4 Request functions
+/*! Send the RSSI.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a RSSI.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_rssi_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_request_t* req);
+
+/*! Send the CELL_SEARCH.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a CELL_SEARCH.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_cell_search_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_request_t* req);
+
+/*! Send the BROADCAST_DETECT.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a BROADCAST_DETECT.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_request_t* req);
+
+/*! Send the SYSTEM_INFORMATION_SCHEDULE.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a SYSTEM_INFORMATION_SCHEDULE.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_request_t* req);
+
+/*! Send the SYSTEM_INFORMATION.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a SYSTEM_INFORMATION.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_system_information_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_request_t* req);
+
+/*! Send the NMM_STOP.request
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param req A pointer to a NMM_STOP.request message structure
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_request_t* req);
+
+/*! Send a vendor extension message
+ * \param config A pointer to a vnf config
+ * \param p5_idx The P5 index
+ * \param msg A poiner to a vendor extention message
+ * \return  0 means success, -1 failure
+ */
+int nfapi_vnf_vendor_extension(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg);
+
+//-----------------------------------------------------------------------------
+
+/*! The nfapi VNF P7 connection information
+ */
+typedef struct nfapi_vnf_p7_config nfapi_vnf_p7_config_t;
+
+/*! The nfapi VNF P7 configuration information
+ */
+typedef struct nfapi_vnf_p7_config
+{
+	/*! A user define callback to override the default memory allocation
+	 * \param size Size of the memory block to allocate
+	 * \return a pointer to a memory block
+	 *
+	 * If not set the vnf p7 library will use malloc
+	 */
+	void* (*malloc)(size_t size);
+	
+	/*! A user define callback to override the default memory deallocation
+	 * \param ptr Pointer to a memory block to deallocate
+	 *
+	 * If not set the vnf p7 library will use free
+	 */
+	void (*free)(void*);
+	
+	/*! A user define callback to handle trace from the pnf
+	 * \param level The trace level 
+	 * \param message The trace string
+	 */
+	void (*trace)(nfapi_trace_level_t level, const char* message, ...);
+
+	/*! The port the vnf p7 will receive on */
+	int port;
+
+	/*! Flag to indicate of the pnf should use the P7 checksum */
+	uint8_t checksum_enabled;
+
+	/*! The maxium size of a P7 segement. If a message is large that this it
+	 * will be segemented */
+	uint16_t segment_size;
+	uint16_t max_num_segments;
+
+	/*! Configuration option for the p7 pack unpack functions*/
+	nfapi_p7_codec_config_t codec_config;
+
+	/* ! Call back to indicate the sync state with the PNF PHY
+	 * \param config A pointer to the vnf p7 configuration
+	 * \param sync Indicating if the pnf is in sync or not
+	 * \return not currently used
+	 *
+	 * sync = 0  : in sync
+	 * sync != 0 : out of sync
+	 */
+	int (*sync_indication)(struct nfapi_vnf_p7_config* config, uint8_t sync);
+
+	/*! A callback for the subframe indication
+	 * \param config A pointer to the vnf p7 configuration
+	 * \param phy_id The ID for the PNF PHY instance
+	 * \param sfn_sf The SFN SF number formated as per the FAPI specification
+	 * \return not currently used
+	 *
+	 * This callback is an indication for the VNF to generate the downlink subframe messages
+	 * for sfn/sf. This indicatoin is called every millisecond
+	 *
+	 * The VNF P7 Lib will adjust the subframe timing to 'catch-up' or 'slow-down' with the PNF PHY's
+	 *
+	 * \todo Need some way the tell the VNF how long it has
+	 */
+	
+	int (*subframe_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn_sf);
+
+	/*! A callback for the HARQ.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded HARQ.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*harq_indication)(struct nfapi_vnf_p7_config* config, nfapi_harq_indication_t* ind);
+	
+	/*! A callback for the CRC.ind
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded CRC.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*crc_indication)(struct nfapi_vnf_p7_config* config, nfapi_crc_indication_t* ind);
+	
+	/*! A callback for the RX_ULSCH.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded RX_ULSCH.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 *
+	 *  Note that the rx_indication may hold one or many uplink pdus in the 
+	 *  ind.rx_indication_body.rx_pdu_list
+	 */	
+	int (*rx_indication)(struct nfapi_vnf_p7_config* config, nfapi_rx_indication_t* ind);
+	
+	/*! A callback for the RACH.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded RACH.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*rach_indication)(struct nfapi_vnf_p7_config* config, nfapi_rach_indication_t* ind);
+	
+	/*! A callback for the SRS.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded SRS.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*srs_indication)(struct nfapi_vnf_p7_config* config, nfapi_srs_indication_t* ind);
+	
+	/*! A callback for the RX_SR.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded RX_SR.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*sr_indication)(struct nfapi_vnf_p7_config* config, nfapi_sr_indication_t* ind);
+	
+	/*! A callback for the RX_CQI.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded RX_CQI.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*cqi_indication)(struct nfapi_vnf_p7_config* config, nfapi_cqi_indication_t* ind);
+	
+	/*! A callback for the LBT_DL.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded LBT_DL.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*lbt_dl_indication)(struct nfapi_vnf_p7_config* config, nfapi_lbt_dl_indication_t* ind);
+	
+	/*! A callback for the NB_HARQ.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded LBT_DL.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*nb_harq_indication)(struct nfapi_vnf_p7_config* config, nfapi_nb_harq_indication_t* ind);	
+	
+	/*! A callback for the NRACH.indication
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param ind A data structure for the decoded LBT_DL.indication This will 
+	 *              have been allocated on the stack. 
+	 *  \return not currently used.
+	 * 
+	 *  The ind may contain pointers to dyanmically allocated sub structures  
+	 *  such as the pdu. The dyanmically allocated structure will 
+	 *  be deallocated on return. If the client wishes to 'keep' the structures 
+	 *  then the substructure pointers should be set to 0 and then the client should
+	 *  use the codec_config.deallocate function to release it at a future point
+	 */	
+	int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind);		
+	
+	/*! A callback for any vendor extension messages
+     *  \param config A pointer to the vnf p7 configuration
+	 *  \param msg A data structure for the decoded vendor extention message allocated
+	 *			   using the allocate_p7_vendor_ext callback
+	 *  \return not currently used.
+	 */	
+	int (*vendor_ext)(struct nfapi_vnf_p7_config* config, nfapi_p7_message_header_t* msg);
+
+	/*! Optional userdata that will be passed back in the callbacks*/
+	void* user_data;
+	
+	/*! A callback to allocate a memory for a vendor extension message
+	 *  \param message_id The message is taken from the p7 message header
+	 *  \param msg_size The is the vendor extention message that has been allocated. 
+	 *					The callee must set this value
+	 *	\return A pointer to an allocated vendor extention message
+	 */
+	nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size);
+	
+	/*! A callback to deallocate a vendor extension message
+	 *  \param header A pointer to an allocated vendor extention message
+	 */
+	void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header);
+
+
+} nfapi_vnf_p7_config_t;
+
+/*! Creates and initializes the nfapi_vnf_p7_config structure before use
+ *  \return A pointer to an allocated vnf p7 configuration
+ */
+nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create(void);
+
+/*! Cleanup and delete nfapi_vnf_p7_config structure
+ *  \param config A pointer to an vnf p7 configuration structure
+ *
+ *  The pointer to the config will not long be valid after this call
+ */
+ 
+void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config);
+
+/*! Start the VNF P7 library.
+ *  \param config A pointer to an vnf p7 configuration structure
+ *	\return A status value. 0 equal success, -1 indicates failure
+ *
+ * This function is blocking and will not return until the nfapi_vnf_p7_stop
+ * function is called. 
+ */
+ 
+int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config);
+
+/*! Stop the VNF P7 library. 
+ *  \param config A pointer to an vnf p7 configuration structure
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ * This function will cause the nfapi_vnf_p7_start function to return
+ */
+int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config);
+
+/*! Release a P7 message back to the vnf_p7 library. This should be used if the
+ *  callback return 0 in the case where MAC wants to keep the message for
+ *  futher processing.
+ *  This function will release any pdu's is they are non-null. If the uplink
+ *  PDU need to be kept then they pdu pointer should be set to 0 in the message
+ *  and then the nfapi_vnf_p7_release_pdu message can be used to release the
+ *  pdu later.
+ */
+int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t*);
+
+/*! Release a P7 pdu's back to the vnf_p7 library.
+ */
+int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t* config, void*);
+
+/*! Add a vnf p7 instance to the vnf p7 module
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param pnf_p7_addr The udp address the pnf p7 entity has chosen 
+ *  \param pnf_p7_port The udp port the pnf p7 entity has chosen
+ *  \param phy_id The unique phy id for the pnf p7 entity
+ *  \return A status value. 0 equal success, -1 indicates failure
+ *
+ * This function should be used to each pnf p7 entity that is to be added to this
+ * vnf p7 entity. Once added the vnf p7 entity will start establish sync with the
+ * pnf p7 entity and that has been sucessfull will generate subframe indications for it
+ */
+int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, int pnf_p7_port, int phy_id);
+
+/*! Delete a vnf p7 instance to the vnf p7 module
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param phy_id The unique phy id for the pnf p7 entity
+ *  \return A status value. 0 equal success, -1 indicates failure
+ *
+ * This function should be used to remove a pnf p7 entity from the vnf p7 entity
+ */
+int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id);
+
+/*! Send the DL_CONFIG.request
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded DL_CONFIG.request.
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req);
+
+/*! Send the UL_CONFIG.request
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded UL_CONFIG.request.
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req);
+
+/*! Send the HI_DCI0.request
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded HI_DCI0.request.
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req);
+
+/*! Send the TX.req
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded HI_DCI0.request.
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req);
+
+/*! Send the LBT_DL_CONFIG.requst
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded LBT_DL_CONFIG.request.
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req);
+
+/*! Send a vendor extension message
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param msg A data structure for the decoded vendor extention message
+ *	\return A status value. 0 equal success, -1 indicates failure
+ * 
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // _NFAPI_PNF_INTERFACE_H_
diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c
new file mode 100644
index 0000000000..6800ee21d2
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/src/vnf.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "vnf.h"
+
+
+void* vnf_malloc(nfapi_vnf_config_t* config, size_t size)
+{
+	if(config->malloc)
+	{
+		return (config->malloc)(size);
+	}
+	else
+	{
+		return calloc(1, size); 
+	}
+}
+void vnf_free(nfapi_vnf_config_t* config, void* ptr)
+{
+	if(config->free)
+	{
+		return (config->free)(ptr);
+	}
+	else
+	{
+		return free(ptr); 
+	}
+}
+
+void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Adding phy p5_idx:%d phy_id:%d\n", info->p5_idx, info->phy_id);
+	info->next = config->phy_list;
+	config->phy_list = info;
+}
+
+nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id)
+{
+	nfapi_vnf_phy_info_t* curr = config->phy_list;
+	while(curr != 0)
+	{
+		if(curr->phy_id == phy_id)
+			return curr;
+
+		curr = curr->next;
+	}
+
+	return 0;
+}
+
+
+
+
+void nfapi_vnf_pnf_list_add(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* node)
+{
+	node->next = config->pnf_list;
+	config->pnf_list = node;
+}
+
+
+nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5_idx)
+{
+	NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : config->pnf_list:%p\n", __FUNCTION__, config->pnf_list);
+
+	nfapi_vnf_pnf_info_t* curr = config->pnf_list;
+	while(curr != 0)
+	{
+		if(curr->p5_idx == p5_idx)
+                {
+                  NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : curr->p5_idx:%d p5_idx:%d\n", __FUNCTION__, curr->p5_idx, p5_idx);
+			return curr;
+                        }
+
+                NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : curr->next:%p\n", __FUNCTION__, curr->next);
+
+		curr = curr->next;
+	}
+
+	return 0;
+}
+
+void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_PARAM.reponse\n");
+
+		nfapi_pnf_param_response_t msg;
+			
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			// Invoke the call back
+			if(config->pnf_param_resp)
+			{
+				(config->pnf_param_resp)(config, p5_idx, &msg);
+			}
+		}	
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_CONFIG_RESPONSE\n");
+		
+		nfapi_pnf_config_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			// Invoke the call back
+			if(config->pnf_config_resp)
+			{
+				(config->pnf_config_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_START_RESPONSE\n");
+	
+		nfapi_pnf_start_response_t msg;
+	
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->pnf_start_resp)
+			{
+				(config->pnf_start_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_pnf_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_STOP_RESPONSE\n");
+	
+		nfapi_pnf_stop_response_t msg;
+
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->pnf_stop_resp)
+			{
+				(config->pnf_stop_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+
+	}
+}
+
+void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n");
+		
+		nfapi_param_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			
+			if (msg.error_code == NFAPI_MSG_OK)
+			{
+				nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id);
+		
+				if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag)
+				{
+					struct sockaddr_in sockAddr;
+		
+					(void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH);
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr));
+		
+					// store address
+					phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr;
+				}
+		
+				if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag)
+				{
+					struct sockaddr_in6 sockAddr6;
+					char addr6[64];
+					(void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH);
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6)));
+				}
+				
+				if (msg.nfapi_config.p7_pnf_port.tl.tag)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value);
+		
+					// store port
+					phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value);
+				}
+			}
+			
+			if(config->param_resp)
+			{
+				(config->param_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CONFIG_RESPONSE\n");
+			
+		nfapi_config_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 )
+		{
+			if(config->config_resp)
+			{
+				(config->config_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{	
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n");
+
+		nfapi_start_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->start_resp)
+			{
+				(config->start_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received STOP.response\n");
+	
+		nfapi_stop_response_t msg;
+			
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->stop_resp)
+			{
+				(config->stop_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_measurement_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received MEASUREMENT.response\n");
+		
+		nfapi_measurement_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->measurement_resp)
+			{
+				(config->measurement_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_rssi_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received RSSI.response\n");		
+
+		nfapi_rssi_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->rssi_resp)
+			{
+				(config->rssi_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_rssi_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received RSSI.indication\n");	
+
+		nfapi_rssi_indication_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->rssi_ind)
+			{
+				(config->rssi_ind)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_cell_search_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CELL_SEARCH.response\n");
+		
+		nfapi_cell_search_response_t msg;
+	
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->cell_search_resp)
+			{
+				(config->cell_search_resp)(config, p5_idx, &msg);
+			}	
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_cell_search_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_cell_search_indication: NULL parameters\n");
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CELL_SEARCH.indication\n");
+	
+		nfapi_cell_search_indication_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->cell_search_ind)
+			{
+				(config->cell_search_ind)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_cell_search_response: Unpack message failed, ignoring\n");
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_broadcast_detect_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received BROADCAST_DETECT.response\n");
+
+		nfapi_broadcast_detect_response_t msg;
+
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->broadcast_detect_resp)
+			{
+				(config->broadcast_detect_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_broadcast_detect_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received BROADCAST_DETECT.indication\n");
+
+		nfapi_broadcast_detect_indication_t msg;
+
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->broadcast_detect_ind)
+			{
+				(config->broadcast_detect_ind)(config, p5_idx, &msg);
+			}	
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+			return;
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_system_information_schedule_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION_SCHEDULE.response\n");
+	
+		nfapi_system_information_schedule_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->system_information_schedule_resp)
+			{
+				(config->system_information_schedule_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+			
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_system_information_schedule_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION_SCHEDULE.indication\n");
+
+		nfapi_system_information_schedule_indication_t msg;
+
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->system_information_schedule_ind)
+			{
+				(config->system_information_schedule_ind)(config, p5_idx, &msg);
+			}	
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_system_information_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION.response\n");
+
+		nfapi_system_information_response_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0)
+		{
+			if(config->system_information_resp)
+			{
+				(config->system_information_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+	
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_system_information_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received SYSTEM_INFORMATION.indication\n");
+		
+		nfapi_system_information_indication_t msg;
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+			return;
+		}
+	
+		if(config->system_information_ind)
+		{
+			(config->system_information_ind)(config, p5_idx, &msg);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+}
+
+void vnf_handle_nmm_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "Received NMM_STOP.response\n");	
+		
+		nfapi_nmm_stop_response_t msg;	
+		
+		// unpack the message
+		if (nfapi_p4_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(nfapi_nmm_stop_response_t), &config->codec_config) >= 0)
+		{
+			if(config->nmm_stop_resp)
+			{
+				(config->nmm_stop_resp)(config, p5_idx, &msg);
+			}
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+		}
+		
+		// make sure to release any dyanmic part of the message
+		if(msg.vendor_extension)
+			config->codec_config.deallocate(msg.vendor_extension);
+	}
+	
+}
+
+void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx, uint16_t message_id)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	
+	if(config->allocate_p4_p5_vendor_ext && config->deallocate_p4_p5_vendor_ext)
+	{
+		uint16_t msg_size;
+		
+		nfapi_p4_p5_message_header_t* msg = config->allocate_p4_p5_vendor_ext(message_id, &msg_size);
+
+		if(msg)
+		{
+			if(nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &config->codec_config) >= 0)
+			{
+				if(config->vendor_ext)
+					config->vendor_ext(config, p5_idx, msg);
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__);
+			}
+			
+			config->deallocate_p4_p5_vendor_ext(msg);
+		}
+		else
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n");
+		}
+	}
+}
+
+void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config)
+{
+	nfapi_p4_p5_message_header_t messageHeader;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH || config == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p4_p5_message: invalid input params\n");
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &config->codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	switch (messageHeader.message_id)
+	{
+		case NFAPI_PNF_PARAM_RESPONSE:
+			vnf_handle_pnf_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_PNF_CONFIG_RESPONSE:
+			vnf_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_PNF_START_RESPONSE:
+			vnf_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_PNF_STOP_RESPONSE:
+			vnf_handle_pnf_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_PARAM_RESPONSE:
+			vnf_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_CONFIG_RESPONSE:
+			vnf_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_START_RESPONSE:
+			vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_STOP_RESPONSE:
+			vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_MEASUREMENT_RESPONSE:
+			vnf_handle_measurement_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_RSSI_RESPONSE:
+			vnf_handle_rssi_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_RSSI_INDICATION:
+			vnf_handle_rssi_indication(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_CELL_SEARCH_RESPONSE:
+			vnf_handle_cell_search_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_CELL_SEARCH_INDICATION:
+			vnf_handle_cell_search_indication(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_RESPONSE:
+			vnf_handle_broadcast_detect_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_BROADCAST_DETECT_INDICATION:
+			vnf_handle_broadcast_detect_indication(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE:
+			vnf_handle_system_information_schedule_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION:
+			vnf_handle_system_information_schedule_indication(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_RESPONSE:
+			vnf_handle_system_information_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_SYSTEM_INFORMATION_INDICATION:
+			vnf_handle_system_information_indication(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		case NFAPI_NMM_STOP_RESPONSE:
+			vnf_handle_nmm_stop_response(pRecvMsg, recvMsgLen, config, p5_idx);
+			break;
+
+		default:
+			{
+				if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					vnf_handle_vendor_extension(pRecvMsg, recvMsgLen, config, p5_idx, messageHeader.message_id);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id);
+				}
+			}
+			break;
+	}
+}
+int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf)
+{
+	if(1)
+	{
+		int socket_connected = 1;
+
+		// 1. Peek the message header
+		// 2. If the message is larger than the stack buffer then create a dynamic buffer
+		// 3. Read the buffer
+		// 4. Handle the p5 message
+		
+		uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+		uint8_t header_buffer[header_buffer_size];
+
+		uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure
+		uint8_t stack_buffer[stack_buffer_size];
+
+		uint8_t* dynamic_buffer = 0;
+
+		uint8_t* read_buffer = &stack_buffer[0];
+		uint32_t message_size = 0;
+
+		struct sockaddr_in addr;
+		socklen_t addr_len = sizeof(addr);
+
+		struct sctp_sndrcvinfo sndrcvinfo;
+		(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+
+		{
+			int flags = MSG_PEEK;
+			message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo,  &flags);
+
+			if(message_size == -1)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno);
+				return 0;
+			}
+
+			nfapi_p4_p5_message_header_t header;
+			int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0);
+			if(unpack_result < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result);
+				return 0;
+			}
+			message_size = header.message_length;
+
+			// now have the size of the mesage
+		}
+
+		if(message_size > stack_buffer_size)
+		{
+			dynamic_buffer = (uint8_t*)malloc(message_size);
+
+			if(dynamic_buffer == NULL)
+			{
+				// todo : add error mesage
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size);
+				return -1;
+			}
+
+			read_buffer = dynamic_buffer;
+		}
+
+		{
+			int flags = 0;
+			(void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+
+			int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags);
+			if(recvmsg_result == -1)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno);
+			}
+			else
+			{
+				if (flags & MSG_NOTIFICATION)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+
+					// todo - handle the events
+				}
+				else
+				{
+					/*
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n",
+							pnf->p5_sock,
+							inet_ntoa(addr.sin_addr),
+							ntohs(addr.sin_port),
+							sndrcvinfo.sinfo_assoc_id,
+							sndrcvinfo.sinfo_stream,
+							ntohl(sndrcvinfo.sinfo_ppid),
+							message_size,
+							flags);
+					*/
+
+					// handle now if complete message in one or more segments
+					if ((flags & 0x80) == 0x80)
+					{
+						vnf_handle_p4_p5_message(read_buffer, message_size, pnf->p5_idx, config);
+					}
+					else
+					{
+						NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags);
+
+						// assume socket disconnected
+						NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n");
+						socket_connected =  0;
+					}
+
+
+				}
+			}
+		}
+
+		if(dynamic_buffer)
+		{
+			free(dynamic_buffer);
+		}
+
+		return socket_connected;
+	}
+}
+
+static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s len:%d stream:%d\n", __FUNCTION__, len, stream);
+
+	int result = sctp_sendmsg(pnf->p5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4);
+
+	if(result != len)
+	{
+		if(result <  0)
+		{
+			// error
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp sendto failed errno: %d\n", errno);
+		}
+		else
+		{
+			// did not send all the message
+		}
+	}
+
+	return 0;
+}
+
+
+int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len)
+{
+	nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx);
+	
+	if(pnf)
+	{
+		// pack the message for transmission
+		int packedMessageLength = nfapi_p5_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
+
+		if (packedMessageLength < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed with return %d\n", packedMessageLength);
+			return -1;
+		}
+
+		return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx);
+		return -1;
+	}
+}
+
+
+int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len)
+{
+	nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx);
+	
+	if(pnf)
+	{
+		// pack the message for transmission
+		int packedMessageLength = nfapi_p4_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
+
+		if (packedMessageLength < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p4_message_pack failed with return %d\n", packedMessageLength);
+			return -1;
+		}
+
+		return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0/*msg->phy_id*/);
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx);
+		return -1;
+	}
+}
+
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c
new file mode 100644
index 0000000000..0aba0a29f5
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c
@@ -0,0 +1,676 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <stdio.h>
+
+#include "vnf.h"
+
+
+
+nfapi_vnf_config_t* nfapi_vnf_config_create()
+{
+	vnf_t* _this = (vnf_t*)calloc(1, sizeof(vnf_t));
+
+	if(_this == 0)
+		return 0;
+
+	_this->sctp = 1;
+
+	_this->next_phy_id = 1;
+	
+	// Set the default P5 port
+	_this->_public.vnf_p5_port = NFAPI_P5_SCTP_PORT;
+	
+	// set the default memory allocation 
+	_this->_public.malloc = &malloc;
+	_this->_public.free = &free;
+	
+	// set the default memory allocation 
+	_this->_public.codec_config.allocate = &malloc;
+	_this->_public.codec_config.deallocate = &free;
+	
+
+	return &(_this->_public);
+}
+
+void nfapi_vnf_config_destory(nfapi_vnf_config_t* config)
+{
+	free(config);
+}
+
+int nfapi_vnf_start(nfapi_vnf_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+	// Make sure to set the defined trace function before using NFAPI_TRACE
+	if(config->trace)
+		nfapi_trace_g = (nfapi_trace_fn_t)config->trace;
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
+
+	int p5ListenSock, p5Sock; 
+
+	struct sockaddr_in addr;
+	socklen_t addrSize;
+
+	struct sockaddr_in6 addr6;
+
+	struct sctp_event_subscribe events;
+	struct sctp_initmsg initMsg;
+	int noDelay;
+
+	(void)memset(&addr, 0, sizeof(struct sockaddr_in));
+	(void)memset(&addr6, 0, sizeof(struct sockaddr_in6));
+	(void)memset(&events, 0, sizeof(struct sctp_event_subscribe));
+	(void)memset(&initMsg, 0, sizeof(struct sctp_initmsg));
+
+	vnf_t* vnf = (vnf_t*)(config);
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port);
+
+	/*
+	char * host = 0;
+	char * port = "4242";
+	struct addrinfo hints;
+	bzero(&hints, sizeof(struct addrinfo));
+	//hints.ai_flags=AI_PASSIVE;
+	//hints.ai_flags=AI_DEFAULT;
+	hints.ai_family=AF_UNSPEC;
+	//hints.ai_family=AF_INET6;
+	hints.ai_socktype=SOCK_STREAM;
+	//hints.ai_protocol=IPPROTO_SCTP
+
+	struct addrinfo *aiHead = 0;
+
+
+
+	int result = getaddrinfo(host, port, &hints, &aiHead);
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno);
+
+	while(aiHead->ai_next != NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", 
+				aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, 
+				aiHead->ai_flags, AI_PASSIVE);
+
+		char hostBfr[ NI_MAXHOST ];
+		char servBfr[ NI_MAXSERV ];
+
+		getnameinfo(aiHead->ai_addr,
+				aiHead->ai_addrlen,
+				hostBfr,
+				sizeof( hostBfr ),
+				servBfr,
+				sizeof( servBfr ),
+				NI_NUMERICHOST | NI_NUMERICSERV );
+
+		switch(aiHead->ai_family)
+		{
+			case PF_INET:
+				{
+				struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr;
+				printf(
+						"   ai_addr      = sin_family: %d (AF_INET = %d, "
+						"AF_INET6 = %d)\n"
+						"                  sin_addr:   %s\n"
+						"                  sin_port:   %s\n",
+						pSadrIn->sin_family,
+						AF_INET,
+						AF_INET6,
+						hostBfr,
+						servBfr );
+				}
+				break;
+			case PF_INET6:
+				{
+				struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr;
+				fprintf( stderr,
+						"   ai_addr      = sin6_family:   %d (AF_INET = %d, "
+						"AF_INET6 = %d) \n"
+						"                  sin6_addr:     %s\n"
+						"                  sin6_port:     %s\n"
+						"                  sin6_flowinfo: %d\n"
+						"                  sin6_scope_id: %d\n",
+						pSadrIn6->sin6_family,
+						AF_INET,
+						AF_INET6,
+						hostBfr,
+						servBfr,
+						pSadrIn6->sin6_flowinfo,
+						pSadrIn6->sin6_scope_id);
+				}
+				break;
+			default:
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n");
+				break;
+		}
+
+		aiHead = aiHead->ai_next;
+	}
+	*/
+
+	{
+		int protocol;
+		int domain;
+
+		if (vnf->sctp)
+			protocol = IPPROTO_SCTP;
+		else
+			protocol = IPPROTO_IP;
+
+		if(config->vnf_ipv6)
+		{
+			domain = PF_INET6;
+		}
+		else
+		{
+			domain = AF_INET;
+		}
+
+		// open the SCTP socket
+		if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno);
+			return 0;
+		}
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock);
+	}
+
+	if (vnf->sctp)
+	{
+		// configure for MSG_NOTIFICATION
+		if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno);
+			close(p5ListenSock);
+			return 0;
+		}
+		NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n");
+		// configure the SCTP socket options
+		initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS;  // number of output streams can be greater
+		initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS;  // number of output streams can be greater
+		if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno)
+			close(p5ListenSock);
+			return 0;
+		}
+		noDelay = 1;
+		if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno);
+			close(p5ListenSock);
+			return 0;
+		}
+		struct sctp_event_subscribe events;
+		memset( (void *)&events, 0, sizeof(events) );
+  	    events.sctp_data_io_event = 1;
+		
+		if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno);
+			close(p5ListenSock);
+			return -1;
+		}
+
+	}
+
+
+	if(config->vnf_ipv6)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock);
+		addr6.sin6_family = AF_INET6;
+		addr6.sin6_port = htons(config->vnf_p5_port);
+		addr6.sin6_addr = in6addr_any;
+
+		// bind to the configured address and port
+		if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
+			close(p5ListenSock);
+			return 0;
+		}
+	}
+	else if(config->vnf_ipv4)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port);
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(config->vnf_p5_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+
+		// bind to the configured address and port
+		if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
+		//if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
+			close(p5ListenSock);
+			return 0;
+		}
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock);
+
+	// put the socket into listen mode
+	if (listen(p5ListenSock, 2) < 0) 
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno);
+		close(p5ListenSock);
+		return 0;
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n");
+
+	struct timeval tv;
+	fd_set read_fd_set;
+
+
+	int p5_idx = 0;
+	while(vnf->terminate == 0)
+	{
+		FD_ZERO(&read_fd_set);
+
+		FD_SET(p5ListenSock, &read_fd_set);
+		int max_fd = p5ListenSock;
+
+		tv.tv_sec = 5;
+		tv.tv_usec = 0;
+
+		nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
+		while(pnf != 0)
+		{
+			if(pnf->connected)
+			{
+				FD_SET(pnf->p5_sock, &read_fd_set);
+				if (pnf->p5_sock > max_fd)
+				{
+					max_fd = pnf->p5_sock;
+				}
+			}
+
+			pnf = pnf->next;
+		}
+
+		int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv);
+
+		if(select_result == -1)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno);
+			close(p5ListenSock);
+			return 0;
+		}
+		else if(select_result)
+		{
+			if(FD_ISSET(p5ListenSock, &read_fd_set))
+			{
+				addrSize = sizeof(struct sockaddr_in);
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n");
+
+				p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize);
+
+				if (p5Sock < 0) 
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock,  inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+					nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t));
+					NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf);
+					memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t));
+					pnf->p5_sock = p5Sock;
+					pnf->p5_idx = p5_idx++;
+					pnf->p5_pnf_sockaddr = addr;
+					pnf->connected = 1;
+
+					nfapi_vnf_pnf_list_add(config, pnf);
+
+					// Inform mac that a pnf connection has been established
+					// todo : allow mac to 'accept' the connection. i.e. to
+					// reject it.
+					if(config->pnf_connection_indication != 0)
+					{
+						(config->pnf_connection_indication)(config, pnf->p5_idx);
+					}
+
+					
+					// check the connection status
+					{
+						struct sctp_status status;
+						(void)memset(&status, 0, sizeof(struct sctp_status));
+						socklen_t optLen = (socklen_t) sizeof(struct sctp_status);
+						if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0)
+						{
+							NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno);
+							return -1;
+						}
+						else
+						{
+							NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id);
+							NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd);
+							NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n",  status.sstat_instrms);
+							NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms);
+
+						}
+					}
+				}
+			}
+			else
+			{
+				uint8_t delete_pnfs = 0;
+
+				nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
+				while(pnf != 0)
+				{
+					if(FD_ISSET(pnf->p5_sock, &read_fd_set))
+					{
+						if(vnf_read_dispatch_message(config, pnf) == 0)
+						{
+							if(config->pnf_disconnect_indication != 0)
+							{
+								(config->pnf_disconnect_indication)(config, pnf->p5_idx);
+							}
+
+							close(pnf->p5_sock);
+
+							pnf->to_delete = 1;
+							delete_pnfs = 1;
+						}
+					}
+			
+					pnf = pnf->next;
+				}
+
+				if(delete_pnfs)
+				{
+					nfapi_vnf_pnf_info_t* pnf = config->pnf_list;
+					nfapi_vnf_pnf_info_t* prev = 0;
+					while(pnf != 0)
+					{
+						nfapi_vnf_pnf_info_t* curr = pnf;
+
+						if(pnf->to_delete == 1)
+						{
+							if(prev == 0)
+							{
+								config->pnf_list = pnf->next;
+							}
+							else
+							{
+								prev->next = pnf->next;
+							}
+
+							pnf = pnf->next;
+
+							free(curr);
+						}
+						else
+						{
+							prev = pnf;
+							pnf = pnf->next;
+						}
+
+					}
+					
+				}
+			}
+
+			continue;
+		}
+		else
+		{
+			// timeout
+			
+			// Should we test for socket closure here every second?
+
+			continue;
+		}
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n");
+	{
+		nfapi_vnf_pnf_info_t* curr = config->pnf_list;
+		while(curr != NULL)
+		{
+			if(config->pnf_disconnect_indication)
+			{
+				(config->pnf_disconnect_indication)(config, curr->p5_idx);
+			}
+
+			close(curr->p5_sock);
+			curr = curr->next;
+		}
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n");
+	close(p5ListenSock);
+		
+	return 0;
+
+}
+
+int nfapi_vnf_stop(nfapi_vnf_config_t* config)
+{
+	// Verify that config is not null
+	if(config == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+	_this->terminate = 1;
+	return 0;
+}
+
+int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t));
+}
+
+int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_config_request_t));
+}
+
+int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t));
+}
+
+int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t));
+}
+
+int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t));
+}
+int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id);
+
+	if(phy == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy inforation phy_id:%d\n", __FUNCTION__, req->header.phy_id);
+		return -1;
+	}
+
+	// set the timing parameters
+	req->nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG;
+	req->nfapi_config.timing_window.value = phy->timing_window;
+	req->num_tlv++;
+
+	req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NFAPI_TIMING_INFO_MODE_TAG;
+	req->nfapi_config.timing_info_mode.value = phy->timing_info_mode;
+	req->num_tlv++;
+
+	req->nfapi_config.timing_info_period.tl.tag = NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG;
+	req->nfapi_config.timing_info_period.value = phy->timing_info_period;
+	req->num_tlv++;
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t));
+}
+int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t));
+}
+int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t));
+}
+int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_measurement_request_t));
+}
+int nfapi_vnf_rssi_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_rssi_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_rssi_request_t));
+}
+int nfapi_vnf_cell_search_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_cell_search_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_cell_search_request_t));
+}
+int nfapi_vnf_broadcast_detect_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_broadcast_detect_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_broadcast_detect_request_t));
+}
+int nfapi_vnf_system_information_schedule_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_schedule_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_schedule_request_t));
+}
+int nfapi_vnf_system_information_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_system_information_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_system_information_request_t));
+}
+int nfapi_vnf_nmm_stop_request(nfapi_vnf_config_t* config, int p5_idx, nfapi_nmm_stop_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p4_message(_this, p5_idx, &req->header, sizeof(nfapi_nmm_stop_request_t));
+}
+int nfapi_vnf_vendor_extension(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg)
+{
+	if(config == 0 || msg == 0)
+		return -1;
+
+	vnf_t* _this = (vnf_t*)(config);
+
+	return vnf_pack_and_send_p5_message(_this, p5_idx, msg, sizeof(nfapi_p4_p5_message_header_t));
+}
+
+int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy_id)
+{
+	vnf_t* vnf = (vnf_t*)config;
+
+	nfapi_vnf_phy_info_t* info = (nfapi_vnf_phy_info_t*)calloc(1, sizeof(nfapi_vnf_phy_info_t));
+	info->p5_idx = p5_idx;
+	info->phy_id = vnf->next_phy_id++;
+
+	info->timing_window = 30;       // This seems to override what gets set by the user - why???
+	info->timing_info_mode = 0x03;
+	info->timing_info_period = 128;
+
+	nfapi_vnf_phy_info_list_add(config, info);
+
+	(*phy_id) = info->phy_id;
+
+	return 0;
+}
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
new file mode 100644
index 0000000000..1304176752
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
@@ -0,0 +1,1599 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <time.h>
+
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vnf_p7.h"
+
+#define SYNC_CYCLE_COUNT 2
+
+void* vnf_p7_malloc(vnf_p7_t* vnf_p7, size_t size)
+{
+	if(vnf_p7->_public.malloc)
+	{
+		return (vnf_p7->_public.malloc)(size);
+	}
+	else
+	{
+		return calloc(1, size); 
+	}
+}
+void vnf_p7_free(vnf_p7_t* vnf_p7, void* ptr)
+{
+	if(ptr == 0)
+		return;
+
+	if(vnf_p7->_public.free)
+	{
+		(vnf_p7->_public.free)(ptr);
+	}
+	else
+	{
+		free(ptr); 
+	}
+}
+
+void vnf_p7_codec_free(vnf_p7_t* vnf_p7, void* ptr)
+{
+	if(ptr == 0)
+		return;
+
+	if(vnf_p7->_public.codec_config.deallocate)
+	{
+		(vnf_p7->_public.codec_config.deallocate)(ptr);
+	}
+	else
+	{
+		free(ptr); 
+	}
+}
+
+void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
+	// todo : add mutex
+	node->next = vnf_p7->p7_connections; 
+	vnf_p7->p7_connections = node;
+}
+
+nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id)
+{
+	nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+	while(curr != 0)
+	{
+		if(curr->phy_id == phy_id)
+		{
+			return curr;
+		}
+		curr = curr->next;
+	}
+
+	return 0;
+}
+
+nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id)
+{
+	nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+	nfapi_vnf_p7_connection_info_t* prev = 0;
+
+	while(curr != 0)
+	{
+		if(curr->phy_id == phy_id)
+		{
+			if(prev == 0)
+			{
+				vnf_p7->p7_connections = curr->next;
+			}
+			else
+			{
+				prev->next = curr->next;
+			}
+
+			return curr;
+		}
+		else
+		{
+			prev = curr;
+			curr = curr->next;
+		}
+	}
+
+	return 0;
+}
+
+vnf_p7_rx_message_t* vnf_p7_rx_reassembly_queue_add_segment(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len)
+{
+	vnf_p7_rx_message_t* msg = 0;
+	// attempt to find a entry for this segment
+	vnf_p7_rx_message_t* iterator = queue->msg_queue;
+	while(iterator != 0)
+	{
+		if(iterator->sequence_number == sequence_number)
+		{
+			msg = iterator;
+			break;
+		}
+
+		iterator = iterator->next;
+	}
+	
+	// if found then copy data to message
+	if(msg != 0)
+	{
+	
+		msg->segments[segment_number].buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, data_len);
+		memcpy(msg->segments[segment_number].buffer, data, data_len);
+		msg->segments[segment_number].length = data_len;
+
+		msg->num_segments_received++;
+
+		// set the segement number if we have the last segment
+		if(m == 0)
+			msg->num_segments_expected = segment_number + 1;
+	}
+	// else add new rx message entry
+	else
+	{
+		// create a new message
+		msg = (vnf_p7_rx_message_t*)(vnf_p7_malloc(vnf_p7, sizeof(vnf_p7_rx_message_t)));
+		memset(msg, 0, sizeof(vnf_p7_rx_message_t));
+
+		msg->sequence_number = sequence_number;
+		msg->num_segments_expected = m ? 255 : segment_number + 1;
+		msg->num_segments_received = 1;
+		msg->rx_hr_time = vnf_get_current_time_hr();
+
+		msg->segments[segment_number].buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, data_len);
+		memcpy(msg->segments[segment_number].buffer, data, data_len);
+		msg->segments[segment_number].length = data_len;
+
+		// place the message at the head of the queue
+		msg->next = queue->msg_queue;
+		queue->msg_queue = msg;
+	}
+
+	return msg;
+}
+
+void vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, vnf_p7_rx_message_t* msg)
+{
+	// remove message if it has the same sequence number
+	vnf_p7_rx_message_t* iterator = queue->msg_queue;
+	vnf_p7_rx_message_t* previous = 0;
+
+	while(iterator != 0)
+	{
+		if(iterator->sequence_number == msg->sequence_number)
+		{
+			if(previous == 0)
+			{
+				queue->msg_queue = iterator->next;
+			}
+			else
+			{
+				previous->next = iterator->next;
+			}
+
+			//NFAPI_TRACE(NFAPI_TRACE_INFO, "Deleting reassembly message\n");
+			// delete the message
+			uint16_t i;
+			for(i = 0; i < 128; ++i)
+			{
+				if(iterator->segments[i].buffer)
+					vnf_p7_free(vnf_p7, iterator->segments[i].buffer);
+			}
+			vnf_p7_free(vnf_p7, iterator);
+
+			break;
+		}
+
+		previous = iterator;
+		iterator = iterator->next;
+	}
+}
+
+void vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7_t* vnf_p7, vnf_p7_rx_reassembly_queue_t* queue, uint32_t delta)
+{
+	// remove all messages that are too old
+	vnf_p7_rx_message_t* iterator = queue->msg_queue;
+	vnf_p7_rx_message_t* previous = 0;
+
+	uint32_t rx_hr_time = vnf_get_current_time_hr();
+
+	while(iterator != 0)
+	{
+		if(rx_hr_time - iterator->rx_hr_time > delta)
+		{
+			if(previous == 0)
+			{
+				queue->msg_queue = iterator->next;
+			}
+			else
+			{
+				previous->next = iterator->next;
+			}
+			
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Deleting stale reassembly message (%u %u %d)\n", iterator->rx_hr_time, rx_hr_time, delta);
+
+			vnf_p7_rx_message_t* to_delete = iterator;
+			iterator = iterator->next;
+
+			// delete the message
+			uint16_t i;
+			for(i = 0; i < 128; ++i)
+			{
+				if(to_delete->segments[i].buffer)
+					vnf_p7_free(vnf_p7, to_delete->segments[i].buffer);
+			}
+			vnf_p7_free(vnf_p7, to_delete);
+
+		}
+		else
+		{
+			previous = iterator;
+			iterator = iterator->next;
+		}
+	}
+}
+
+uint32_t vnf_get_current_time_hr()
+{
+	struct timeval now;
+	(void)gettimeofday(&now, NULL);
+	uint32_t time_hr = TIME2TIMEHR(now);
+	return time_hr;
+}
+
+uint16_t increment_sfn_sf(uint16_t sfn_sf)
+{
+	if((sfn_sf & 0xF) == 9)
+	{
+		sfn_sf += 0x0010;
+		sfn_sf &= 0x3FF0;
+	}
+	else if((sfn_sf & 0xF) > 9)
+	{
+		// error should not happen
+	}
+	else
+	{
+		sfn_sf++;
+	}
+
+	return sfn_sf;
+}
+
+struct timespec timespec_delta(struct timespec start, struct timespec end)
+{
+	struct timespec temp;
+	if ((end.tv_nsec-start.tv_nsec)<0) 
+	{
+		temp.tv_sec = end.tv_sec-start.tv_sec-1;
+		temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
+	} 
+	else 
+	{
+		temp.tv_sec = end.tv_sec-start.tv_sec;
+		temp.tv_nsec = end.tv_nsec-start.tv_nsec;
+	}
+	return temp;
+}
+
+static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr)
+{
+	if(now_hr < sf_start_hr)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier that start of subframe\n");
+		return 0;
+	}
+	else
+	{
+		uint32_t now_us = TIMEHR_USEC(now_hr);
+		uint32_t sf_start_us = TIMEHR_USEC(sf_start_hr);
+
+		// if the us have wrapped adjust for it
+		if(now_hr < sf_start_us)
+		{
+			now_us += 1000000;
+		}
+
+		return now_us - sf_start_us;
+	}
+}
+
+uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr)
+{
+	uint32_t now_time_hr = vnf_get_current_time_hr();
+
+	uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
+
+	uint32_t t1 = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
+
+	return t1;
+}
+
+
+uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr)
+{
+	uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
+
+	uint32_t t4 = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
+
+	return t4;
+
+}
+
+
+uint32_t calculate_transmit_timestamp(uint16_t sfn_sf, uint32_t sf_start_time_hr)
+{
+	uint32_t now_time_hr = vnf_get_current_time_hr();
+
+	uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr);
+
+	uint32_t tt = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us;
+
+	return tt;
+}
+
+
+uint16_t increment_sfn_sf_by(uint16_t sfn_sf, uint8_t increment)
+{
+	while(increment > 0)
+	{
+		sfn_sf = increment_sfn_sf(sfn_sf);
+		--increment;
+	}
+
+	return sfn_sf;
+}
+
+
+int send_mac_subframe_indications(vnf_p7_t* vnf_p7)
+{
+	nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+	while(curr != 0)
+	{
+		if(curr->in_sync == 1)
+		{
+			// ask for subframes in the future
+			uint16_t sfn_sf_adv = increment_sfn_sf_by(curr->sfn_sf, 2);
+
+			vnf_p7->_public.subframe_indication(&(vnf_p7->_public), curr->phy_id, sfn_sf_adv);
+		}
+
+		curr = curr->next;
+	}
+
+	return 0;
+}
+
+int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, uint8_t* msg, const uint32_t len)
+{
+	int sendto_result = sendto(vnf_p7->socket, msg, len, 0, (struct sockaddr*)&(p7_info->remote_addr), sizeof(p7_info->remote_addr)); 
+
+	if(sendto_result != len)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno);
+	}
+
+	return 0;
+}
+
+int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header)
+{
+
+	nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id);
+	if(p7_connection)
+	{
+		int send_result = 0;
+		uint8_t  buffer[1024 * 32];
+
+		header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number);
+		
+		int len = nfapi_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config);
+		
+                //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size);
+
+		if(len < 0) 
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id);
+			return -1;
+		}
+
+		if(len > vnf_p7->_public.segment_size)
+		{
+			// todo : consider replacing with the sendmmsg call
+			// todo : worry about blocking writes?
+		
+			// segmenting the transmit
+			int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; 
+			int seg_body_len = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; 
+			int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); 
+				
+			int segment = 0;
+			int offset = NFAPI_P7_HEADER_LENGTH;
+			uint8_t tx_buffer[vnf_p7->_public.segment_size];
+                        NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size);
+			for(segment = 0; segment < segment_count; ++segment)
+			{
+				uint8_t last = 0;
+				uint16_t size = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH;
+				if(segment + 1 == segment_count)
+				{
+					last = 1;
+					size = (msg_body_len) - (seg_body_len * segment);
+				}
+
+				uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH;
+
+				// Update the header with the m and segement 
+				memcpy(&tx_buffer[0], buffer, NFAPI_P7_HEADER_LENGTH);
+
+				// set the segment length
+				tx_buffer[4] = (segment_size & 0xFF00) >> 8;
+				tx_buffer[5] = (segment_size & 0xFF);
+
+				// set the m & segment number
+				tx_buffer[6] = ((!last) << 7) + segment;
+
+				memcpy(&tx_buffer[NFAPI_P7_HEADER_LENGTH], &buffer[0] + offset, size);
+				offset += size;
+
+				if(vnf_p7->_public.checksum_enabled)
+				{
+					nfapi_p7_update_checksum(tx_buffer, segment_size);
+				}
+			
+				nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr));	
+
+				send_result = vnf_send_p7_msg(vnf_p7, p7_connection,  &tx_buffer[0], segment_size);
+			}
+		}
+		else
+		{
+			if(vnf_p7->_public.checksum_enabled)
+			{
+				nfapi_p7_update_checksum(buffer, len);
+			}
+
+			nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr));	
+
+			// simple case that the message fits in a single segement
+			send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len);
+		}
+
+		p7_connection->sequence_number++;
+
+		return send_result;
+	}
+	else
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id);
+		return -1;
+	}
+}
+
+int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
+{
+	nfapi_dl_node_sync_t dl_node_sync;
+	memset(&dl_node_sync, 0, sizeof(dl_node_sync));
+
+	dl_node_sync.header.phy_id = p7_info->phy_id;
+	dl_node_sync.header.message_id = NFAPI_DL_NODE_SYNC;
+	dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr);
+	dl_node_sync.delta_sfn_sf = 0;
+
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header);	
+}
+
+int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info)
+{
+
+	if(p7_info->in_sync == 1)
+	{
+		uint16_t dl_sync_period_mask = p7_info->dl_in_sync_period-1;
+		uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf);
+
+		if ((((sfn_sf_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
+		{
+			vnf_build_send_dl_node_sync(vnf_p7, p7_info);
+		}
+	}
+	else
+	{
+		uint16_t dl_sync_period_mask = p7_info->dl_out_sync_period-1;
+		uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf);
+
+		if ((((sfn_sf_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0)
+		{
+			vnf_build_send_dl_node_sync(vnf_p7, p7_info);
+		}
+	}
+	return 0;
+}
+
+
+void vnf_handle_harq_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_harq_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.harq_indication)
+			{
+				(vnf_p7->_public.harq_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.harq_indication_body.harq_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+}
+
+void vnf_handle_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_crc_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.crc_indication)
+			{
+				(vnf_p7->_public.crc_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.crc_indication_body.crc_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+}
+
+void vnf_handle_rx_ulsch_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_rx_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.rx_indication)
+			{
+				(vnf_p7->_public.rx_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+
+		uint16_t i = 0;
+		for(i = 0; i < ind.rx_indication_body.number_of_pdus; ++i)
+		{
+			vnf_p7_codec_free(vnf_p7, ind.rx_indication_body.rx_pdu_list[i].data);
+		}
+		vnf_p7_codec_free(vnf_p7, ind.rx_indication_body.rx_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+
+}
+
+void vnf_handle_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_rach_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.rach_indication)
+			{
+				(vnf_p7->_public.rach_indication)(&vnf_p7->_public, &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.rach_indication_body.preamble_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+
+	}
+}
+
+void vnf_handle_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_srs_indication_t ind;
+
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.srs_indication)
+			{
+				(vnf_p7->_public.srs_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.srs_indication_body.srs_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);	
+	}
+}
+
+void vnf_handle_rx_sr_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_sr_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.sr_indication)
+			{
+				(vnf_p7->_public.sr_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.sr_indication_body.sr_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);	
+	}
+}
+void vnf_handle_rx_cqi_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_cqi_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.cqi_indication)
+			{
+				(vnf_p7->_public.cqi_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.cqi_indication_body.cqi_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.cqi_indication_body.cqi_raw_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);	
+		
+	}
+
+}
+
+void vnf_handle_lbt_dl_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_lbt_dl_indication_t ind;
+
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.lbt_dl_indication)
+			{
+				(vnf_p7->_public.lbt_dl_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.lbt_dl_indication_body.lbt_indication_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+}
+
+void vnf_handle_nb_harq_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_nb_harq_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.nb_harq_indication)
+			{
+				(vnf_p7->_public.nb_harq_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.nb_harq_indication_body.nb_harq_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+}
+
+void vnf_handle_nrach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	// ensure it's valid
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else
+	{
+		nfapi_nrach_indication_t ind;
+	
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+		else
+		{
+			if(vnf_p7->_public.nrach_indication)
+			{
+				(vnf_p7->_public.nrach_indication)(&(vnf_p7->_public), &ind);
+			}
+		}
+	
+		vnf_p7_codec_free(vnf_p7, ind.nrach_indication_body.nrach_pdu_list);
+		vnf_p7_codec_free(vnf_p7, ind.vendor_extension);
+	}
+}
+
+void vnf_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7, uint16_t message_id)
+{
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+	}
+	else if(vnf_p7->_public.allocate_p7_vendor_ext)
+	{
+		uint16_t msg_size;
+		nfapi_p7_message_header_t* msg = vnf_p7->_public.allocate_p7_vendor_ext(message_id, &msg_size);
+
+		if(msg == 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate vendor extention structure\n", __FUNCTION__);
+			return;
+		}
+
+		int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, msg, msg_size, &vnf_p7->_public.codec_config);
+
+		if(unpack_result == 0)
+		{
+			if(vnf_p7->_public.vendor_ext)
+				vnf_p7->_public.vendor_ext(&(vnf_p7->_public), msg);
+		}
+		
+		if(vnf_p7->_public.deallocate_p7_vendor_ext)
+			vnf_p7->_public.deallocate_p7_vendor_ext(msg);
+		
+	}
+}
+
+
+void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	uint32_t now_time_hr = vnf_get_current_time_hr();
+
+	if (pRecvMsg == NULL || vnf_p7  == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_ul_node_sync: NULL parameters\n");
+		return;
+	}
+
+	nfapi_ul_node_sync_t ind;
+	if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n");
+		return;
+	}
+
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "Received UL_NODE_SYNC phy_id:%d t1:%d t2:%d t3:%d\n", ind.header.phy_id, ind.t1, ind.t2, ind.t3);
+
+	nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, ind.header.phy_id);
+	uint32_t t4 = calculate_t4(now_time_hr, phy->sfn_sf, vnf_p7->sf_start_time_hr);
+
+	uint32_t tx_2_rx = t4>ind.t1 ? t4 - ind.t1 : t4 + NFAPI_MAX_SFNSFDEC - ind.t1 ;
+	uint32_t pnf_proc_time = ind.t3 - ind.t2;
+
+	// divide by 2 using shift operator
+	uint32_t latency =  (tx_2_rx - pnf_proc_time) >> 1;
+
+	if(!(phy->filtered_adjust))
+	{
+		phy->latency[phy->min_sync_cycle_count] = latency;
+
+		NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n",
+				NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, 
+				tx_2_rx, pnf_proc_time, latency);
+	}
+	else
+	{
+		phy->latency[phy->min_sync_cycle_count] = latency;
+
+		//if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT)
+		{
+			if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1)
+			{
+				// Only t2 wrap has occurred!!!
+				phy->sf_offset = (NFAPI_MAX_SFNSFDEC + ind.t2) - ind.t1 - latency;
+			}
+			else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1)
+			{
+				// Only t1 wrap has occurred
+				phy->sf_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSFDEC) - latency;
+			}
+			else
+			{
+				// Either no wrap or both have wrapped
+				phy->sf_offset = ind.t2 - ind.t1 - latency;
+			}
+
+			if (phy->sf_offset_filtered == 0)
+			{
+				phy->sf_offset_filtered = phy->sf_offset;
+			}
+			else
+			{
+				int32_t oldFilteredValueShifted = phy->sf_offset_filtered << 5;
+				int32_t newOffsetShifted = phy->sf_offset << 5;
+
+				// 1/8 of new and 7/8 of old
+				phy->sf_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5;
+			}
+		}
+
+		if(1)
+		{
+                  struct timespec ts;
+                  clock_gettime(CLOCK_MONOTONIC, &ts);
+
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", 
+					NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ts.tv_sec, ts.tv_nsec, ind.header.phy_id,
+					ind.t1, ind.t2, ind.t3, t4, 
+					tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->sf_offset, phy->sf_offset_filtered,
+					(ind.t1<phy->previous_t1), (ind.t2<phy->previous_t2));
+		}
+
+	}
+
+        if (phy->filtered_adjust && (phy->sf_offset_filtered > 1e6 || phy->sf_offset_filtered < -1e6))
+        {
+          phy->filtered_adjust = 0;
+          phy->zero_count=0;
+          phy->min_sync_cycle_count = 2;
+          phy->in_sync = 0;
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->sf_offset_filtered:%d\n", __FUNCTION__, phy->sf_offset_filtered);
+        }
+
+	if(phy->min_sync_cycle_count)
+		phy->min_sync_cycle_count--;
+
+	if(phy->min_sync_cycle_count == 0)
+	{
+		uint32_t curr_sfn_sf = phy->sfn_sf;
+		int32_t sfn_sf_dec = NFAPI_SFNSF2DEC(phy->sfn_sf);
+
+		if(!phy->filtered_adjust)
+		{
+			int i = 0;
+			//phy->average_latency = 0;
+			for(i = 0; i < SYNC_CYCLE_COUNT; ++i)
+			{
+				phy->average_latency += phy->latency[i];
+
+			}
+			phy->average_latency /= SYNC_CYCLE_COUNT;
+
+			phy->sf_offset = ind.t2 - (ind.t1 - phy->average_latency);
+
+			sfn_sf_dec += (phy->sf_offset / 1000);
+		}
+		else
+		{
+			sfn_sf_dec += ((phy->sf_offset_filtered + 500) / 1000);	//Round up go from microsecond to subframe(1ms)
+		}
+
+		if(sfn_sf_dec < 0)
+		{
+			sfn_sf_dec += NFAPI_MAX_SFNSFDEC;
+		}
+		else if( sfn_sf_dec >= NFAPI_MAX_SFNSFDEC)
+		{
+			sfn_sf_dec -= NFAPI_MAX_SFNSFDEC;
+		}
+
+		uint16_t new_sfn_sf = NFAPI_SFNSFDEC2SFNSF(sfn_sf_dec);
+
+
+		{
+			phy->adjustment = NFAPI_SFNSF2DEC(new_sfn_sf) - NFAPI_SFNSF2DEC(curr_sfn_sf);
+
+			NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend);
+
+			phy->previous_t1 = 0;
+			phy->previous_t2 = 0;
+
+			if(phy->previous_sf_offset_filtered > 0)
+			{
+				if( phy->sf_offset_filtered > phy->previous_sf_offset_filtered)
+				{
+					// pnf is getting futher ahead of vnf
+					//phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered;
+					phy->sf_offset_trend = (phy->sf_offset_filtered + phy->previous_sf_offset_filtered)/2;
+				}
+				else
+				{
+					// pnf is getting back in sync
+				}
+			}
+			else if(phy->previous_sf_offset_filtered < 0)
+			{
+				if(phy->sf_offset_filtered < phy->previous_sf_offset_filtered)
+				{
+					// vnf is getting future ahead of pnf
+					//phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered);
+					phy->sf_offset_trend = (-(phy->sf_offset_filtered + phy->previous_sf_offset_filtered)) /2;
+				}
+				else
+				{
+					//  vnf is getting back in sync
+				}
+			}
+
+			
+			int insync_minor_adjustment_1 = phy->sf_offset_trend / 6;
+			int insync_minor_adjustment_2 = phy->sf_offset_trend / 2;
+
+
+			if(insync_minor_adjustment_1 == 0)
+				insync_minor_adjustment_1 = 2;
+
+			if(insync_minor_adjustment_2 == 0)
+				insync_minor_adjustment_2 = 10;
+
+			if(!phy->filtered_adjust)
+			{
+				if(phy->adjustment < 10)
+				{
+					phy->zero_count++;
+
+					if(phy->zero_count >= 10)
+					{
+						phy->filtered_adjust = 1;
+						phy->zero_count = 0;
+
+						NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n");
+					}
+				}
+				else
+				{
+					phy->zero_count = 0;
+				}
+			}
+			else
+			{
+				// Fine level of adjustment
+				if (phy->adjustment == 0)
+				{
+					if (phy->zero_count >= 10)
+					{
+						if(phy->in_sync == 0)
+						{
+							NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); 
+
+							if(vnf_p7->_public.sync_indication)
+								(vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1);
+						}
+
+						phy->in_sync = 1;
+					}
+					else
+					{
+						phy->zero_count++;
+					}
+
+					if(phy->in_sync)
+					{
+						// in sync
+						if(phy->sf_offset_filtered > 250)
+						{
+							// VNF is slow
+							phy->insync_minor_adjustment = insync_minor_adjustment_1; //25;
+							phy->insync_minor_adjustment_duration = ((phy->sf_offset_filtered) / insync_minor_adjustment_1);
+						}
+						else if(phy->sf_offset_filtered < -250)
+						{
+							// VNF is fast
+							phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25;
+							phy->insync_minor_adjustment_duration = (((phy->sf_offset_filtered) / -(insync_minor_adjustment_1)));
+						}
+						else
+						{
+							phy->insync_minor_adjustment = 0;
+						}
+
+						if(phy->insync_minor_adjustment != 0)
+						{
+							NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (sf_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", 
+										NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
+										phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, 
+                                                                                phy->sf_offset_filtered, 
+                                                                                insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend,
+                                                                                NFAPI_SFNSF2DEC(new_sfn_sf),
+                                                                                NFAPI_SFNSF2DEC(curr_sfn_sf),
+                                                                                phy->adjustment); 
+						}
+					}
+				}
+				else
+				{
+					if (phy->in_sync)
+					{
+						if(phy->adjustment == 0)
+						{
+						}
+						else if(phy->adjustment > 0)
+						{
+							// VNF is slow
+							//if(phy->adjustment == 1)
+							{
+								//
+								if(phy->sf_offset_filtered > 250)
+								{
+									// VNF is slow
+									phy->insync_minor_adjustment = insync_minor_adjustment_2;
+									phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered - 250) / insync_minor_adjustment_2);
+								}
+								else if(phy->sf_offset_filtered < -250)
+								{
+									// VNF is fast
+									phy->insync_minor_adjustment = -(insync_minor_adjustment_2);
+									phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered + 250) / -(insync_minor_adjustment_2));
+								}
+							
+							}
+							//else
+							{
+								// out of sync?
+							}
+							
+							NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (adjustment:%d sf_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", 
+										NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
+										phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->sf_offset_filtered,
+										insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend,
+                                                                                NFAPI_SFNSF2DEC(new_sfn_sf),
+                                                                                NFAPI_SFNSF2DEC(curr_sfn_sf),
+                                                                                phy->adjustment); 
+							
+						}
+						else if(phy->adjustment < 0)
+						{
+							// VNF is fast
+							//if(phy->adjustment == -1)
+							{
+								//
+								if(phy->sf_offset_filtered > 250)
+								{
+									// VNF is slow
+									phy->insync_minor_adjustment = insync_minor_adjustment_2;
+									phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered - 250) / insync_minor_adjustment_2);
+								}
+								else if(phy->sf_offset_filtered < -250)
+								{
+									// VNF is fast
+									phy->insync_minor_adjustment = -(insync_minor_adjustment_2);
+									phy->insync_minor_adjustment_duration = 2 * ((phy->sf_offset_filtered + 250) / -(insync_minor_adjustment_2));
+								}
+							}
+							//else
+							{
+								// out of sync?
+							}
+
+							NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d subframes (adjustment:%d sf_offset_filtered:%d) %d %d %d\n", 
+										NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ind.header.phy_id,
+										phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->sf_offset_filtered,
+										insync_minor_adjustment_1, insync_minor_adjustment_2, phy->sf_offset_trend); 
+						}
+
+						/*
+						if (phy->adjustment > 10 || phy->adjustment < -10)
+						{
+							phy->zero_count++;		// Add one to the getting out of sync counter
+						}
+						else
+						{
+							phy->zero_count = 0;		// Small error - zero the out of sync counter
+						}
+
+						if (phy->zero_count >= 10)	// If we have had 10 consecutive large errors - drop out of sync
+						{
+							NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n");
+							//pP7SockInfo->syncAchieved = 0;
+						}
+						*/
+					}
+				}
+			}
+
+
+			if(phy->in_sync == 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", 
+					ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"),
+					NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, 
+					phy->filtered_adjust ? "FILTERED" : "ABSOLUTE",
+					phy->zero_count,
+					phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");
+
+				phy->sfn_sf = new_sfn_sf;
+			}
+		}
+
+		// reset for next cycle
+		phy->previous_sf_offset_filtered = phy->sf_offset_filtered;
+		phy->min_sync_cycle_count = 2;
+		phy->sf_offset_filtered = 0;
+		phy->sf_offset = 0;
+	}
+	else
+	{
+		phy->previous_t1 = ind.t1;
+		phy->previous_t2 = ind.t2;
+	}
+}
+
+void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	if (pRecvMsg == NULL || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n");
+		return;
+	}
+
+	nfapi_timing_info_t ind;
+	if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n");
+		return;
+	}
+
+        if (vnf_p7 && vnf_p7->p7_connections)
+        {
+          int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf);
+
+          //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta);
+          if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1)
+          {
+            NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnsf_delta, NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), NFAPI_SFNSF2DEC(ind.last_sfn_sf));
+          }
+        }
+}
+
+void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
+{
+	nfapi_p7_message_header_t header;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	// ensure the message is sensible
+	if (recvMsgLen < 8 || pRecvMsg == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
+		return;
+	}
+
+	switch (header.message_id)
+	{
+		case NFAPI_UL_NODE_SYNC:
+			vnf_handle_ul_node_sync(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+
+		case NFAPI_TIMING_INFO:
+			vnf_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_HARQ_INDICATION:
+			vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+	
+		case NFAPI_CRC_INDICATION:
+			vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+	
+		case NFAPI_RX_ULSCH_INDICATION:
+			vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+	
+		case NFAPI_RACH_INDICATION:
+			vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+	
+		case NFAPI_SRS_INDICATION:
+			vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+
+		case NFAPI_RX_SR_INDICATION:
+			vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_LBT_DL_INDICATION:
+			vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_NB_HARQ_INDICATION:
+			vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_NRACH_INDICATION:
+			vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;			
+
+		default:
+			{
+				if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
+				   header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX)
+				{
+					vnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, vnf_p7, header.message_id);
+				}
+				else
+				{
+					NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unknown message ID %d\n", header.message_id);
+				}
+			}
+			break;
+	}
+}
+
+void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) 
+{
+	nfapi_p7_message_header_t messageHeader;
+
+	// validate the input params
+	if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, vnf_p7);
+		return;
+	}
+
+	// unpack the message header
+	if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &vnf_p7->_public.codec_config) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+		return;
+	}
+
+	if(vnf_p7->_public.checksum_enabled)
+	{
+		uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen);
+		if(checksum != messageHeader.checksum)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen);
+			return;
+		}
+	}
+
+	uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence);
+	uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence);
+	uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence);
+
+
+	if(m == 0 && segment_num == 0)
+	{
+		// we have a complete message
+		// ensure the message is sensible
+		if (recvMsgLen < 8 || pRecvMsg == NULL)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen);
+			return;
+		}
+
+		//vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7);
+		vnf_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7);
+	}
+	else
+	{
+		nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id);
+
+		if(phy)
+		{
+			vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen);
+
+			if(rx_msg->num_segments_received == rx_msg->num_segments_expected)
+			{
+				// send the buffer on
+				uint16_t i = 0;
+				uint16_t length = 0;
+				for(i = 0; i < rx_msg->num_segments_expected; ++i)
+				{
+					length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0);
+				}
+
+				if(phy->reassembly_buffer_size < length)
+				{
+					vnf_p7_free(vnf_p7, phy->reassembly_buffer);
+					phy->reassembly_buffer = 0;
+				}
+
+				if(phy->reassembly_buffer == 0)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length);
+					phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length);
+
+					if(phy->reassembly_buffer == 0)
+					{
+						NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length);
+						return;
+					}
+
+					phy->reassembly_buffer_size = length;
+				}
+
+				uint16_t offset = 0;
+				for(i = 0; i < rx_msg->num_segments_expected; ++i)
+				{
+					if(i == 0)
+					{
+						memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length);
+						offset += rx_msg->segments[i].length;
+					}
+					else
+					{
+						memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH);
+						offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH;
+					}
+				}
+
+
+				//pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time);
+				vnf_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7);
+
+
+				// delete the structure
+				vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg);
+			}
+
+			vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 1000);
+		}
+		else
+		{
+
+			NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id);
+		}
+	}
+}
+
+int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7)
+{
+	int recvfrom_result = 0;
+	struct sockaddr_in remote_addr;
+	socklen_t remote_addr_size = sizeof(remote_addr);
+
+	do
+	{
+		// peek the header
+		uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH];
+		recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size);
+
+		if(recvfrom_result > 0)
+		{
+			// get the segment size
+			nfapi_p7_message_header_t header;
+			if(nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n");
+				return -1;
+			}
+
+			// resize the buffer if we have a large segment
+			if(header.message_length > vnf_p7->rx_message_buffer_size)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); 
+				vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length);
+				vnf_p7->rx_message_buffer_size = header.message_length;
+			}
+
+			// read the segment
+			recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size);
+
+			// todo : how to handle incomplete readfroms, need some sort of buffer/select
+
+			if(recvfrom_result == 0)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom returned 0\n");
+			}
+			else if(recvfrom_result != header.message_length)
+			{
+				NFAPI_TRACE(NFAPI_TRACE_NOTE, "did not receive the entire message %d %d\n", recvfrom_result, header.message_length); 
+				
+				recvfrom_result += recvfrom(vnf_p7->socket, &vnf_p7->rx_message_buffer[recvfrom_result], header.message_length - recvfrom_result, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size);
+	
+			}
+			
+			
+			if(recvfrom_result > 0)
+			{
+				vnf_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7);
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno);
+			}
+		}
+
+		if(recvfrom_result == -1)
+		{
+			if(errno == EAGAIN || errno == EWOULDBLOCK)
+			{
+				// return to the select
+				//NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno);
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno);
+			}
+		}
+	}
+	while(recvfrom_result > 0);
+
+	return 0;
+}
+
+void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header)
+{
+	switch(header->message_id)
+	{
+		case NFAPI_HARQ_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_harq_indication_t*)(header))->harq_indication_body.harq_pdu_list);
+			}
+			break;
+		case NFAPI_CRC_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_crc_indication_t*)(header))->crc_indication_body.crc_pdu_list);
+			}
+			break;
+		case NFAPI_RX_ULSCH_INDICATION:
+			{
+				nfapi_rx_indication_t* rx_ind = (nfapi_rx_indication_t*)(header);
+				uint16_t i = 0;
+				for(i = 0; i < rx_ind->rx_indication_body.number_of_pdus; ++i)
+				{
+					vnf_p7_codec_free(vnf_p7, rx_ind->rx_indication_body.rx_pdu_list[i].data);
+				}
+
+				vnf_p7_codec_free(vnf_p7, rx_ind->rx_indication_body.rx_pdu_list);
+			}
+			break;
+		case NFAPI_RACH_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_rach_indication_t*)(header))->rach_indication_body.preamble_list);
+			}
+			break;
+		case NFAPI_SRS_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_srs_indication_t*)(header))->srs_indication_body.srs_pdu_list);
+			}
+			break;
+		case NFAPI_RX_SR_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_sr_indication_t*)(header))->sr_indication_body.sr_pdu_list);
+			}
+			break;
+		case NFAPI_RX_CQI_INDICATION:
+			{
+				vnf_p7_codec_free(vnf_p7, ((nfapi_cqi_indication_t*)(header))->cqi_indication_body.cqi_pdu_list);
+				vnf_p7_codec_free(vnf_p7, ((nfapi_cqi_indication_t*)(header))->cqi_indication_body.cqi_raw_pdu_list);
+			}
+			break;
+	}
+				
+	vnf_p7_free(vnf_p7, header);
+	
+}
+
+void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu)
+{
+	vnf_p7_free(vnf_p7, pdu);
+}
+
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
new file mode 100644
index 0000000000..a35d8e3c1d
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vnf_p7.h"
+
+#define FAPI2_IP_DSCP	0
+
+nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create()
+{
+	vnf_p7_t* _this = (vnf_p7_t*)calloc(1, sizeof(vnf_p7_t));
+
+	if(_this == 0)
+		return 0;
+
+	// todo : initialize
+	_this->_public.segment_size = 1400;
+	_this->_public.max_num_segments = 8;
+	_this->_public.checksum_enabled = 1;
+	
+	_this->_public.malloc = &malloc;
+	_this->_public.free = &free;	
+
+	_this->_public.codec_config.allocate = &malloc;
+	_this->_public.codec_config.deallocate = &free;
+	
+
+	return &(_this->_public);
+}
+
+void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config)
+{
+	free(config);
+}
+
+
+struct timespec timespec_add(struct timespec lhs, struct timespec rhs)
+{
+	struct timespec result;
+
+	result.tv_sec = lhs.tv_sec + rhs.tv_sec;
+	result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec;
+
+	if(result.tv_nsec > 1e9)
+	{
+		result.tv_sec++;
+		result.tv_nsec-= 1e9;
+	}
+
+	return result;
+}
+
+struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
+{
+	struct timespec result;
+	if ((lhs.tv_nsec-rhs.tv_nsec)<0) 
+	{
+		result.tv_sec = lhs.tv_sec-rhs.tv_sec-1;
+		result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec;
+	} 
+	else 
+	{
+		result.tv_sec = lhs.tv_sec-rhs.tv_sec;
+		result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec;
+	}
+	return result;
+}
+
+// monitor the p7 endpoints and the timing loop and 
+// send indications to mac
+int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config)
+{
+	if(config == 0)
+		return -1;
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__);
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+
+	// Create p7 receive udp port 
+	// todo : this needs updating for Ipv6
+	
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port);
+
+	// open the UDP socket
+	if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno);
+		return -1;
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n");
+
+	// configure the UDP socket options
+	int iptos_value = FAPI2_IP_DSCP << 2;
+	if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno);
+		return -1;
+	}
+	
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n");
+
+	// Create the address structure
+	struct sockaddr_in addr;
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(config->port);
+	addr.sin_addr.s_addr = INADDR_ANY;
+
+	// bind to the configured port
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+	if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
+	//if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno);
+		return -1;
+	}
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n");
+
+
+	//struct timespec original_pselect_timeout;
+	struct timespec pselect_timeout;
+	pselect_timeout.tv_sec = 0;
+	pselect_timeout.tv_nsec = 1000000; // ns in a 1 us
+
+
+	struct timespec pselect_start;
+	struct timespec pselect_stop;
+
+	//struct timespec sf_end;
+
+	long last_millisecond = -1;
+
+
+	struct timespec sf_duration;
+	sf_duration.tv_sec = 0;
+	sf_duration.tv_nsec = 1e6; // We want 1ms pause
+
+	struct timespec sf_start;
+	clock_gettime(CLOCK_MONOTONIC, &sf_start);
+	long millisecond = sf_start.tv_nsec / 1e6;
+	sf_start = timespec_add(sf_start, sf_duration);
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
+
+	while(vnf_p7->terminate == 0)
+	{
+		fd_set rfds;
+		int maxSock = 0;
+		FD_ZERO(&rfds);
+		int selectRetval = 0;
+
+		// Add the p7 socket
+		FD_SET(vnf_p7->socket, &rfds);
+		maxSock = vnf_p7->socket;
+		
+		clock_gettime(CLOCK_MONOTONIC, &pselect_start);
+		//long millisecond = pselect_start.tv_nsec / 1e6;
+
+		if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) )
+		{
+                  //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec);
+
+
+			if((pselect_start.tv_sec > sf_start.tv_sec) || 
+			   ((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec)))
+			{
+				// overran the end of the subframe we do not want to wait
+				pselect_timeout.tv_sec = 0;
+				pselect_timeout.tv_nsec = 0;
+
+				//struct timespec overrun = timespec_sub(pselect_start, sf_start);
+				//NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec);
+			}
+			else
+			{
+				// still time before the end of the subframe wait
+				pselect_timeout = timespec_sub(sf_start, pselect_start);
+
+#if 0
+                                NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sf_start:%d.%ld pselect_start:%d.%ld pseclect_timeout:%d.%ld\n",
+                                    __FUNCTION__,
+                                    sf_start.tv_sec, sf_start.tv_nsec,
+                                    pselect_start.tv_sec, pselect_start.tv_nsec,
+                                    pselect_timeout.tv_sec, pselect_timeout.tv_nsec);
+#endif
+			}
+
+//original_pselect_timeout = pselect_timeout;
+
+			// detemine how long to sleep in ns before the start of the next 1ms
+			//pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000);
+
+			//uint8_t underrun_possible =0;
+			
+			// if we are not sleeping until the next milisecond due to the
+			// insycn minor adjment flag it so we don't consider it an error
+			//uint8_t underrun_possible =0;
+			/*
+			{
+				nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
+				if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0)
+				{
+					NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment,
+							pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000)) 
+					if(phy->insync_minor_adjustment > 0)
+					{
+						// todo check we don't go below 0
+						if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec)
+							pselect_timeout.tv_nsec = 0;
+						else
+							pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
+
+
+						//underrun_possible = 1;
+					}
+					else if(phy->insync_minor_adjustment < 0)
+					{
+						// todo check we don't go below 0
+						pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000);
+					}
+
+					//phy->insync_minor_adjustment = 0;
+					phy->insync_minor_adjustment_duration--;
+				}
+			}
+			*/
+			
+
+//long wraps = pselect_timeout.tv_nsec % 1e9;
+
+
+			selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL);
+
+			clock_gettime(CLOCK_MONOTONIC, &pselect_stop);
+
+                        nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections;
+
+if (selectRetval==-1 && errno == 22)
+{
+  NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", 
+  pselect_timeout.tv_sec, pselect_timeout.tv_nsec, 
+  phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, 
+  sf_duration.tv_sec, sf_duration.tv_nsec);
+}
+#if 0
+                        if (selectRetval != 0 || phy->insync_minor_adjustment_duration != 0)
+                          NFAPI_TRACE(NFAPI_TRACE_NOTE, "pselect()=%d maxSock:%d vnf_p7->socket:%d pselect_timeout:%u.%u original_pselect_timeout:%u.%u\n", 
+                              selectRetval, maxSock, vnf_p7->socket, pselect_timeout.tv_sec, pselect_timeout.tv_nsec,
+                              original_pselect_timeout.tv_sec, original_pselect_timeout.tv_nsec);
+#endif
+
+			if(selectRetval == 0)
+			{
+				// calculate the start of the next subframe
+				sf_start = timespec_add(sf_start, sf_duration);
+				//NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec);
+
+				if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0)
+				{
+                                        long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000);
+
+                                        sf_start.tv_nsec -= insync_minor_adjustment_ns;
+
+#if 1
+                                        if (sf_start.tv_nsec > 1e9)
+                                        {
+                                          sf_start.tv_sec++;
+                                          sf_start.tv_nsec-=1e9;
+                                        }
+                                        else if (sf_start.tv_nsec < 0)
+                                        {
+                                          sf_start.tv_sec--;
+                                          sf_start.tv_nsec+=1e9;
+                                        }
+#else
+                                        //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec);
+					if(phy->insync_minor_adjustment > 0)
+					{
+						// decrease the subframe duration a little
+                                                if (sf_start.tv_nsec > insync_minor_adjustment_ns)
+                                                  sf_start.tv_nsec -= insync_minor_adjustment_ns;
+                                                else
+                                                {
+                                                  NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns);
+                                                  sf_start.tv_sec--;
+                                                  sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns;
+                                                }
+					}
+					else if(phy->insync_minor_adjustment < 0)
+					{
+						// todo check we don't go below 0
+						// increase the subframe duration a little
+						sf_start.tv_nsec += insync_minor_adjustment_ns;
+
+                                                if (sf_start.tv_nsec < 0)
+                                                {
+                                                  NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec);
+                                                  sf_start.tv_sec++;
+                                                  sf_start.tv_nsec += 1e9;
+                                                }
+					}
+#endif
+
+					//phy->insync_minor_adjustment = 0;
+                                        phy->insync_minor_adjustment_duration--;
+
+                                        NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n", 
+                                            phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration);
+
+                                        if (phy->insync_minor_adjustment_duration==0)
+                                        {
+                                          phy->insync_minor_adjustment = 0;
+                                        }
+				}
+				/*
+				long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6;
+				if(millisecond == pselect_stop_millisecond)
+				{
+					// we have woke up in the same subframe
+					if(underrun_possible == 0)
+						NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec);
+				}
+				else if(((millisecond + 1) % 1000) != pselect_stop_millisecond)
+				{
+					// we have overrun the subframe
+					NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond);
+					NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond);
+				}
+				last_millisecond = millisecond;
+				*/
+				
+				millisecond ++;
+			}
+		}
+		else
+		{
+			// we have overrun the subframe advance to go and collect $200
+			if((millisecond - last_millisecond) > 3)
+				NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1);
+
+			last_millisecond = ( last_millisecond + 1 ) % 1000;
+			selectRetval = 0;
+		}
+
+		if(selectRetval == 0)
+		{
+			vnf_p7->sf_start_time_hr = vnf_get_current_time_hr();
+
+			// pselect timed out
+			nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+
+			while(curr != 0)
+			{
+				curr->sfn_sf = increment_sfn_sf(curr->sfn_sf);
+				
+				vnf_sync(vnf_p7, curr);
+
+				curr = curr->next;
+			}
+
+			send_mac_subframe_indications(vnf_p7);
+
+		}
+		else if(selectRetval > 0)
+		{
+			// have a p7 message
+			if(FD_ISSET(vnf_p7->socket, &rfds))
+			{
+				vnf_p7_read_dispatch_message(vnf_p7);
+			}
+		}
+		else
+		{
+			// pselect error
+			if(selectRetval == -1 && errno == EINTR)
+			{
+				// a sigal was received.
+			}
+			else
+			{
+				NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond);
+				// should we exit now?
+                                if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration
+                                {
+                                  usleep(100000);
+                                }
+			}
+		}
+
+	}
+
+	
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n");
+	close(vnf_p7->socket);
+
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__);
+
+	return 0;
+}
+
+int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config)
+{
+	if(config == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	vnf_p7->terminate =1;
+	return 0;
+}
+
+int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, int pnf_p7_port, int phy_id)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p phy_id:%d pnf_addr:%s pnf_p7_port:%d)\n", __FUNCTION__, config, phy_id,  pnf_p7_addr, pnf_p7_port);
+
+	if(config == 0)
+        {
+          return -1;
+        }
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+
+	nfapi_vnf_p7_connection_info_t* node = (nfapi_vnf_p7_connection_info_t*)malloc(sizeof(nfapi_vnf_p7_connection_info_t));
+
+	memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t));
+	node->phy_id = phy_id;
+	node->in_sync = 0;
+	node->dl_out_sync_offset = 30;
+	node->dl_out_sync_period = 10;
+	node->dl_in_sync_offset = 30;
+	node->dl_in_sync_period = 512;
+	node->sfn_sf = 0;
+
+	node->min_sync_cycle_count = 8;
+
+	// save the remote endpoint information
+	node->remote_addr.sin_family = AF_INET;
+	node->remote_addr.sin_port = htons(pnf_p7_port);
+	node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr);
+
+	vnf_p7_connection_info_list_add(vnf_p7, node);
+
+	return 0;
+}
+
+int nfapi_vnf_p7_del_pnf(nfapi_vnf_p7_config_t* config, int phy_id)
+{
+	NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d)\n", __FUNCTION__, phy_id);
+
+	if(config == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+
+	nfapi_vnf_p7_connection_info_t* to_delete = vnf_p7_connection_info_list_delete(vnf_p7, phy_id);
+
+	if(to_delete)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(phy_id:%d) deleting connection info\n", __FUNCTION__, phy_id);
+		free(to_delete);
+	}
+
+	return 0;
+}
+int nfapi_vnf_p7_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_dl_config_request_t* req)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(config:%p req:%p)\n", __FUNCTION__, config, req);
+
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
+
+int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
+int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
+int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
+int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req)
+{
+	if(config == 0 || req == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
+int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header)
+{
+	if(config == 0 || header == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	return vnf_p7_pack_and_send_p7_msg(vnf_p7, header);
+}
+
+
+int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header)
+{
+	if(config == 0 || header == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	vnf_p7_release_msg(vnf_p7, header);
+
+	return 0;
+
+}
+
+int nfapi_vnf_p7_release_pdu(nfapi_vnf_p7_config_t* config, void* pdu)
+{
+	if(config == 0 || pdu == 0)
+		return -1;
+
+	vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+	vnf_p7_release_pdu(vnf_p7, pdu);
+
+	return 0;
+}
diff --git a/nfapi/open-nFAPI/vnf/tests/Makefile.am b/nfapi/open-nFAPI/vnf/tests/Makefile.am
new file mode 100644
index 0000000000..0c8163102c
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/tests/Makefile.am
@@ -0,0 +1,30 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+#vnf unit test
+#AUTOMAKE_OPTIONS=subdir-objects
+
+AM_CPPFLAGS = -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc  -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/vnf/public_inc $(CFLAGS_CUNIT) -Wall -Werror
+
+check_PROGRAMS= test_vnf
+
+test_vnf_SOURCES = vnf_cunit_main.c ../..//common/src/debug.c   
+test_vnf_LDADD=$(top_builddir)/vnf/libnfapi_vnf.a $(top_builddir)/nfapi/libnfapi.a  -L$(libdir) -lpthread -lrt -lsctp -lz -lcunit
+
+LOG_DRIVER = $(top_srcdir)/tap-driver.sh
+TESTS=test_vnf
+EXTRA_DIST = $(TESTS)
+
diff --git a/nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c b/nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c
new file mode 100644
index 0000000000..4df5da7c26
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf/tests/vnf_cunit_main.c
@@ -0,0 +1,1497 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "CUnit.h"
+#include "Basic.h"
+#include "Automated.h"
+//#include "CUnit/Console.h"
+
+#include "nfapi_interface.h"
+#include "nfapi_vnf_interface.h"
+#include "nfapi.h"
+#include <stdio.h>  // for printf
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <arpa/inet.h>
+#include "debug.h"
+#include <unistd.h>
+#include <stdlib.h>
+
+/* Test Suite setup and cleanup functions: */
+
+int init_suite(void) { return 0; }
+int clean_suite(void) { return 0; }
+
+#define MAX_PACKED_MESSAGE_SIZE	8192
+
+#define SFNSF2SFN(_sfnsf) ((_sfnsf) >> 4)
+#define SFNSF2SF(_sfnsf) ((_sfnsf) & 0xF)
+
+typedef struct
+{
+	uint8_t enabled;
+	uint8_t started;
+	uint16_t phy_id;
+
+	int p7_rx_port;
+	char* p7_rx_addr;
+
+	struct sockaddr_in p7_rx_sockaddr;
+	int p7_rx_sock;
+
+	struct sockaddr_in p7_tx_sockaddr;
+	int p7_tx_sock;
+} pnf_test_config_phy_t;
+
+typedef struct
+{
+	uint8_t enabled;
+	
+	char* vnf_p5_addr;
+	int vnf_p5_port;
+
+	struct sockaddr_in p5_tx_sockaddr;
+	int p5_sock;
+
+	int p7_rx_port_base;
+
+	pnf_test_config_phy_t phys[4];
+
+} pnf_test_config_t;
+
+pnf_test_config_t pnf_test_config[5];
+
+typedef struct
+{
+	uint8_t enabled;
+	uint8_t state;
+	uint16_t p5_idx;
+	uint16_t phy_id;
+
+	uint8_t vnf_idx;
+	//struct sockaddr_in p7_rx_sockaddr;
+	struct sockaddr_in p7_tx_sockaddr;
+
+} vnf_test_config_phy_t;
+
+typedef struct 
+{
+	uint8_t enabled;
+	pthread_t thread;
+
+	char* vnf_p7_addr;
+	int vnf_p7_port;
+
+	struct sockaddr_in p7_rx_sockaddr;
+
+	nfapi_vnf_p7_config_t* config;
+
+	uint8_t max_phys;
+	uint8_t phy_count;
+	//uint8_t phy_ids[4];
+	
+} vnf_test_config_vnf_t;
+
+typedef struct  
+{
+	char* p5_addr;
+	int p5_port;
+
+	pthread_t thread;
+
+	vnf_test_config_vnf_t vnfs[2];
+
+	uint8_t phy_count;
+	vnf_test_config_phy_t phys[5];
+
+	nfapi_vnf_config_t* p5_vnf_config;
+
+} vnf_test_config_t;
+
+vnf_test_config_t vnf_test_config[5];
+
+void reset_test_configs()
+{
+	memset(&pnf_test_config, 0, sizeof(pnf_test_config));
+	memset(&vnf_test_config, 0, sizeof(vnf_test_config));
+}
+
+void pnf_create_p5_sock(pnf_test_config_t* config)
+{
+	config->p5_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	
+	config->p5_tx_sockaddr.sin_family = AF_INET;
+	config->p5_tx_sockaddr.sin_port = htons(config->vnf_p5_port);
+	config->p5_tx_sockaddr.sin_addr.s_addr = inet_addr(config->vnf_p5_addr);
+}
+
+void pnf_p5_connect(pnf_test_config_t* config)
+{
+	int connect_result = connect(config->p5_sock, (struct sockaddr *)&config->p5_tx_sockaddr, sizeof(config->p5_tx_sockaddr) );
+
+	printf("connect_result %d %d\n", connect_result, errno);
+}
+
+pnf_test_config_phy_t* find_pnf_phy_config(pnf_test_config_t* config, uint16_t phy_id)
+{
+	int i = 0;
+	for(i = 0; i < 4; ++i)
+	{
+		if(config->phys[i].phy_id == phy_id)
+			return &(config->phys[i]);
+	}
+
+	return 0;
+}
+
+vnf_test_config_phy_t* find_vnf_phy_config(vnf_test_config_t* config, uint16_t phy_id)
+{
+	int i = 0;
+	for(i = 0; i < 4; ++i)
+	{
+		if(config->phys[i].phy_id == phy_id)
+			return &(config->phys[i]);
+	}
+
+	return 0;
+}
+
+
+
+
+/************* Test case functions ****************/
+
+
+void vnf_test_start_no_config(void) 
+{
+	int result = nfapi_vnf_start(0);
+	CU_ASSERT_EQUAL(result, -1);
+}
+
+void* vnf_test_start_thread(void* ptr)
+{
+	int result = nfapi_vnf_start((nfapi_vnf_config_t*)ptr);
+	return (void*)(intptr_t)result;
+}
+
+int pnf_connection_indication_called = 0;
+int pnf_connection_indication(nfapi_vnf_config_t* config, int p5_idx)
+{
+	printf("[VNF] pnf_connection_indication p5_idx:%d\n", p5_idx);
+	pnf_connection_indication_called++;
+
+	nfapi_pnf_param_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+	req.header.message_length = 0;
+
+	nfapi_vnf_pnf_param_req(config, p5_idx, &req);
+	
+	return 1;
+}
+
+int pnf_disconnect_indication(nfapi_vnf_config_t* config, int p5_idx)
+{
+	printf("[VNF] pnf_disconnect_indication p5_idx:%d\n", p5_idx);
+	pnf_connection_indication_called++;
+
+	vnf_test_config_t* test_config = (vnf_test_config_t*)(config->user_data);
+	printf("[VNF] pnf_disconnect_indication user_data %p\n", config->user_data);
+
+	int i = 0;
+	for(i = 0; i < test_config->phy_count; ++i)
+	{
+		vnf_test_config_phy_t* phy = &test_config->phys[i];
+		vnf_test_config_vnf_t* vnf = &test_config->vnfs[phy->p5_idx];
+
+		// need to send stop request/response
+
+		nfapi_vnf_p7_del_pnf((vnf->config), phy->phy_id);
+		vnf->phy_count--;
+	}
+
+
+	for(i = 0; i < 2; ++i)
+	{
+		vnf_test_config_vnf_t* vnf = &test_config->vnfs[i];
+	printf("[VNF] pnf_disconnect_indication phy_count:%d\n", vnf->phy_count);
+		if(vnf->enabled == 1)
+		{
+			nfapi_vnf_p7_stop(vnf->config);
+			//vnf->config->terminate = 1;
+
+			int* result;
+	printf("[VNF] waiting for vnf p7 thread to exit\n");
+			pthread_join((vnf->thread), (void**)&result);
+			CU_ASSERT_EQUAL(result, 0);
+
+			vnf->enabled = 0;
+		}
+	}
+	
+	return 1;
+}
+
+int send_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	char buffer[256];
+	int encoded_size = nfapi_p5_message_pack(msg, msg_size, buffer, sizeof(buffer), 0);
+	int result = sendto(p5Sock, buffer, encoded_size, 0, (struct sockaddr*)addr, addr_size);
+	(void)result;
+	return 0;
+}
+
+int recv_p5_message(int p5Sock, nfapi_p4_p5_message_header_t* msg, unsigned msg_size)
+{
+	struct sockaddr_in addr2;
+	socklen_t addr2len;
+	char buffer2[256];
+	int result2 = recvfrom(p5Sock, buffer2, sizeof(buffer2), 0, (struct sockaddr*)&addr2, &addr2len); 
+		
+	int unpack_result = nfapi_p5_message_unpack(buffer2, result2, msg, msg_size, 0); //, sizeof(resp));
+	(void)unpack_result;
+	return 0;
+}
+
+int send_pnf_param_response(pnf_test_config_t* config) //int p5Sock, struct sockaddr_in* addr, socklen_t addr_size)
+{
+	nfapi_pnf_param_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
+
+	resp.header.message_length = 0;
+	resp.error_code = NFAPI_MSG_OK;
+
+	//send_p5_message(p5Sock, &resp, sizeof(resp), addr, addr_size);
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int create_p7_rx_socket(const char* addr, int port)
+{
+	int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+	struct sockaddr_in sock_addr;
+	sock_addr.sin_family = AF_INET;
+	sock_addr.sin_port = htons(port);
+
+	if(addr == 0)
+		sock_addr.sin_addr.s_addr = INADDR_ANY;
+	else
+		sock_addr.sin_addr.s_addr = inet_addr(addr);
+
+	int bind_result = bind(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
+	if(bind_result != 0)
+	{
+		printf("Failed to bind p7 rx socket %d(%d) to %s:%d\n", bind_result, errno, addr, port);
+	}
+
+	
+	return fd;
+}
+
+int create_p7_tx_socket()
+{
+	int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	return fd;
+}
+
+int send_param_response(pnf_test_config_t* config, uint16_t phy_id)
+{
+	nfapi_param_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PARAM_RESPONSE;
+	resp.header.phy_id = phy_id;
+
+	pnf_test_config_phy_t* phy = find_pnf_phy_config(config, phy_id);
+
+	resp.error_code = NFAPI_MSG_OK;
+
+	resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
+	resp.nfapi_config.p7_pnf_port.value = phy->p7_rx_port;
+
+	struct sockaddr_in pnf_p7_sockaddr;
+	pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(phy->p7_rx_addr);
+
+	resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
+	memcpy(&resp.nfapi_config.p7_pnf_address_ipv4.address[0], &pnf_p7_sockaddr.sin_addr.s_addr, 4);
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int receive_pnf_param_request(pnf_test_config_t* config)
+{
+	nfapi_pnf_param_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_PARAM_REQUEST);
+	if(req.header.message_id == NFAPI_PNF_PARAM_REQUEST)
+	{
+		printf("[PNF] nfapi_pnf_param_request\n");
+	}
+	return 0;
+}
+
+int receive_param_request(pnf_test_config_t* config)
+{
+	nfapi_param_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PARAM_REQUEST);
+	if(req.header.message_id == NFAPI_PARAM_REQUEST)
+	{
+		printf("[PNF] nfapi_param_request phy_id:%d\n", req.header.phy_id);
+	}
+	else
+	{
+		printf("[PNF] ERROR, unexpected message %d phy_id:%d\n", req.header.message_id, req.header.phy_id);
+	}
+	return req.header.phy_id;
+}
+
+int send_pnf_config_response(pnf_test_config_t* config)
+{
+	nfapi_pnf_config_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
+	resp.header.message_length = 0;
+	resp.error_code = NFAPI_MSG_OK;
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int send_config_response(pnf_test_config_t* config, uint16_t phy_id)
+{
+	nfapi_config_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_CONFIG_RESPONSE;
+	resp.header.message_length = 0;
+	resp.header.phy_id = phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+
+int receive_pnf_config_request(pnf_test_config_t* config)
+{
+	nfapi_pnf_config_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_CONFIG_REQUEST);
+	if(req.header.message_id == NFAPI_PNF_CONFIG_REQUEST)
+	{
+		printf("decoded nfapi_pnf_config_request\n");
+
+		int i = 0;
+		for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i)
+		{
+			nfapi_phy_rf_config_info_t* info = &(req.pnf_phy_rf_config.phy_rf_config[i]);
+			printf("adding pnf phy %d id %d\n",  i, info->phy_id);
+
+			config->phys[i].enabled = 1;
+			config->phys[i].phy_id = info->phy_id;
+		}
+	}
+	return 0;
+}
+
+int receive_config_request(pnf_test_config_t* config)
+{
+	nfapi_config_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_CONFIG_REQUEST);
+	if(req.header.message_id == NFAPI_CONFIG_REQUEST)
+	{
+		printf("[PNF] nfapi_config_request phy_id:%d\n", req.header.phy_id);
+
+		pnf_test_config_phy_t* phy = find_pnf_phy_config(config, req.header.phy_id);
+
+		// todo verify that this is the same as a vnf config?
+		phy->p7_tx_sockaddr.sin_family = AF_INET;
+		phy->p7_tx_sockaddr.sin_port = htons(req.nfapi_config.p7_vnf_port.value);
+		memcpy(&phy->p7_tx_sockaddr.sin_addr.s_addr, &req.nfapi_config.p7_vnf_address_ipv4.address, 4);
+		phy->p7_tx_sock = create_p7_tx_socket();
+
+
+		printf("[PNF] vnf p7 address %s:%d\n", inet_ntoa(phy->p7_tx_sockaddr.sin_addr), ntohs(phy->p7_tx_sockaddr.sin_port));
+
+		return req.header.phy_id;
+	}
+
+	return NFAPI_PHY_ID_NA;
+}
+
+int send_pnf_start_response(pnf_test_config_t* config)
+{
+	nfapi_pnf_start_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_START_RESPONSE;
+	resp.header.message_length = 0;
+	resp.error_code = NFAPI_MSG_OK;
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int send_start_response(pnf_test_config_t* config, uint16_t phy_id)
+{
+	nfapi_start_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_START_RESPONSE;
+	resp.header.message_length = 0;
+	resp.header.phy_id  = phy_id;
+	resp.error_code = NFAPI_MSG_OK;
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int receive_pnf_start_request(pnf_test_config_t* config)
+{
+	nfapi_pnf_start_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_START_REQUEST);
+	if(req.header.message_id == NFAPI_PNF_START_REQUEST)
+	{
+		printf("decoded nfapi_pnf_start_request\n");
+
+		int phy_idx = 0;
+		for(phy_idx = 0; phy_idx < 4; ++phy_idx)
+		{
+			if(config->phys[phy_idx].enabled)
+			{
+				pnf_test_config_phy_t* phy = &(config->phys[phy_idx]);
+				phy->p7_rx_port = config->p7_rx_port_base + phy_idx;
+				phy->p7_rx_addr = "127.0.0.1"; 
+			}
+		}
+	}
+	return 0;
+}
+
+int receive_start_request(pnf_test_config_t* config)
+{
+	nfapi_start_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_START_REQUEST);
+	if(req.header.message_id == NFAPI_START_REQUEST)
+	{
+		printf("[PNF] nfapi_start_request\n");
+
+		pnf_test_config_phy_t* phy = find_pnf_phy_config(config, req.header.phy_id);
+		printf("[PNF] creating p7 rx socket %s:%d\n", phy->p7_rx_addr, phy->p7_rx_port);
+		phy->p7_rx_sock = create_p7_rx_socket(phy->p7_rx_addr, phy->p7_rx_port);
+		phy->started = 1;
+
+	}
+
+	return req.header.phy_id;
+}
+
+int send_pnf_stop_response(pnf_test_config_t* config, uint16_t phy_id)
+{
+	printf("pnf_stop_response\n");
+	nfapi_pnf_stop_response_t resp;
+	memset(&resp, 0, sizeof(resp));
+	resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
+	resp.header.message_length = 0;
+	resp.error_code = NFAPI_MSG_OK;
+
+	send_p5_message(config->p5_sock, &resp.header, sizeof(resp), &(config->p5_tx_sockaddr), sizeof(config->p5_tx_sockaddr));
+	return 0;
+}
+
+int receive_pnf_stop_request(pnf_test_config_t* config)
+{
+	printf("pnf_stop_request\n");
+	nfapi_pnf_stop_request_t req;
+	recv_p5_message(config->p5_sock, &req.header, sizeof(req));
+
+	CU_ASSERT_EQUAL(req.header.message_id, NFAPI_PNF_STOP_REQUEST);
+	if(req.header.message_id == NFAPI_PNF_STOP_REQUEST)
+	{
+		printf("decoded nfapi_pnf_stop_request\n");
+	}
+	return 0;
+}
+int pnf_param_response(nfapi_vnf_config_t* config, int p5_idx,nfapi_pnf_param_response_t* response)
+{
+	printf("[VNF] pnf_param_response p5_idx:%d\n", p5_idx);
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	uint16_t phy_id;
+	nfapi_vnf_allocate_phy(config, p5_idx, &phy_id);
+
+	nfapi_pnf_config_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
+	req.header.message_length = 0;
+	req.header.phy_id = NFAPI_PHY_ID_NA;
+
+	req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
+	req.pnf_phy_rf_config.number_phy_rf_config_info = 2;
+	nfapi_vnf_allocate_phy(config, p5_idx, &req.pnf_phy_rf_config.phy_rf_config[0].phy_id);
+	nfapi_vnf_allocate_phy(config, p5_idx, &req.pnf_phy_rf_config.phy_rf_config[1].phy_id);
+	
+	uint16_t i = vnf_test_config[0].phy_count;
+
+	vnf_test_config[0].phys[i].enabled = 1;
+	vnf_test_config[0].phys[i].p5_idx = p5_idx;
+	vnf_test_config[0].phys[i].phy_id = req.pnf_phy_rf_config.phy_rf_config[0].phy_id;
+
+	i++;
+
+	vnf_test_config[0].phys[i].enabled = 1;
+	vnf_test_config[0].phys[i].p5_idx = p5_idx;
+	vnf_test_config[0].phys[i].phy_id = req.pnf_phy_rf_config.phy_rf_config[1].phy_id;
+
+	i++;
+	
+	vnf_test_config[0].phy_count = i;
+
+	nfapi_vnf_pnf_config_req(config, p5_idx, &req);
+
+	return 0;
+}
+
+int pnf_config_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* response)
+{
+	printf("pnf_config_response\n");
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	nfapi_pnf_start_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PNF_START_REQUEST;
+	req.header.message_length = 0;
+	req.header.phy_id = response->header.phy_id;
+
+	nfapi_vnf_pnf_start_req(config, p5_idx, &req);
+
+	return 0;
+}
+
+
+void* vnf_test_start_p7_thread(void* ptr)
+{
+	int result = nfapi_vnf_p7_start((nfapi_vnf_p7_config_t*)ptr);
+	(void)result;
+	return 0;
+}
+
+int test_subframe_indication(nfapi_vnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf)
+{
+	//printf("[VNF:%d] (%d:%d) SUBFRAME_IND\n", phy_id, SFNSF2SFN(sfn_sf), SFNSF2SF(sfn_sf));
+
+	nfapi_dl_config_request_t dl_config_req;
+	memset(&dl_config_req, 0, sizeof(dl_config_req));
+	dl_config_req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+	dl_config_req.header.phy_id = phy_id;
+	dl_config_req.sfn_sf = sfn_sf;
+	nfapi_vnf_p7_dl_config_req(config, &dl_config_req);
+	
+	nfapi_ul_config_request_t ul_config_req;
+	memset(&ul_config_req, 0, sizeof(ul_config_req));
+	ul_config_req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+	ul_config_req.header.phy_id = phy_id;
+	ul_config_req.sfn_sf = sfn_sf;
+	nfapi_vnf_p7_ul_config_req(config, &ul_config_req);
+
+	nfapi_hi_dci0_request_t hi_dci0_req;
+	memset(&hi_dci0_req, 0, sizeof(hi_dci0_req));
+	hi_dci0_req.header.message_id = NFAPI_HI_DCI0_REQUEST;
+	hi_dci0_req.header.phy_id = phy_id;
+	hi_dci0_req.sfn_sf = sfn_sf;
+	nfapi_vnf_p7_hi_dci0_req(config, &hi_dci0_req);
+
+
+	nfapi_tx_request_t tx_req;
+	memset(&tx_req, 0, sizeof(tx_req));
+	tx_req.header.message_id = NFAPI_TX_REQUEST;
+	tx_req.header.phy_id = phy_id;
+	tx_req.sfn_sf = sfn_sf;
+	nfapi_vnf_p7_tx_req(config, &tx_req);
+	return 0;
+}
+
+int test_harq_indication(nfapi_vnf_p7_config_t* config, nfapi_harq_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) HARQ_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+
+int test_nb_harq_indication(nfapi_vnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) HARQ_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+
+
+int test_crc_indication(nfapi_vnf_p7_config_t* config, nfapi_crc_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) CRC_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_rx_indication(nfapi_vnf_p7_config_t* config, nfapi_rx_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) RX_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_rach_indication(nfapi_vnf_p7_config_t* config, nfapi_rach_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) RACH_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_nrach_indication(nfapi_vnf_p7_config_t* config, nfapi_nrach_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) RACH_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_srs_indication(nfapi_vnf_p7_config_t* config, nfapi_srs_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) SRS_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_sr_indication(nfapi_vnf_p7_config_t* config, nfapi_sr_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) SR_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+int test_cqi_indication(nfapi_vnf_p7_config_t* config, nfapi_cqi_indication_t* ind)
+{
+	//printf("[VNF:%d] (%d:%d) CQI_IND\n", ind->header.phy_id, SFNSF2SFN(ind->sfn_sf), SFNSF2SF(ind->sfn_sf));
+	return 0;
+}
+
+int pnf_start_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* response)
+{
+	printf("[VNF] pnf_start_response p5_idx:%d\n", p5_idx);
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	return 0;
+}
+
+int pnf_stop_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_response_t* response)
+{
+	printf("pnf_stop_response\n");
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	nfapi_vnf_p7_stop(vnf_test_config[0].vnfs[0].config);
+	return 0;
+}
+
+int param_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* response)
+{
+	printf("[VNF] param_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	struct sockaddr_in addr;
+	memcpy(&addr.sin_addr.s_addr, &response->nfapi_config.p7_pnf_address_ipv4.address, 4);
+	printf("[VNF] param_response pnf p7 %s:%d\n", inet_ntoa(addr.sin_addr), response->nfapi_config.p7_pnf_port.value);
+
+	// find the vnf phy configuration
+	vnf_test_config_phy_t* phy = find_vnf_phy_config(&(vnf_test_config[0]), response->header.phy_id);
+	
+	// save the pnf p7 connection information
+	phy->p7_tx_sockaddr.sin_port = response->nfapi_config.p7_pnf_port.value;
+	memcpy(&phy->p7_tx_sockaddr.sin_addr.s_addr, &response->nfapi_config.p7_pnf_address_ipv4.address, 4);
+
+	nfapi_config_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_CONFIG_REQUEST;
+	req.header.phy_id = response->header.phy_id;
+
+	vnf_test_config_vnf_t* vnf = &(vnf_test_config[0].vnfs[phy->vnf_idx]);
+	req.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+	memcpy(&req.nfapi_config.p7_vnf_address_ipv4.address, &vnf->p7_rx_sockaddr.sin_addr.s_addr, 4);
+
+	req.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NFAPI_P7_VNF_PORT_TAG;
+	req.nfapi_config.p7_vnf_port.value = vnf->p7_rx_sockaddr.sin_port;
+
+	nfapi_vnf_config_req(config, p5_idx, &req);
+	return 0;
+}
+
+int config_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* response)
+{
+	printf("[VNF] config_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
+	return 0;
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+}
+
+int send_vnf_start_req(vnf_test_config_t* config, vnf_test_config_phy_t* phy)
+{
+	nfapi_start_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_START_REQUEST;
+	req.header.phy_id = phy->phy_id;
+
+	nfapi_vnf_start_req(config->p5_vnf_config, phy->p5_idx, &req);
+	return 0;
+}
+
+int start_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* response)
+{
+	printf("[VNF] start_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+
+	sleep(1);
+	
+	vnf_test_config_phy_t* phy = find_vnf_phy_config(&(vnf_test_config[0]), response->header.phy_id);
+
+	char* addr = inet_ntoa(phy->p7_tx_sockaddr.sin_addr);
+	int port = phy->p7_tx_sockaddr.sin_port;
+
+	vnf_test_config_vnf_t* vnf = &(vnf_test_config[0].vnfs[phy->vnf_idx]);
+
+	nfapi_vnf_p7_add_pnf(vnf->config, addr, port, response->header.phy_id);
+	return 0;
+}
+
+int stop_response(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_response_t* response)
+{
+	printf("stop_response p5_idx:%d phy_id:%d\n", p5_idx, response->header.phy_id);
+	CU_ASSERT_EQUAL(response->error_code, NFAPI_MSG_OK);
+	return 0;
+}
+
+void  start_vnf_p5(vnf_test_config_t* test_config)
+{
+	test_config->p5_vnf_config = nfapi_vnf_config_create();
+
+	test_config->p5_vnf_config->vnf_p5_port = test_config->p5_port;
+	test_config->p5_vnf_config->vnf_ipv4 = 1;
+	test_config->p5_vnf_config->pnf_connection_indication = &pnf_connection_indication;
+	test_config->p5_vnf_config->pnf_disconnect_indication = &pnf_disconnect_indication;
+	test_config->p5_vnf_config->pnf_param_resp = &pnf_param_response;
+	test_config->p5_vnf_config->pnf_config_resp = &pnf_config_response;
+	test_config->p5_vnf_config->pnf_start_resp = &pnf_start_response;
+	test_config->p5_vnf_config->pnf_stop_resp = &pnf_stop_response;
+	test_config->p5_vnf_config->param_resp = &param_response;
+	test_config->p5_vnf_config->config_resp = &config_response;
+	test_config->p5_vnf_config->start_resp = &start_response;
+	test_config->p5_vnf_config->stop_resp = &stop_response;
+
+	test_config->p5_vnf_config->user_data = test_config;
+
+	pthread_create(&test_config->thread, NULL, &vnf_test_start_thread, test_config->p5_vnf_config);
+
+	sleep(1);
+
+}
+
+void start_vnf_p7(vnf_test_config_vnf_t* vnf)
+{
+	
+	// todo : select which vnf to use for these phy's
+	vnf->enabled = 1;
+
+	vnf->p7_rx_sockaddr.sin_addr.s_addr = inet_addr(vnf->vnf_p7_addr);
+	vnf->p7_rx_sockaddr.sin_port = vnf->vnf_p7_port;
+
+
+	vnf->config = nfapi_vnf_p7_config_create();
+	vnf->config->checksum_enabled = 0;
+	vnf->config->port = vnf->vnf_p7_port;
+	vnf->config->subframe_indication = &test_subframe_indication;
+	vnf->config->harq_indication = &test_harq_indication;
+	vnf->config->crc_indication = &test_crc_indication;
+	vnf->config->rx_indication = &test_rx_indication;
+	vnf->config->rach_indication = &test_rach_indication;
+	vnf->config->srs_indication = &test_srs_indication;
+	vnf->config->sr_indication = &test_sr_indication;
+	vnf->config->cqi_indication = &test_cqi_indication;
+	
+	vnf->config->nb_harq_indication = &test_nb_harq_indication;
+	vnf->config->nrach_indication = &test_nrach_indication;
+	
+
+	vnf->config->segment_size = 1400;
+	vnf->config->max_num_segments = 6;
+
+	pthread_create(&(vnf->thread), NULL, &vnf_test_start_p7_thread, vnf->config);
+
+	vnf->enabled = 1;
+
+	//vnf->phy_count++;
+
+	sleep(1);
+}
+
+void send_p7_segmented_msg(int sock, char* msg, int len, int segment_size, struct sockaddr* addr,  socklen_t addr_len)
+{
+	static uint8_t sequence_num = 0;
+	if(len < segment_size)
+	{
+		msg[7] = sequence_num;
+		sendto(sock, msg, len, 0, addr, addr_len);
+	}
+	else
+	{
+		int msg_body_len = len - 12 ; 
+		int seg_body_len = segment_size - 12 ; 
+		int segments = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); 
+
+		//printf("sending segmented message len:%d seg_size:%d count:%d\n", len, segment_size, segments);
+
+		int segment = 0;
+		int offset = 12;
+		for(segment = 0; segment < segments; ++segment)
+		{
+			uint8_t last = 0;
+			uint16_t size = segment_size - 12;
+			if(segment + 1 == segments)
+			{
+				last = 1;
+				size = (msg_body_len) - (seg_body_len * segment);
+			}
+
+			char buffer[segment_size];
+
+			memcpy(&buffer[0], msg, 12);
+			buffer[6] = ((!last) << 7) + segment;
+			buffer[7] = sequence_num;
+
+			// msg length
+			uint8_t* p = (uint8_t*)&buffer[4];
+			push16(size + 12, &p, (uint8_t*)&buffer[size + 12]);
+
+			memcpy(&buffer[12], msg + offset, size);
+			offset += size;
+		
+			sendto(sock, &buffer[0], size + 12, 0, addr, addr_len);
+
+		}
+
+
+	}
+
+	sequence_num++;
+}
+
+void start_phy(vnf_test_config_phy_t* phy)
+{
+
+	nfapi_param_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PARAM_REQUEST;
+	req.header.phy_id = phy->phy_id;
+
+	nfapi_vnf_config_t* p5_vnf_config = (vnf_test_config[0].p5_vnf_config);
+	
+
+	nfapi_vnf_param_req(p5_vnf_config, phy->p5_idx, &req);
+
+}
+
+
+void vnf_test_start_connect(void)
+{
+	reset_test_configs();
+
+	int segment_size = 256;
+
+	vnf_test_config[0].p5_addr = "127.0.0.1";
+	vnf_test_config[0].p5_port = 4242;
+
+	vnf_test_config[0].vnfs[0].enabled = 0;
+	vnf_test_config[0].vnfs[0].vnf_p7_addr = "127.0.0.1";
+	vnf_test_config[0].vnfs[0].vnf_p7_port = 7878;
+	vnf_test_config[0].vnfs[0].max_phys = 1;
+
+	vnf_test_config[0].vnfs[1].enabled = 0;
+	vnf_test_config[0].vnfs[1].vnf_p7_addr = "127.0.0.1";
+	vnf_test_config[0].vnfs[1].vnf_p7_port = 7879;
+	vnf_test_config[0].vnfs[1].max_phys = 1;
+
+
+	// this is the action that p9 would take to set the vnf p5 address/port
+	pnf_test_config[0].enabled = 1;
+	pnf_test_config[0].vnf_p5_port = vnf_test_config[0].p5_port;
+	pnf_test_config[0].vnf_p5_addr = vnf_test_config[0].p5_addr;
+	pnf_test_config[0].p7_rx_port_base = 8000;
+
+	pnf_test_config[1].enabled = 1;
+	pnf_test_config[1].vnf_p5_port = vnf_test_config[0].p5_port;
+	pnf_test_config[1].vnf_p5_addr = vnf_test_config[0].p5_addr;
+	pnf_test_config[1].p7_rx_port_base = 8100;
+
+	pnf_connection_indication_called = 0;
+
+	start_vnf_p5(&vnf_test_config[0]);
+
+
+	pnf_create_p5_sock(&pnf_test_config[0]);
+	pnf_p5_connect(&pnf_test_config[0]);
+
+	receive_pnf_param_request(&pnf_test_config[0]);
+	send_pnf_param_response(&pnf_test_config[0]);
+
+	receive_pnf_config_request(&pnf_test_config[0]);
+	send_pnf_config_response(&pnf_test_config[0]);
+
+	receive_pnf_start_request(&pnf_test_config[0]);
+	send_pnf_start_response(&pnf_test_config[0]);
+
+	pnf_create_p5_sock(&pnf_test_config[1]);
+
+	pnf_p5_connect(&pnf_test_config[1]);
+
+	receive_pnf_param_request(&pnf_test_config[1]);
+	send_pnf_param_response(&pnf_test_config[1]);
+
+	receive_pnf_config_request(&pnf_test_config[1]);
+	send_pnf_config_response(&pnf_test_config[1]);
+
+	receive_pnf_start_request(&pnf_test_config[1]);
+	send_pnf_start_response(&pnf_test_config[1]);
+
+	// start the vnf_p7 thread and assign by phys to that instance
+
+	start_vnf_p7(&vnf_test_config[0].vnfs[0]);
+	//start_vnf_p7(&vnf_test_config[0].vnfs[1]);
+	
+	printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[0].phy_id);
+	vnf_test_config[0].phys[0].vnf_idx = 0;
+	start_phy(&vnf_test_config[0].phys[0]);
+
+	int phy_id = receive_param_request(&pnf_test_config[0]);
+	send_param_response(&pnf_test_config[0], phy_id); 
+
+	phy_id = receive_config_request(&pnf_test_config[0]);
+	send_config_response(&pnf_test_config[0], phy_id);
+
+	printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[2].phy_id);
+	vnf_test_config[0].phys[2].vnf_idx = 0; 
+	start_phy(&vnf_test_config[0].phys[2]);
+
+	phy_id = receive_param_request(&pnf_test_config[1]);
+	send_param_response(&pnf_test_config[1], phy_id); 
+
+	phy_id = receive_config_request(&pnf_test_config[1]);
+	send_config_response(&pnf_test_config[1], phy_id);
+
+	printf("---- configuring phy %d -----\n", vnf_test_config[0].phys[1].phy_id);
+
+	vnf_test_config[0].phys[1].vnf_idx = 0;
+	start_phy(&vnf_test_config[0].phys[1]);
+
+	phy_id = receive_param_request(&pnf_test_config[0]);
+	send_param_response(&pnf_test_config[0], phy_id); 
+
+	phy_id = receive_config_request(&pnf_test_config[0]);
+	send_config_response(&pnf_test_config[0], phy_id);
+
+	//-------------
+	printf("---- starting phy %d -----\n", vnf_test_config[0].phys[0].phy_id);
+
+	send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[0]);
+	phy_id = receive_start_request(&pnf_test_config[0]);
+	send_start_response(&pnf_test_config[0], phy_id);
+/*
+	printf("---- starting phy %d -----\n", vnf_test_config[0].phys[2].phy_id);
+
+	send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[2]);
+	phy_id = receive_start_request(&pnf_test_config[1]);
+	send_start_response(&pnf_test_config[1], phy_id);
+
+	printf("---- starting phy %d -----\n", vnf_test_config[0].phys[1].phy_id);
+
+	send_vnf_start_req(&vnf_test_config[0], &vnf_test_config[0].phys[1]);
+	phy_id = receive_start_request(&pnf_test_config[0]);
+	send_start_response(&pnf_test_config[0], phy_id);
+*/
+	//close(pnf_test_config[0].p5_sock);
+
+	char buffer[2048];
+	int buffer_size = sizeof(buffer);
+
+	
+	fd_set rdfs;
+	int exit = 0;
+	while(exit != 1)
+	{
+		int pnf_idx, phy_idx; 
+		int max_fd = 0;
+		FD_ZERO(&rdfs);
+
+		for(pnf_idx = 0; pnf_idx < 4; ++pnf_idx)
+		{
+			if(pnf_test_config[pnf_idx].enabled)
+			{
+				FD_SET(pnf_test_config[pnf_idx].p5_sock, &rdfs);
+				if(pnf_test_config[pnf_idx].p5_sock > max_fd)
+					max_fd = pnf_test_config[pnf_idx].p5_sock;
+			}
+
+			for(phy_idx = 0; phy_idx < 4; ++phy_idx)
+			{
+				pnf_test_config_phy_t* phy_info = &(pnf_test_config[pnf_idx].phys[phy_idx]);
+
+				if(phy_info->started == 1 && phy_info->enabled == 1)
+				{
+					//////////////////printf("adding %d/%d %d %d\n", pnf_idx, phy_idx, phy_info->phy_id, phy_info->p7_rx_sock);
+					FD_SET(phy_info->p7_rx_sock, &rdfs);
+					if(phy_info->p7_rx_sock > max_fd)
+						max_fd = phy_info->p7_rx_sock;
+				}
+			}
+		}
+
+		
+		// changed to select,
+		int select_result = select(max_fd + 1, &rdfs, NULL, NULL, NULL);
+		(void)select_result;
+
+		for(pnf_idx = 0; pnf_idx < 4; ++pnf_idx)
+		{
+			if(pnf_test_config[pnf_idx].enabled)
+			{
+				//pnf_test_config_t* pnf_config = &(pnf_test_config[pnf_idx]);
+			}
+
+			for(phy_idx = 0; phy_idx < 4; ++phy_idx)
+			{
+				pnf_test_config_phy_t* phy_info = &(pnf_test_config[pnf_idx].phys[phy_idx]);
+
+				if(phy_info->enabled)
+				{
+					if(FD_ISSET(phy_info->p7_rx_sock, &rdfs))
+					{
+						//struct sockaddr_in recv_addr;
+						//memset(&recv_addr, 0, sizeof(recv_addr));
+						//socklen_t recv_addr_size;
+						int len = recvfrom(phy_info->p7_rx_sock, &buffer[0], buffer_size, 0, 0, 0);// (struct sockaddr*)&recv_addr, &recv_addr_size);
+
+						if(len == -1)
+						{
+							printf("recvfrom %d failed %d\n", phy_info->p7_rx_sock, errno);
+							continue;
+						}
+
+						nfapi_p7_message_header_t header;
+						nfapi_p7_message_header_unpack(buffer, len, &header, sizeof(header), 0);
+
+						switch(header.message_id)
+						{
+							case NFAPI_DL_NODE_SYNC:
+								{
+									nfapi_dl_node_sync_t msg;
+									nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
+									printf("[PNF:%d] NFAPI_DL_NODE_SYNC t1:%d\n", msg.header.phy_id, msg.t1);
+
+									nfapi_ul_node_sync_t resp;
+									memset(&resp, 0, sizeof(resp));
+									resp.header.message_id = NFAPI_UL_NODE_SYNC;
+									resp.header.phy_id = msg.header.phy_id;
+									resp.t1 = msg.t1;
+									usleep(50);
+									resp.t2 = msg.t1 + 50; // 50 us rx latency
+									resp.t3 = msg.t1 + 10; // 10 us pnf proc
+
+									usleep(50);
+
+									len = nfapi_p7_message_pack(&resp, buffer, buffer_size, 0);
+									// send ul node sycn
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+								}
+								break;
+							case NFAPI_DL_CONFIG_REQUEST:
+								{
+									nfapi_dl_config_request_t msg;
+									nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
+									//printf("[PNF:%d] (%d/%d) NFAPI_DL_CONFIG_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
+
+									if(SFNSF2SFN(msg.sfn_sf) == 500)
+										exit = 1;
+									// simulate the uplink messages
+									
+									nfapi_harq_indication_t harq_ind;
+									memset(&harq_ind, 0, sizeof(harq_ind));
+									harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
+									harq_ind.header.phy_id = msg.header.phy_id;
+									harq_ind.sfn_sf = msg.sfn_sf;
+									harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+									harq_ind.harq_indication_body.number_of_harqs = 2;
+
+									harq_ind.harq_indication_body.harq_pdu_list = (nfapi_harq_indication_pdu_t*)(malloc(sizeof(nfapi_harq_indication_pdu_t) * harq_ind.harq_indication_body.number_of_harqs));
+
+									int i = 0;
+									for(i = 0; i < harq_ind.harq_indication_body.number_of_harqs; ++i)
+									{
+										harq_ind.harq_indication_body.harq_pdu_list[i].rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
+									}
+									len = nfapi_p7_message_pack(&harq_ind, buffer, buffer_size, 0);
+									//sendto(phy_info->p7_tx_sock, &buffer[0], len, 0, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+									
+
+
+									//sendto(phy_info->p7_tx_sock, &buffer[0], len, 0, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									free(harq_ind.harq_indication_body.harq_pdu_list);
+
+									nfapi_crc_indication_t crc_ind;
+									memset(&crc_ind, 0, sizeof(crc_ind));
+									crc_ind.header.message_id = NFAPI_CRC_INDICATION;
+									crc_ind.header.phy_id = msg.header.phy_id;
+									crc_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&crc_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_sr_indication_t sr_ind;
+									memset(&sr_ind, 0, sizeof(sr_ind));
+									sr_ind.header.message_id = NFAPI_RX_SR_INDICATION;
+									sr_ind.header.phy_id = msg.header.phy_id;
+									sr_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&sr_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_cqi_indication_t cqi_ind;
+									memset(&cqi_ind, 0, sizeof(cqi_ind));
+									cqi_ind.header.message_id = NFAPI_RX_CQI_INDICATION;
+									cqi_ind.header.phy_id = msg.header.phy_id;
+									cqi_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&cqi_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_rach_indication_t rach_ind;
+									memset(&rach_ind, 0, sizeof(rach_ind));
+									rach_ind.header.message_id = NFAPI_RACH_INDICATION;
+									rach_ind.header.phy_id = msg.header.phy_id;
+									rach_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&rach_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_srs_indication_t srs_ind;
+									memset(&srs_ind, 0, sizeof(srs_ind));
+									srs_ind.header.message_id = NFAPI_SRS_INDICATION;
+									srs_ind.header.phy_id = msg.header.phy_id;
+									srs_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&srs_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_rx_indication_t rx_ind;
+									memset(&rx_ind, 0, sizeof(rx_ind));
+									rx_ind.header.message_id = NFAPI_RX_ULSCH_INDICATION;
+									rx_ind.header.phy_id = msg.header.phy_id;
+									rx_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&rx_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									if(msg.sfn_sf % 5 == 0)
+									{
+										// periodically send the timing info
+										nfapi_timing_info_t timing_info;
+										memset(&timing_info, 0, sizeof(timing_info));
+										timing_info.header.message_id = NFAPI_TIMING_INFO;
+										timing_info.header.phy_id = msg.header.phy_id;
+										len = nfapi_p7_message_pack(&timing_info, buffer, buffer_size, 0);
+										send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+									}
+									
+									nfapi_nb_harq_indication_t nb_harq_ind;
+									memset(&nb_harq_ind, 0, sizeof(nb_harq_ind));
+									nb_harq_ind.header.message_id = NFAPI_NB_HARQ_INDICATION;
+									nb_harq_ind.header.phy_id = msg.header.phy_id;
+									nb_harq_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&nb_harq_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+									nfapi_nrach_indication_t nrach_ind;
+									memset(&nrach_ind, 0, sizeof(nrach_ind));
+									nrach_ind.header.message_id = NFAPI_NRACH_INDICATION;
+									nrach_ind.header.phy_id = msg.header.phy_id;
+									nrach_ind.sfn_sf = msg.sfn_sf;
+									len = nfapi_p7_message_pack(&nrach_ind, buffer, buffer_size, 0);
+									send_p7_segmented_msg(phy_info->p7_tx_sock, &buffer[0], len, segment_size, (struct sockaddr*)&phy_info->p7_tx_sockaddr, sizeof(phy_info->p7_tx_sockaddr));
+
+								}
+								break;
+							case NFAPI_UL_CONFIG_REQUEST:
+								{
+									nfapi_ul_config_request_t msg;
+									nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
+									//printf("[PNF:%d] (%d/%d) NFAPI_UL_CONFIG_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
+								}
+								break;
+							case NFAPI_HI_DCI0_REQUEST:
+								{
+									nfapi_hi_dci0_request_t msg;
+									nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
+									//printf("[PNF:%d] (%d/%d) NFAPI_HI_DCI0_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
+								}
+								break;
+							case NFAPI_TX_REQUEST:
+								{
+									nfapi_tx_request_t msg;
+									nfapi_p7_message_unpack(buffer, len, &msg, sizeof(msg), 0);
+									//printf("[PNF:%d] (%d/%d) NFAPI_TX_REQUEST\n", header.phy_id, SFNSF2SFN(msg.sfn_sf), SFNSF2SF(msg.sfn_sf));
+								}
+								break;
+						}
+					
+					}
+				}
+			}
+		}
+	}
+
+	printf("Triggering p5 shutdown\n");
+
+	// vnf p5 trigger shutdown
+	nfapi_pnf_stop_request_t stop_req;
+	memset(&stop_req, 0, sizeof(stop_req));
+	stop_req.header.message_id = NFAPI_PNF_STOP_REQUEST;
+	nfapi_vnf_pnf_stop_req(vnf_test_config[0].p5_vnf_config, 0, &stop_req);
+
+	phy_id = receive_pnf_stop_request(&pnf_test_config[0]);
+	send_pnf_stop_response(&pnf_test_config[0], phy_id);
+
+
+	nfapi_vnf_stop(vnf_test_config[0].p5_vnf_config);
+
+
+	
+	int* result;
+	pthread_join((vnf_test_config[0].thread), (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+	//CU_ASSERT_EQUAL(pnf_connection_indication_called, 1);
+
+
+	close(pnf_test_config[0].p5_sock);
+}
+
+void vnf_test_start_connect_ipv6(void)
+{
+	char* vnf_addr = "::1";
+	int vnf_port = 4242;
+	pnf_connection_indication_called = 0;
+
+	nfapi_vnf_config_t* config = nfapi_vnf_config_create();
+	config->vnf_p5_port = vnf_port;
+	config->vnf_ipv4 = 0;
+	config->vnf_ipv6 = 1;
+	config->pnf_connection_indication = &pnf_connection_indication;
+	config->pnf_disconnect_indication = &pnf_disconnect_indication;
+	config->pnf_param_resp = &pnf_param_response;
+	config->pnf_config_resp = &pnf_config_response;
+	config->pnf_start_resp = &pnf_start_response;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &vnf_test_start_thread, config);
+
+	sleep(1);
+
+	
+	int p5Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+	
+	struct sockaddr_in6 addr;
+	addr.sin6_family = AF_INET6;
+	addr.sin6_port = htons(vnf_port);
+	//addr.sin6_addr = inet_addr(vnf_addr);
+	inet_pton(AF_INET6, vnf_addr, &addr.sin6_addr);
+
+
+	/*
+	int connect_result = connect(p5Sock, (struct sockaddr *)&addr, sizeof(addr) );
+
+	printf("connect_result %d %d\n", connect_result, errno);
+
+	receive_pnf_param_request(p5Sock);
+	send_pnf_param_response(p5Sock, &addr, sizeof(addr));
+
+	receive_pnf_config_request(p5Sock);
+	send_pnf_config_response(p5Sock, &addr, sizeof(addr));
+
+	receive_pnf_start_request(p5Sock);
+	send_pnf_start_response(p5Sock, &addr, sizeof(addr));
+	*/
+	sleep(4);
+	nfapi_vnf_stop(config);
+	
+	int* result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+	CU_ASSERT_EQUAL(pnf_connection_indication_called, 1);
+
+
+	close(p5Sock);
+}
+void vnf_test_start_connect_2(void)
+{
+	char* vnf_addr = "127.0.0.1";
+	int vnf_port = 4242;
+	pnf_connection_indication_called = 0;
+
+	nfapi_vnf_config_t * config = nfapi_vnf_config_create();
+	config->vnf_p5_port = vnf_port;
+	config->pnf_connection_indication = &pnf_connection_indication;
+
+	pthread_t thread;
+	pthread_create(&thread, NULL, &vnf_test_start_thread, config);
+
+	sleep(1);
+
+	
+	
+	struct sockaddr_in addr;
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(vnf_port);
+	addr.sin_addr.s_addr = inet_addr(vnf_addr);
+
+	
+	int p5Sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+	int connect_result_1 = connect(p5Sock1, (struct sockaddr *)&addr, sizeof(addr) );
+
+	printf("connect_result_1 %d %d\n", connect_result_1, errno);
+
+	int p5Sock2 = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+	int connect_result_2 = connect(p5Sock2, (struct sockaddr *)&addr, sizeof(addr) );
+
+	printf("connect_result_2 %d %d\n", connect_result_2, errno);
+
+	sleep(1);
+
+	close(p5Sock1);
+
+	sleep(1);
+
+	close(p5Sock2);
+
+	sleep(1);
+
+	nfapi_vnf_stop(config);
+	
+	int* result;
+	pthread_join(thread, (void**)&result);
+	CU_ASSERT_EQUAL(result, 0);
+	CU_ASSERT_EQUAL(pnf_connection_indication_called, 2);
+
+
+	close(p5Sock1);
+	close(p5Sock2);
+}
+
+void vnf_test_p7_segmentation_test1(void)
+{
+
+}
+
+
+/************* Test Runner Code goes here **************/
+
+int main ( void )
+{
+   CU_pSuite pSuite = NULL;
+
+   /* initialize the CUnit test registry */
+   if ( CUE_SUCCESS != CU_initialize_registry() )
+      return CU_get_error();
+
+   /* add a suite to the registry */
+   pSuite = CU_add_suite( "vnf_test_suite", init_suite, clean_suite );
+   if ( NULL == pSuite ) 
+   {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+        //(NULL == CU_add_test(pSuite, "vnf_test_start_connect_2", vnf_test_start_connect_2)) 
+   /* add the tests to the suite */
+   if ( (NULL == CU_add_test(pSuite, "vnf_test_start_no_config", vnf_test_start_no_config)) ||
+        (NULL == CU_add_test(pSuite, "vnf_test_start_connect", vnf_test_start_connect)) ||
+        (NULL == CU_add_test(pSuite, "vnf_test_p7_segmentation_test1", vnf_test_p7_segmentation_test1))
+      )
+   {
+      CU_cleanup_registry();
+      return CU_get_error();
+   }
+
+   // Run all tests using the basic interface
+   CU_basic_set_mode(CU_BRM_VERBOSE);
+   CU_set_output_filename("vnf_unit_test_results.xml");
+   CU_basic_run_tests();
+
+	CU_pSuite s = CU_get_registry()->pSuite;
+	int count = 0;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+	printf("%d..%d\n", 1, count);
+
+
+
+	s = CU_get_registry()->pSuite;
+	count = 1;
+	while(s)
+	{
+		CU_pTest t = s->pTest;
+		while(t)
+		{
+			int pass = 1;
+			CU_FailureRecord* failures = CU_get_failure_list();
+			while(failures)
+			{
+				if(strcmp(failures->pSuite->pName, s->pName) == 0 &&
+				   strcmp(failures->pTest->pName, t->pName) == 0)
+				{
+					pass = 0;
+					failures = 0;
+				}
+				else
+				{
+					failures = failures->pNext;
+				}
+			}
+
+			if(pass)
+				printf("ok %d - %s:%s\n", count, s->pName, t->pName);
+			else 
+				printf("not ok %d - %s:%s\n", count, s->pName, t->pName);
+
+			count++;
+			t = t->pNext;
+		}
+		s = s->pNext;
+	}
+
+   CU_cleanup_registry();
+   return CU_get_error();
+
+}
diff --git a/nfapi/open-nFAPI/vnf_sim/Makefile.am b/nfapi/open-nFAPI/vnf_sim/Makefile.am
new file mode 100644
index 0000000000..c3e42cebf3
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf_sim/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2017 Cisco Systems, Inc.
+# 
+# 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.
+# 
+
+AUTOMAKE_OPTIONS=subdir-objects
+AM_CPPFLAGS = -I$(top_srcdir)/vnf_sim/inc -I$(top_srcdir)/sim_common/inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/vnf/inc -I$(top_srcdir)/vnf/public_inc $(XML_CFLAGS) -Wall -Werror -g
+AM_CXXFLAGS = -I$(top_srcidr)/vnf_sim/inc -I$(top_srcdir)/sim_common/inc -I$(top_srcdir)/common/public_inc -I$(top_srcdir)/nfapi/inc -I$(top_srcdir)/nfapi/public_inc -I$(top_srcdir)/vnf/inc -I$(top_srcdir)/vnf/public_inc $(XML_CFLAGS) -std=c++11 $(BOOST_CPPFLAGS) -g
+bin_PROGRAMS = vnfsim
+vnfsim_SOURCES = src/main.cpp src/mac.cpp
+LDADD= $(top_builddir)/vnf/libnfapi_vnf.a $(top_builddir)/common/libnfapi_common.a $(top_builddir)/nfapi/libnfapi.a $(top_builddir)/sim_common/libnfapi_sim_common.a -L$(libdir) -lpthread -lrt -lsctp -lz
diff --git a/nfapi/open-nFAPI/vnf_sim/inc/mac.h b/nfapi/open-nFAPI/vnf_sim/inc/mac.h
new file mode 100644
index 0000000000..eac5b3b2ac
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf_sim/inc/mac.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 _MAC_H_
+#define _MAC_H_
+
+#include "nfapi_interface.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct mac mac_t;
+
+typedef struct mac
+{
+	void* user_data;
+
+	void (*dl_config_req)(mac_t* mac, nfapi_dl_config_request_t* req);
+	void (*ul_config_req)(mac_t* mac, nfapi_ul_config_request_t* req);
+	void (*hi_dci0_req)(mac_t* mac, nfapi_hi_dci0_request_t* req);
+	void (*tx_req)(mac_t* mac, nfapi_tx_request_t* req);
+} mac_t;
+
+mac_t* mac_create(uint8_t wireshark_test_mode);
+void mac_destroy(mac_t* mac);
+
+void mac_start_data(mac_t* mac, unsigned rx_port, const char* tx_addres, unsigned tx_port);
+
+void mac_subframe_ind(mac_t* mac, uint16_t phy_id, uint16_t sfn_sf);
+void mac_harq_ind(mac_t* mac, nfapi_harq_indication_t* ind);
+void mac_crc_ind(mac_t* mac, nfapi_crc_indication_t* ind);
+void mac_rx_ind(mac_t* mac, nfapi_rx_indication_t* ind);
+void mac_rach_ind(mac_t* mac, nfapi_rach_indication_t* ind);
+void mac_srs_ind(mac_t* mac, nfapi_srs_indication_t* ind);
+void mac_sr_ind(mac_t* mac, nfapi_sr_indication_t* ind);
+void mac_cqi_ind(mac_t* mac, nfapi_cqi_indication_t* ind);
+void mac_lbt_dl_ind(mac_t* mac, nfapi_lbt_dl_indication_t* ind);
+void mac_nb_harq_ind(mac_t* mac, nfapi_nb_harq_indication_t* ind);
+void mac_nrach_ind(mac_t* mac, nfapi_nrach_indication_t* ind);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/nfapi/open-nFAPI/vnf_sim/src/mac.cpp b/nfapi/open-nFAPI/vnf_sim/src/mac.cpp
new file mode 100644
index 0000000000..fa6f487be8
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf_sim/src/mac.cpp
@@ -0,0 +1,1327 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 "mac.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <vendor_ext.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <mutex>
+#include <queue>
+#include <list>
+
+uint32_t rand_range(uint32_t min, uint32_t max)
+{
+	return ((rand() % (max + 1 - min)) + min);
+}
+
+struct mac_pdu
+{
+	mac_pdu() : buffer_len(1500), buffer(0), len(0)
+	{
+		buffer = (char*) malloc(buffer_len);
+	}
+	
+	virtual ~mac_pdu()
+	{
+		free(buffer);
+	}
+
+	unsigned buffer_len;
+	char* buffer;
+	unsigned len;
+};
+
+class mac_private
+{
+		std::mutex mutex;
+		std::queue<mac_pdu*> rx_buffer;
+
+		std::queue<mac_pdu*> free_store;
+	public:
+
+		mac_private(bool _wireshark_test_mode)
+			: byte_count(0), tick(0), wireshark_test_mode(_wireshark_test_mode)
+		{
+
+		}
+
+		mac_pdu* allocate_mac_pdu()
+		{
+			mac_pdu* pdu = 0;
+			mutex.lock();
+			if(free_store.empty())
+			{
+				pdu = new mac_pdu();
+			}
+			else
+			{
+				pdu = free_store.front();
+				free_store.pop();
+			}
+			mutex.unlock();
+			return pdu;
+		}
+
+		void release_mac_pdu(mac_pdu* pdu)
+		{
+			mutex.lock();
+			free_store.push(pdu);
+			mutex.unlock();
+		}
+
+		
+
+		void push_rx_buffer(mac_pdu* buff)
+		{
+			mutex.lock();
+			rx_buffer.push(buff);
+			mutex.unlock();
+		}
+
+		mac_pdu* pop_rx_buffer()
+		{
+			mac_pdu* buff = 0;
+			mutex.lock();
+			if(!rx_buffer.empty())
+			{
+				buff = rx_buffer.front();
+				rx_buffer.pop();
+			}
+			mutex.unlock();
+			return buff;
+		}
+
+		uint32_t byte_count;
+		uint32_t tick;
+		
+		bool wireshark_test_mode;
+
+};
+
+extern "C"
+{
+	typedef struct {
+		mac_t _public;
+
+		int rx_sock;
+		int tx_sock;
+		struct sockaddr_in tx_addr;
+
+		uint32_t tx_byte_count;
+
+		mac_private* mac;
+		
+	} mac_internal_t;
+
+	mac_t* mac_create(uint8_t wireshark_test_mode)
+	{
+		mac_internal_t* instance = (mac_internal_t*)malloc(sizeof(mac_internal_t));
+		instance->mac = new mac_private((wireshark_test_mode >= 1));
+		return (mac_t*)instance;
+	}
+	
+	void mac_destroy(mac_t* mac)
+	{
+		mac_internal_t* instance = (mac_internal_t*)mac;
+		delete instance->mac;
+		free(instance);
+	}
+	
+	void* mac_rx_thread_start(void* ptr)
+	{
+		mac_internal_t* instance = (mac_internal_t*)ptr;
+
+		while(1)
+		{
+			mac_pdu* pdu = instance->mac->allocate_mac_pdu();
+			int len = recvfrom(instance->rx_sock, pdu->buffer, pdu->buffer_len, 0, 0, 0);
+			if(len > 0)
+			{
+				pdu->len = len;
+				instance->mac->push_rx_buffer(pdu);
+			}
+			else
+			{
+				instance->mac->release_mac_pdu(pdu);
+			}
+		}
+		return 0;
+	}
+
+	void mac_start_data(mac_t* mac, unsigned rx_port, const char* tx_address, unsigned tx_port)
+	{
+		mac_internal_t* instance = (mac_internal_t*)mac;
+
+		printf("[MAC] Rx Data from %d\n", rx_port);
+		printf("[MAC] Tx Data to %s.%d\n", tx_address, tx_port);
+
+		instance->rx_sock = socket(AF_INET, SOCK_DGRAM, 0);
+		
+		if(instance->rx_sock < 0)
+		{
+			printf("[MAC] Failed to create socket\n");
+			return;
+		}
+
+		struct sockaddr_in addr;
+		memset(&addr, 0, sizeof(0));
+		addr.sin_family = AF_INET;
+		addr.sin_port = htons(rx_port);
+		addr.sin_addr.s_addr = INADDR_ANY;
+		
+		if(bind(instance->rx_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
+		{
+			printf("[MAC] Failed to bind to %d\n", rx_port);
+			close(instance->rx_sock);
+			return;
+		}
+
+		pthread_t mac_rx_thread;
+		pthread_create(&mac_rx_thread, NULL, &mac_rx_thread_start, instance);
+
+		instance->tx_sock = socket(AF_INET, SOCK_DGRAM, 0);
+		instance->tx_addr.sin_family = AF_INET;
+		instance->tx_addr.sin_port = htons(tx_port);
+		instance->tx_addr.sin_addr.s_addr = inet_addr(tx_address);
+	}
+
+
+	
+	void generate_test_subframe(mac_t *mac, uint16_t phy_id, uint16_t sfn_sf)	
+	{
+		//mac_internal_t* instance = (mac_internal_t*)mac;
+		
+		uint8_t max_num_dl_pdus = 50;
+		nfapi_dl_config_request_pdu_t dl_config_pdus[max_num_dl_pdus];
+		memset(&dl_config_pdus, 0, sizeof(dl_config_pdus));
+		
+		nfapi_dl_config_request_t dl_config_req;
+		memset(&dl_config_req, 0, sizeof(dl_config_req));
+		dl_config_req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+		dl_config_req.header.phy_id = phy_id;
+		dl_config_req.sfn_sf = sfn_sf;
+		dl_config_req.dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+		
+		dl_config_req.dl_config_request_body.number_pdu = rand_range(4, max_num_dl_pdus);
+		
+		uint16_t i = 0;
+		for(i = 0; i < dl_config_req.dl_config_request_body.number_pdu; ++i)
+		{
+			dl_config_pdus[i].pdu_type = rand_range(0, 11);
+			
+			switch(dl_config_pdus[i].pdu_type)
+			{
+				case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
+				{
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.dci_format = rand_range(0, 9);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = rand_range(0, 255);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level  = rand_range(0, 32);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti = rand_range(0, (uint16_t)-1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rand_range(0, 320000);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = rand_range(0, 31);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = rand_range(0, 3);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.transport_block_to_codeword_swap_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = rand_range(0, 31);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = rand_range(0, 31);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_2 = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.harq_process = rand_range(0, 31);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.tpmi = rand_range(0, 15);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.pmi = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.precoding_information = rand_range(0, 63);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.tpc = rand_range(0, 3);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = rand_range(0, 15);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.ngap = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.transport_block_size_index = rand_range(0, 31);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.downlink_power_offset = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.allocate_prach_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.preamble_index = rand_range(0, 63);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.prach_mask_index = rand_range(0, 15);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = rand_range(0, 3);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = rand_range(0, 10000);		
+					
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel9.mcch_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel9.mcch_change_notification = rand_range(0, 255);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel9.scrambling_identity = rand_range(0, 1);
+					
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.cross_carrier_scheduling_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.carrier_indicator = rand_range(0, 7);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.srs_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.srs_request = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.antenna_ports_scrambling_and_layers = rand_range(0, 15);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.total_dci_length_including_padding = rand_range(0, 255);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel10.n_dl_rb = rand_range(0, 100);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel11.harq_ack_resource_offset = rand_range(0, 3);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel11.pdsch_re_mapping_quasi_co_location_indicator = rand_range(0, 3);
+					
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.primary_cell_type = rand_range(0, 2);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.number_ul_dl_configurations = 2;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_indication[0] = rand_range(1, 5);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel12.ul_dl_configuration_indication[1] = rand_range(1, 5);
+					
+					
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG;
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.laa_end_partial_sf_flag = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.laa_end_partial_sf_configuration = rand_range(0, 255);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.initial_lbt_sf = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.codebook_size_determination = rand_range(0, 1);
+					dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.drms_table_flag = rand_range(0, 1);
+					
+					// if the tpm extention is present of not.
+					if(rand_range(0, 1))
+					{
+						dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm_struct_flag = rand_range(0, 1);
+						dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_prb_per_subband = rand_range(0, 8);
+						dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.number_of_subbands = rand_range(0, 13);
+						dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_antennas = 1; // rand_range(0, 8);
+						
+						for(int j = 0; j < dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.number_of_subbands; ++j)
+						{
+							dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[j].subband_index = j;
+							dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[j].scheduled_ues = 1; //rand_range(1, 4);
+							
+							for(int k = 0; k < dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.num_antennas; ++k)
+								for(int l = 0; l < dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[j].scheduled_ues; ++l)
+									dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm.subband_info[j].precoding_value[k][l] = rand_range(0, 65535);
+						}
+					}
+					else
+					{
+						dl_config_pdus[i].dci_dl_pdu.dci_dl_pdu_rel13.tpm_struct_flag = 0;
+					}
+					
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_BCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG;
+					dl_config_pdus[i].bch_pdu.bch_pdu_rel8.length = rand_range(0, 42);
+					dl_config_pdus[i].bch_pdu.bch_pdu_rel8.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].bch_pdu.bch_pdu_rel8.transmission_power = rand_range(0, 10000);
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_MCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG;
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.length = rand_range(0, 42);
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.rnti = 0xFFFD;
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.resource_allocation_type = 0;
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.resource_block_coding = 0;
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.modulation = rand_range(0, 8);
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.transmission_power = rand_range(0, 10000);
+					dl_config_pdus[i].mch_pdu.mch_pdu_rel8.mbsfn_area_id = rand_range(0, 255);
+				}
+				break;
+			
+				case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.length = rand_range(0, 42);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.rnti = rand_range(1, 65535);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = rand_range(0, 5);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = rand_range(0, 32000);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.modulation = rand_range(2, 8);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.redundancy_version = rand_range(0, 3);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.transport_blocks = rand_range(1, 2);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = rand_range(0, 13);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.number_of_layers = rand_range(1, 8);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 2; //rand_range(0, 13);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.codebook_index[0] = rand_range(0, 15);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.codebook_index[1] = rand_range(0, 15);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = rand_range(0, 14);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.pa = rand_range(0, 7);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.ngap = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.nprb = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.transmission_mode = rand_range(1, 10);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 2; //rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 2; //rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[0].subband_index = rand_range(0, 4);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[0].num_antennas = 1;	
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[0].bf_value[0] = rand_range(0, 128);	
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[1].subband_index = rand_range(0, 4);	
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[1].num_antennas = 1;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel8.bf_vector[1].bf_value[0] = rand_range(0, 128);	
+					
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel9.nscid = rand_range(0, 1);	
+					
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.csi_rs_flag = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.csi_rs_resource_config_r10 = 0;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.csi_rs_zero_tx_power_resource_config_bitmap_r10 = rand_range(0, 65535);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.csi_rs_number_nzp_configuration = 1;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.csi_rs_resource_config[0] = rand_range(0, 31);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel10.pdsch_start = rand_range(0, 4);		
+					
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.drms_config_flag = rand_range(0, 1);	
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.drms_scrambling = rand_range(0, 503);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.csi_config_flag = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.csi_scrambling = rand_range(0, 503);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.pdsch_re_mapping_flag = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.pdsch_re_mapping_atenna_ports = rand_range(1,4);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel11.pdsch_re_mapping_freq_shift = rand_range(0, 5);
+					
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG;
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel12.altcqi_table_r12 = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel12.maxlayers = rand_range(1, 8);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel12.n_dl_harq = rand_range(0, 255);
+					
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.dwpts_symbols = rand_range(3, 14);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.initial_lbt_sf = rand_range(0, 1);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.ue_type = rand_range(0, 2);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = rand_range(0, 2);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = rand_range(0, 10239);
+					dl_config_pdus[i].dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = rand_range(0, 1);
+				}
+				break;
+			
+				case NFAPI_DL_CONFIG_PCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.length = rand_range(0, 42);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.p_rnti = 0xFFFE;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.resource_allocation_type = rand_range(2, 6);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.virtual_resource_block_assignment_flag = rand_range(0, 1);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.resource_block_coding = rand_range(0, 34000);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.mcs = 0;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.redundancy_version = 0;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.number_of_transport_blocks = 1;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.transport_block_to_codeword_swap_flag = 0;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.transmission_scheme = rand_range(1, 6);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.number_of_layers = rand_range(1, 4);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.codebook_index = 0;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.ue_category_capacity = rand_range(0, 14);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.pa = rand_range(0, 7);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.transmission_power = rand_range(0, 10000);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.nprb = rand_range(0, 1);
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel8.ngap = rand_range(0, 1);	
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG;
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel13.ue_mode = rand_range(0, 1);	
+					dl_config_pdus[i].pch_pdu.pch_pdu_rel13.initial_transmission_sf_io = rand_range(0, 10239);
+				}
+				break;
+			
+				case NFAPI_DL_CONFIG_PRS_PDU_TYPE:
+				{
+					dl_config_pdus[i].prs_pdu.prs_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG;
+					dl_config_pdus[i].prs_pdu.prs_pdu_rel9.transmission_power = rand_range(0, 10000);	
+					dl_config_pdus[i].prs_pdu.prs_pdu_rel9.prs_bandwidth = rand_range(6, 100);
+					dl_config_pdus[i].prs_pdu.prs_pdu_rel9.prs_cyclic_prefix_type = rand_range(0, 1);
+					dl_config_pdus[i].prs_pdu.prs_pdu_rel9.prs_muting = rand_range(0, 1);
+				}
+				break;
+	
+				case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE:
+				{
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG;
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_antenna_port_count_r10 = rand_range(1, 16);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_resource_config_r10 = 0;
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.transmission_power = rand_range(0, 10000);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_zero_tx_power_resource_config_bitmap_r10 = rand_range(0, 8);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_number_of_nzp_configuration = 2;
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_resource_config[0] = rand_range(0, 31);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel10.csi_rs_resource_config[1] = rand_range(0, 31);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG;
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.csi_rs_class = rand_range(0, 2);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.cdm_type = rand_range(0, 1);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.num_bf_vector = 0; // set to zero as not clear how to handle bf value array
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.bf_vector[0].csi_rs_resource_index = rand_range(0, 7);
+					dl_config_pdus[i].csi_rs_pdu.csi_rs_pdu_rel13.bf_vector[0].bf_value[0] = 42;
+				}
+				break;
+	
+				case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE:
+				{
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.dci_format = rand_range(0, 9);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.cce_idx = rand_range(0, 255);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.aggregation_level  = rand_range(0, 32);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.rnti = rand_range(0, (uint16_t)-1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.resource_allocation_type = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.virtual_resource_block_assignment_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.resource_block_coding = rand_range(0, 320000);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.mcs_1 = rand_range(0, 31);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.redundancy_version_1 = rand_range(0, 3);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.new_data_indicator_1 = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.transport_block_to_codeword_swap_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.mcs_2 = rand_range(0, 31);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.redundancy_version_2 = rand_range(0, 31);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.new_data_indicator_2 = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.harq_process = rand_range(0, 31);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.tpmi = rand_range(0, 15);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.pmi = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.precoding_information = rand_range(0, 63);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.tpc = rand_range(0, 3);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.downlink_assignment_index = rand_range(0, 15);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.ngap = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.transport_block_size_index = rand_range(0, 31);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.downlink_power_offset = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.allocate_prach_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.preamble_index = rand_range(0, 63);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.prach_mask_index = rand_range(0, 15);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.rnti_type = rand_range(0, 3);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel8.transmission_power = rand_range(0, 10000);	
+					
+					
+					
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel9.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel9.mcch_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel9.mcch_change_notification = rand_range(0, 255);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel9.scrambling_identity = rand_range(0, 1);
+					
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.cross_carrier_scheduling_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.carrier_indicator = rand_range(0, 7);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.srs_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.srs_request = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.antenna_ports_scrambling_and_layers = rand_range(0, 15);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.total_dci_length_including_padding = rand_range(0, 255);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel10.n_dl_rb = rand_range(0, 100);
+					
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel11.harq_ack_resource_offset = rand_range(0, 3);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel11.pdsch_re_mapping_quasi_co_location_indicator = rand_range(0, 3);
+					
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.primary_cell_type = rand_range(0, 2);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.ul_dl_configuration_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.number_ul_dl_configurations = 2;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.ul_dl_configuration_indication[0] = rand_range(1, 5);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel12.ul_dl_configuration_indication[1] = rand_range(1, 5);
+					
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.laa_end_partial_sf_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.laa_end_partial_sf_configuration = rand_range(0, 255);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.initial_lbt_sf = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.codebook_size_determination = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_pdu_rel13.drms_table_flag = rand_range(0, 1);
+
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_resource_assignment_flag = rand_range(0, 1);
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_id = rand_range(0, 503);
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_start_symbol = rand_range(1, 4);
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_num_prb = rand_range(2, 8);
+					for(int j = 0; j < dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_num_prb; ++j)
+						dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_prb_index[j] = rand_range(0, 99);
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.bf_vector.subband_index = rand_range(0, 25);	
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.bf_vector.num_antennas= rand_range(1, 4);
+					for(int j = 0; j < dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.epdcch_num_prb; ++j)
+						dl_config_pdus[i].epdcch_pdu.epdcch_params_rel11.bf_vector.bf_value[j] = rand_range(0, 65535);
+					
+	
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG;
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel13.dwpts_symbols = rand_range(3, 14);
+					dl_config_pdus[i].epdcch_pdu.epdcch_params_rel13.initial_lbt_sf = rand_range(0, 1);
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG;
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs = rand_range(2, 6);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = rand_range(0, 14);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = rand_range(1, 4);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = rand_range(0, 22);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = rand_range(2, 24);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = rand_range(0, 4);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.rnti = rand_range(1, 65535);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = rand_range(1, 2);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = rand_range(0, 503);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io = rand_range(0, 10239);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = rand_range(0, 10000);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.dci_format = rand_range(10, 12);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = rand_range(0, 0xFFFF);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.mcs = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = rand_range(1, 8);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = rand_range(0, 3);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.harq_process = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = rand_range(0, 4);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.tpmi = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.pmi = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset = rand_range(0, 3);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number = rand_range(1, 4);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.tpc = rand_range(0, 3);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length = rand_range(0, 4);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag = rand_range(0, 63);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = rand_range(0, 15);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = rand_range(0, 3);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.srs_request = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = rand_range(0, 3);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = rand_range(0, 255);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = rand_range(0, 1);
+					dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports = rand_range(0, 8);
+					for(int j = 0 ; j < dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports; ++j)
+						dl_config_pdus[i].mpdcch_pdu.mpdcch_pdu_rel13.precoding_value[j] = rand_range(0, 65535);
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_NBCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].nbch_pdu.nbch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG;
+					dl_config_pdus[i].nbch_pdu.nbch_pdu_rel13.length = rand_range(0, 5555);
+					dl_config_pdus[i].nbch_pdu.nbch_pdu_rel13.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].nbch_pdu.nbch_pdu_rel13.transmission_power = rand_range(0, 10000);
+					dl_config_pdus[i].nbch_pdu.nbch_pdu_rel13.hyper_sfn_2_lsbs = rand_range(0, 3);
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG;
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.length = rand_range(0, 5555);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.ncce_index = rand_range(0, 1);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.aggregation_level = rand_range(1, 2);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.start_symbol = rand_range(0, 4);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.rnti_type = rand_range(0, 3);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.rnti = rand_range(1, 65535);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.scrambling_reinitialization_batch_index = rand_range(1, 4);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue = rand_range(1, 2);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.dci_format = rand_range(0, 1);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.scheduling_delay = rand_range(0, 7);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.resource_assignment = rand_range(0, 7);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.repetition_number = rand_range(0, 15); 
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.mcs = rand_range(0, 13);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.new_data_indicator = rand_range(0, 1);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource = rand_range(0, 15);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication = rand_range(0, 1);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.starting_number_of_nprach_repetitions = rand_range(0, 3);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.subcarrier_indication_of_nprach = rand_range(0, 63);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.paging_direct_indication_differentation_flag = rand_range(0, 1);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.direct_indication = rand_range(0, 255);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number  = rand_range(0, 7);
+					dl_config_pdus[i].npdcch_pdu.npdcch_pdu_rel13.total_dci_length_including_padding = rand_range(0, 255);
+				}
+				break;
+				
+				case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE:
+				{
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.tl.tag = NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG;
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.length = rand_range(0, 5555);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.pdu_index = rand_range(0, 65535);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.start_symbol = rand_range(0, 4);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.rnti_type = rand_range(0, 1);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.rnti = rand_range(1, 65535);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment = rand_range(0, 7);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.repetition_number = rand_range(0, 15);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.modulation = 2;
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment = rand_range(1, 10);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.scrambling_sequence_initialization_cinit = rand_range(0, 65535);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.sf_idx = rand_range(1, 10240);
+					dl_config_pdus[i].ndlsch_pdu.ndlsch_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue = rand_range(1, 2);
+				}
+				break;
+				
+			};
+		}
+
+
+		dl_config_req.dl_config_request_body.dl_config_pdu_list = dl_config_pdus;		
+		mac->dl_config_req(mac, &dl_config_req);
+		
+		uint8_t num_ul_pdus = 18;
+		nfapi_ul_config_request_pdu_t ul_config_pdus[num_ul_pdus];
+		memset(&ul_config_pdus, 0, sizeof(ul_config_pdus));
+		
+		nfapi_ul_config_request_t ul_config_req;
+		memset(&ul_config_req, 0, sizeof(ul_config_req));
+		ul_config_req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+		ul_config_req.header.phy_id = phy_id;
+		ul_config_req.sfn_sf = sfn_sf;
+		ul_config_req.ul_config_request_body.tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
+		ul_config_req.ul_config_request_body.number_of_pdus = num_ul_pdus;
+		ul_config_req.ul_config_request_body.rach_prach_frequency_resources = rand_range(0, 255);
+		ul_config_req.ul_config_request_body.srs_present = rand_range(0, 1);
+		
+		auto ul_config_ulsch_pdu_test_gen = [](nfapi_ul_config_ulsch_pdu& ulsch_pdu)
+		{
+			ulsch_pdu.ulsch_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG;
+			ulsch_pdu.ulsch_pdu_rel8.handle = rand_range(0, 50000);
+			ulsch_pdu.ulsch_pdu_rel8.size = rand_range(0, 32000);
+			ulsch_pdu.ulsch_pdu_rel8.rnti = rand_range(1, 65535);
+			ulsch_pdu.ulsch_pdu_rel8.resource_block_start = rand_range(0, 99);
+			ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks = rand_range(1, 100);
+			ulsch_pdu.ulsch_pdu_rel8.modulation_type = rand_range(2, 6);
+			ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms = rand_range(0, 7);
+			ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits = rand_range(0, 3);
+			ulsch_pdu.ulsch_pdu_rel8.new_data_indication = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel8.redundancy_version = rand_range(0, 3);
+			ulsch_pdu.ulsch_pdu_rel8.harq_process_number = rand_range(0, 15);
+			ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel8.current_tx_nb = rand_range(0, 5);
+			ulsch_pdu.ulsch_pdu_rel8.n_srs = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG;
+			ulsch_pdu.ulsch_pdu_rel10.resource_allocation_type = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel10.resource_block_coding = rand_range(0, 35000);
+			ulsch_pdu.ulsch_pdu_rel10.transport_blocks = rand_range(1, 2);
+			ulsch_pdu.ulsch_pdu_rel10.transmission_scheme = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel10.number_of_layers = rand_range(1, 4);
+			ulsch_pdu.ulsch_pdu_rel10.codebook_index = rand_range(0, 23);
+			ulsch_pdu.ulsch_pdu_rel10.disable_sequence_hopping_flag = rand_range(0, 1);		
+			ulsch_pdu.ulsch_pdu_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG;
+			ulsch_pdu.ulsch_pdu_rel11.virtual_cell_id_enabled_flag = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel11.npusch_identity = rand_range(0, 509);
+			ulsch_pdu.ulsch_pdu_rel11.dmrs_config_flag = rand_range(0, 1);
+			ulsch_pdu.ulsch_pdu_rel11.ndmrs_csh_identity = rand_range(0, 509);
+			ulsch_pdu.ulsch_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG;
+			ulsch_pdu.ulsch_pdu_rel13.ue_type = rand_range(0, 2);
+			ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions = rand_range(1, 2048);
+			ulsch_pdu.ulsch_pdu_rel13.repetition_number = rand_range(1, 2048);
+			ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io = rand_range(0, 10239);
+			ulsch_pdu.ulsch_pdu_rel13.empty_symbols_due_to_re_tunning = rand_range(0, 8);
+		};
+		
+		auto ul_config_cqi_ri_info_test_gen = [](nfapi_ul_config_cqi_ri_information& cqi_ri_information)
+		{
+			cqi_ri_information.cqi_ri_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG;
+			cqi_ri_information.cqi_ri_information_rel8.dl_cqi_pmi_size_rank_1 = rand_range(0, 255);
+			cqi_ri_information.cqi_ri_information_rel8.dl_cqi_pmi_size_rank_greater_1 = rand_range(0, 255);
+			cqi_ri_information.cqi_ri_information_rel8.ri_size = rand_range(0, 3);
+			cqi_ri_information.cqi_ri_information_rel8.delta_offset_cqi = rand_range(0, 15);
+			cqi_ri_information.cqi_ri_information_rel8.delta_offset_ri = rand_range(0, 15);
+
+			cqi_ri_information.cqi_ri_information_rel9.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG;
+			cqi_ri_information.cqi_ri_information_rel9.report_type = 1; // rand_range(0, 1);
+			cqi_ri_information.cqi_ri_information_rel9.delta_offset_cqi = rand_range(0, 15);
+			cqi_ri_information.cqi_ri_information_rel9.delta_offset_ri = rand_range(0, 15);
+			
+			if(cqi_ri_information.cqi_ri_information_rel9.report_type == 0)
+			{
+				cqi_ri_information.cqi_ri_information_rel9.periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size = rand_range(0, 255);
+				cqi_ri_information.cqi_ri_information_rel9.periodic_cqi_pmi_ri_report.control_type = rand_range(0, 1);
+			}
+			else
+			{
+				cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.number_of_cc = 1;
+				cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = rand_range(0, 3);
+				cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[0] = rand_range(0, 255);
+			}
+			
+			cqi_ri_information.cqi_ri_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG;
+			cqi_ri_information.cqi_ri_information_rel13.report_type = rand_range(0, 1);
+			
+			if(cqi_ri_information.cqi_ri_information_rel13.report_type == 0)
+			{
+				cqi_ri_information.cqi_ri_information_rel13.periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2 = rand_range(255, 10000);
+			}
+		};
+		
+		auto ul_config_init_tx_params_test_gen = [](nfapi_ul_config_initial_transmission_parameters& initial_transmission_parameters)
+		{
+			initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
+			initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = rand_range(0, 1);
+			initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rand_range(1, 100);
+		};
+		
+		auto ul_config_harqinfo_test_gen = [](nfapi_ul_config_ulsch_harq_information& harq_information)
+		{
+			harq_information.harq_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG;
+			harq_information.harq_information_rel10.harq_size = rand_range(0, 21);
+			harq_information.harq_information_rel10.delta_offset_harq = rand_range(0, 15);
+			harq_information.harq_information_rel10.ack_nack_mode = rand_range(0, 5);
+			harq_information.harq_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG;
+			harq_information.harq_information_rel13.harq_size_2 = rand_range(0, 21);
+			harq_information.harq_information_rel13.delta_offset_harq_2 = rand_range(0, 15);	
+		};
+
+		auto ul_config_sr_info_test_gen = [](nfapi_ul_config_sr_information& sr_info)
+		{
+			sr_info.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG;
+			sr_info.sr_information_rel8.pucch_index = rand_range(0, 2047);
+			sr_info.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG;
+			sr_info.sr_information_rel10.number_of_pucch_resources = rand_range(1, 2);
+			sr_info.sr_information_rel10.pucch_index_p1 = rand_range(0, 2047);
+		};
+		
+		auto ul_config_ue_info_test_gen = [](nfapi_ul_config_ue_information& ue_information)
+		{
+			ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
+			ue_information.ue_information_rel8.handle = rand_range(0, 99999);
+			ue_information.ue_information_rel8.rnti = rand_range(1, 65535);
+			ue_information.ue_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG;
+			ue_information.ue_information_rel11.virtual_cell_id_enabled_flag = rand_range(0, 1);
+			ue_information.ue_information_rel11.npusch_identity = rand_range(0, 503);
+			ue_information.ue_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG;
+			ue_information.ue_information_rel13.ue_type = rand_range(0, 2);
+			ue_information.ue_information_rel13.empty_symbols = rand_range(0, 2);
+			ue_information.ue_information_rel13.total_number_of_repetitions = rand_range(1, 32);
+			ue_information.ue_information_rel13.repetition_number = rand_range(1, 32);
+		};
+		
+		auto ul_config_cqi_info_test_gen = [](nfapi_ul_config_cqi_information& cqi_information)
+		{
+			cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
+			cqi_information.cqi_information_rel8.pucch_index = rand_range(0, 1184);
+			cqi_information.cqi_information_rel8.dl_cqi_pmi_size = rand_range(0, 255);
+			cqi_information.cqi_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG;
+			cqi_information.cqi_information_rel10.number_of_pucch_resource = rand_range(1, 2);
+			cqi_information.cqi_information_rel10.pucch_index_p1 = rand_range(0, 1184);
+			cqi_information.cqi_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG;
+			cqi_information.cqi_information_rel13.csi_mode = rand_range(0, 2);
+			cqi_information.cqi_information_rel13.dl_cqi_pmi_size_2 = rand_range(0, 999);
+			cqi_information.cqi_information_rel13.starting_prb = rand_range(0, 109);
+			cqi_information.cqi_information_rel13.n_prb = rand_range(0, 7);
+			cqi_information.cqi_information_rel13.cdm_index = rand_range(0, 1);
+			cqi_information.cqi_information_rel13.n_srs = rand_range(0, 1);
+		};
+		
+		auto ul_config_harq_info_test_gen = [](nfapi_ul_config_harq_information& harq_information)
+		{
+			harq_information.harq_information_rel10_tdd.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG;
+			harq_information.harq_information_rel10_tdd.harq_size = rand_range(0, 21);
+			harq_information.harq_information_rel10_tdd.ack_nack_mode = rand_range(0, 5);
+			harq_information.harq_information_rel10_tdd.number_of_pucch_resources = rand_range(0, 4);
+			harq_information.harq_information_rel10_tdd.n_pucch_1_0 = rand_range(0, 2047);
+			harq_information.harq_information_rel10_tdd.n_pucch_1_1 = rand_range(0, 2047);
+			harq_information.harq_information_rel10_tdd.n_pucch_1_2 = rand_range(0, 2047);
+			harq_information.harq_information_rel10_tdd.n_pucch_1_3 = rand_range(0, 2047);
+			harq_information.harq_information_rel8_fdd.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG;
+			harq_information.harq_information_rel8_fdd.n_pucch_1_0 = rand_range(0, 2047);
+			harq_information.harq_information_rel8_fdd.harq_size = rand_range(1, 2);
+			harq_information.harq_information_rel9_fdd.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG;
+			harq_information.harq_information_rel9_fdd.harq_size = rand_range(1, 10);
+			harq_information.harq_information_rel9_fdd.ack_nack_mode = rand_range(0, 4);
+			harq_information.harq_information_rel9_fdd.number_of_pucch_resources = rand_range(0, 4);
+			harq_information.harq_information_rel9_fdd.n_pucch_1_0 = rand_range(0, 2047);
+			harq_information.harq_information_rel9_fdd.n_pucch_1_1 = rand_range(0, 2047);
+			harq_information.harq_information_rel9_fdd.n_pucch_1_2 = rand_range(0, 2047);
+			harq_information.harq_information_rel9_fdd.n_pucch_1_3 = rand_range(0, 2047);
+			harq_information.harq_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG;
+			harq_information.harq_information_rel11.num_ant_ports = rand_range(1, 2);
+			harq_information.harq_information_rel11.n_pucch_2_0 = rand_range(0, 2047);
+			harq_information.harq_information_rel11.n_pucch_2_1 = rand_range(0, 2047);
+			harq_information.harq_information_rel11.n_pucch_2_2 = rand_range(0, 2047);
+			harq_information.harq_information_rel11.n_pucch_2_3 = rand_range(0, 2047);
+			harq_information.harq_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG;
+			harq_information.harq_information_rel13.harq_size_2 = rand_range(0, 999);
+			harq_information.harq_information_rel13.starting_prb = rand_range(0, 109);
+			harq_information.harq_information_rel13.n_prb = rand_range(0, 7);
+			harq_information.harq_information_rel13.cdm_index = rand_range(0, 1);
+			harq_information.harq_information_rel13.n_srs = rand_range(0, 1);
+		};		
+		
+		
+		ul_config_pdus[0].pdu_type = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[0].ulsch_pdu);
+
+		ul_config_pdus[1].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[1].ulsch_cqi_ri_pdu.ulsch_pdu);
+		ul_config_cqi_ri_info_test_gen(ul_config_pdus[1].ulsch_cqi_ri_pdu.cqi_ri_information);
+		ul_config_init_tx_params_test_gen(ul_config_pdus[1].ulsch_cqi_ri_pdu.initial_transmission_parameters);	
+
+		ul_config_pdus[2].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[2].ulsch_harq_pdu.ulsch_pdu);
+		ul_config_harqinfo_test_gen(ul_config_pdus[2].ulsch_harq_pdu.harq_information);
+		ul_config_init_tx_params_test_gen(ul_config_pdus[2].ulsch_harq_pdu.initial_transmission_parameters);
+		
+		ul_config_pdus[3].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[3].ulsch_cqi_harq_ri_pdu.ulsch_pdu);		
+		ul_config_cqi_ri_info_test_gen(ul_config_pdus[3].ulsch_cqi_harq_ri_pdu.cqi_ri_information);	
+		ul_config_harqinfo_test_gen(ul_config_pdus[3].ulsch_cqi_harq_ri_pdu.harq_information);
+		ul_config_init_tx_params_test_gen(ul_config_pdus[3].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters);
+		
+		
+		ul_config_pdus[4].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[4].uci_cqi_pdu.ue_information);
+		ul_config_cqi_info_test_gen(ul_config_pdus[4].uci_cqi_pdu.cqi_information);
+
+		ul_config_pdus[5].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[5].uci_sr_pdu.ue_information);
+		ul_config_sr_info_test_gen(ul_config_pdus[5].uci_sr_pdu.sr_information);
+
+		
+		ul_config_pdus[6].pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[6].uci_harq_pdu.ue_information);
+		ul_config_harq_info_test_gen(ul_config_pdus[6].uci_harq_pdu.harq_information);
+		
+		
+		ul_config_pdus[7].pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[7].uci_sr_harq_pdu.ue_information);
+		ul_config_sr_info_test_gen(ul_config_pdus[7].uci_sr_harq_pdu.sr_information);
+		ul_config_harq_info_test_gen(ul_config_pdus[7].uci_sr_harq_pdu.harq_information);
+		
+		ul_config_pdus[8].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[8].uci_cqi_harq_pdu.ue_information);
+		ul_config_cqi_info_test_gen(ul_config_pdus[8].uci_cqi_harq_pdu.cqi_information);
+		ul_config_harq_info_test_gen(ul_config_pdus[8].uci_cqi_harq_pdu.harq_information);
+		
+		ul_config_pdus[9].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[9].uci_cqi_sr_pdu.ue_information);
+		ul_config_cqi_info_test_gen(ul_config_pdus[9].uci_cqi_sr_pdu.cqi_information);
+		ul_config_sr_info_test_gen(ul_config_pdus[9].uci_cqi_sr_pdu.sr_information);
+		
+		ul_config_pdus[10].pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[10].uci_cqi_sr_harq_pdu.ue_information);
+		ul_config_cqi_info_test_gen(ul_config_pdus[10].uci_cqi_sr_harq_pdu.cqi_information);
+		ul_config_sr_info_test_gen(ul_config_pdus[10].uci_cqi_sr_harq_pdu.sr_information);
+		ul_config_harq_info_test_gen(ul_config_pdus[10].uci_cqi_sr_harq_pdu.harq_information);
+		
+		ul_config_pdus[11].pdu_type = NFAPI_UL_CONFIG_SRS_PDU_TYPE;
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.handle = rand_range(0, 9999);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.size = rand_range(1, 999);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.rnti = rand_range(1, 65535);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.srs_bandwidth = rand_range(0, 3);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.frequency_domain_position = rand_range(0, 23);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = rand_range(0, 3);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.transmission_comb = rand_range(0, 3);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.i_srs = rand_range(0, 1023);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = rand_range(0, 11);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG;
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel10.antenna_port = rand_range(0, 2);
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG;
+		ul_config_pdus[11].srs_pdu.srs_pdu_rel13.number_of_combs = rand_range(0, 1);
+		
+		ul_config_pdus[12].pdu_type = NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE;
+		ul_config_ue_info_test_gen(ul_config_pdus[12].harq_buffer_pdu.ue_information);		
+		
+		ul_config_pdus[13].pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[13].ulsch_uci_csi_pdu.ulsch_pdu);
+		ul_config_cqi_info_test_gen(ul_config_pdus[13].ulsch_uci_csi_pdu.csi_information);
+		
+		ul_config_pdus[14].pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[14].ulsch_uci_harq_pdu.ulsch_pdu);
+		ul_config_harq_info_test_gen(ul_config_pdus[14].ulsch_uci_harq_pdu.harq_information);
+		
+		ul_config_pdus[15].pdu_type = NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE;
+		ul_config_ulsch_pdu_test_gen(ul_config_pdus[15].ulsch_csi_uci_harq_pdu.ulsch_pdu);
+		ul_config_cqi_info_test_gen(ul_config_pdus[15].ulsch_csi_uci_harq_pdu.csi_information);
+		ul_config_harq_info_test_gen(ul_config_pdus[15].ulsch_csi_uci_harq_pdu.harq_information);
+		
+		ul_config_pdus[16].pdu_type = NFAPI_UL_CONFIG_NULSCH_PDU_TYPE;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.nulsch_format = rand_range(0, 1);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.handle = rand_range(0, 0xFFFF);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.size = rand_range(0, 65535);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.rnti = rand_range(1, 65535);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication = rand_range(0, 47);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.resource_assignment = rand_range(0, 7);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.mcs = rand_range(0, 12);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.redudancy_version = rand_range(0, 1);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.repetition_number = rand_range(0, 7);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.new_data_indication = rand_range(0, 1);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.n_srs = rand_range(0, 1);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.scrambling_sequence_initialization_cinit = rand_range(0, 65535);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.sf_idx = rand_range(0, 40960);
+		
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.handle = rand_range(0, 0xFF);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel8.rnti = rand_range(1, 65535);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.virtual_cell_id_enabled_flag = rand_range(0, 1);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel11.npusch_identity = rand_range(0, 503);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.ue_type = rand_range(0, 2);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.empty_symbols = rand_range(0, 0x3);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.total_number_of_repetitions = rand_range(1, 32);
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.repetition_number = rand_range(1, 32);
+		
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.tl.tag = NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG;
+		ul_config_pdus[16].nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.harq_ack_resource = rand_range(0, 15);
+		
+		ul_config_pdus[17].pdu_type = NFAPI_UL_CONFIG_NRACH_PDU_TYPE;
+		ul_config_pdus[17].nrach_pdu.nrach_pdu_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG;
+		ul_config_pdus[17].nrach_pdu.nrach_pdu_rel13.nprach_config_0 = rand_range(0, 1);
+		ul_config_pdus[17].nrach_pdu.nrach_pdu_rel13.nprach_config_1 = rand_range(0, 1);
+		ul_config_pdus[17].nrach_pdu.nrach_pdu_rel13.nprach_config_2 = rand_range(0, 1);
+		
+		ul_config_req.ul_config_request_body.ul_config_pdu_list = ul_config_pdus;	
+		mac->ul_config_req(mac, &ul_config_req);
+		
+		
+		uint8_t num_dci_pdus = 4;
+		uint8_t num_hi_pdus = 1;
+		nfapi_hi_dci0_request_pdu_t hi_dci0_pdus[num_dci_pdus + num_hi_pdus];
+		memset(&hi_dci0_pdus, 0, sizeof(hi_dci0_pdus));
+		
+		nfapi_hi_dci0_request_t hi_dci0_req;
+		memset(&hi_dci0_req, 0, sizeof(hi_dci0_req));
+		hi_dci0_req.header.message_id = NFAPI_HI_DCI0_REQUEST;
+		hi_dci0_req.header.phy_id = phy_id;
+		hi_dci0_req.sfn_sf = sfn_sf;
+		
+		hi_dci0_req.hi_dci0_request_body.tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG;
+		hi_dci0_req.hi_dci0_request_body.sfnsf = sfn_sf;
+		hi_dci0_req.hi_dci0_request_body.number_of_dci = num_dci_pdus;
+		hi_dci0_req.hi_dci0_request_body.number_of_hi = num_hi_pdus;
+		
+		hi_dci0_pdus[0].pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE;
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG;
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.resource_block_start = rand_range(0, 100);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = rand_range(0, 7);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.hi_value = rand_range(0, 1);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.i_phich = rand_range(0, 1);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel8.transmission_power = rand_range(0, 10000);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG;	
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel10.flag_tb2 = rand_range(0, 1);
+		hi_dci0_pdus[0].hi_pdu.hi_pdu_rel10.hi_value_2 = rand_range(0, 1);
+		
+		hi_dci0_pdus[1].pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE;
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.dci_format = rand_range(0, 4);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.cce_index = rand_range(0, 88);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.aggregation_level = rand_range(1, 8);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.rnti = rand_range(1, 65535);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.resource_block_start = rand_range(0, 100);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.number_of_resource_block = rand_range(0, 100);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.mcs_1 = rand_range(0, 31);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = rand_range(0, 7);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.frequency_hopping_bits = rand_range(0, 3);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.new_data_indication_1 = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.ue_tx_antenna_seleciton = rand_range(0, 2);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.tpc = rand_range(0, 3);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.cqi_csi_request = rand_range(0, 7);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.ul_index = rand_range(0, 3);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.dl_assignment_index = rand_range(1, 4);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.tpc_bitmap = rand_range(0, 9999);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel8.transmission_power = rand_range(0, 10000);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG;
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.cross_carrier_scheduling_flag = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.carrier_indicator = rand_range(0, 7);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.size_of_cqi_csi_feild = rand_range(0, 2);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.srs_flag = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.srs_request = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.resource_allocation_flag = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.resource_allocation_type = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.resource_block_coding = rand_range(0, 9999);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.mcs_2 = rand_range(0, 31);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.new_data_indication_2 = rand_range(0, 1);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.number_of_antenna_ports = rand_range(0, 2);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.tpmi = rand_range(0, 63);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.total_dci_length_including_padding = rand_range(0, 255);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel10.n_ul_rb = rand_range(6, 100);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel12.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG;
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel12.pscch_resource = rand_range(0, 16);
+		hi_dci0_pdus[1].dci_pdu.dci_pdu_rel12.time_resource_pattern = rand_range(0, 32);
+		
+		
+		hi_dci0_pdus[2].pdu_type = NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE;
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG;
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.dci_format = rand_range(0, 4);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.cce_index = rand_range(0, 88);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.aggregation_level = rand_range(1, 8);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.rnti = rand_range(1, 65535);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.resource_block_start = rand_range(0, 100);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.number_of_resource_block = rand_range(0, 100);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.mcs_1 = rand_range(0, 31);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.cyclic_shift_2_for_drms = rand_range(0, 7);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.frequency_hopping_enabled_flag = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.frequency_hopping_bits = rand_range(0, 3);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.new_data_indication_1 = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.ue_tx_antenna_seleciton = rand_range(0, 2);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.tpc = rand_range(0, 3);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.cqi_csi_request = rand_range(0, 7);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.ul_index = rand_range(0, 3);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.dl_assignment_index = rand_range(1, 4);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.tpc_bitmap = rand_range(0, 9999);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel8.transmission_power = rand_range(0, 10000);		
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG;
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.cross_carrier_scheduling_flag = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.carrier_indicator = rand_range(0, 7);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.size_of_cqi_csi_feild = rand_range(0, 2);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.srs_flag = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.srs_request = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.resource_allocation_flag = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.resource_allocation_type = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.resource_block_coding = rand_range(0, 9999);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.mcs_2 = rand_range(0, 31);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.new_data_indication_2 = rand_range(0, 1);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.number_of_antenna_ports = rand_range(0, 2);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.tpmi = rand_range(0, 63);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.total_dci_length_including_padding = rand_range(0, 255);
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_dci_pdu_rel10.n_ul_rb = rand_range(6, 100);			
+		hi_dci0_pdus[2].epdcch_dci_pdu.epdcch_parameters_rel11.tl.tag = NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG;
+		
+		hi_dci0_pdus[3].pdu_type = NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE;
+		hi_dci0_pdus[3].mpdcch_dci_pdu.mpdcch_dci_pdu_rel13.tl.tag = NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG;
+
+		hi_dci0_pdus[4].pdu_type = NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE;
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.tl.tag = NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG;
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.ncce_index = rand_range(0, 1);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level = rand_range(1, 2);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol = rand_range(0, 4);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti = rand_range(1, 65535);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.scrambling_reinitialization_batch_index = rand_range(1, 4);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.nrs_antenna_ports_assumed_by_the_ue = rand_range(1, 2);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication = rand_range(0, 63);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.resource_assignment = rand_range(0, 7);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay = rand_range(0, 3);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs = rand_range(0, 12);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version = rand_range(0, 1);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number = rand_range(0, 7);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator = rand_range(0, 1);
+		hi_dci0_pdus[4].npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number = rand_range(0, 3);
+		
+		hi_dci0_req.hi_dci0_request_body.hi_dci0_pdu_list = hi_dci0_pdus;
+		mac->hi_dci0_req(mac, &hi_dci0_req);
+
+		uint8_t num_tx_pdus = 2;
+		nfapi_tx_request_pdu_t tx_pdus[num_tx_pdus];
+		memset(&tx_pdus, 0, sizeof(tx_pdus));
+		
+		nfapi_tx_request_t tx_req;
+		memset(&tx_req, 0, sizeof(tx_req));
+		tx_req.header.message_id = NFAPI_TX_REQUEST;
+		tx_req.header.phy_id = phy_id;
+		tx_req.sfn_sf = sfn_sf;
+		
+		tx_req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+		tx_req.tx_request_body.number_of_pdus = num_tx_pdus;
+		
+		uint32_t data[2];
+		data[0] = 0x11223344;
+		data[1] = 0x55667788;
+		
+		tx_pdus[0].pdu_length = 8;
+		tx_pdus[0].pdu_index = 1;
+		tx_pdus[0].num_segments = 2;
+		tx_pdus[0].segments[0].segment_length = 4;
+		tx_pdus[0].segments[0].segment_data = (uint8_t*)&data[0];
+		tx_pdus[0].segments[1].segment_length = 4;
+		tx_pdus[0].segments[1].segment_data = (uint8_t*)&data[1];
+		
+		tx_pdus[1].pdu_length = 8;
+		tx_pdus[1].pdu_index = 2;
+		tx_pdus[1].num_segments = 2;
+		tx_pdus[1].segments[0].segment_length = 4;
+		tx_pdus[1].segments[0].segment_data = (uint8_t*)&data[0];
+		tx_pdus[1].segments[1].segment_length = 4;
+		tx_pdus[1].segments[1].segment_data = (uint8_t*)&data[1];		
+		
+		
+		tx_req.tx_request_body.tx_pdu_list = tx_pdus;
+		mac->tx_req(mac, &tx_req);
+	}
+	
+	void generate_subframe(mac_t *mac, uint16_t phy_id, uint16_t sfn_sf)
+	{
+		mac_internal_t* instance = (mac_internal_t*)mac;
+				
+		nfapi_dl_config_request_t dl_config_req;
+		memset(&dl_config_req, 0, sizeof(dl_config_req));
+		dl_config_req.header.message_id = NFAPI_DL_CONFIG_REQUEST;
+		dl_config_req.header.phy_id = phy_id;
+		dl_config_req.sfn_sf = sfn_sf;
+
+		dl_config_req.dl_config_request_body.tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+		dl_config_req.dl_config_request_body.number_pdu = 8;
+
+		nfapi_dl_config_request_pdu_t pdus[8];
+		memset(&pdus, 0, sizeof(pdus));
+		for(int i = 0; i < 8; i++)
+		{
+			pdus[i].pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE;
+
+			pdus[i].bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG;
+			pdus[i].bch_pdu.bch_pdu_rel8.length = 42;
+			pdus[i].bch_pdu.bch_pdu_rel8.pdu_index = i;
+			pdus[i].bch_pdu.bch_pdu_rel8.transmission_power = 56;
+
+		}
+
+		dl_config_req.dl_config_request_body.dl_config_pdu_list = pdus;
+
+		/*
+		vendor_ext_tlv_1 ve;
+		ve.tl.tag = VENDOR_EXT_TLV_1_TAG;
+		ve.dummy = 999;
+		dl_config_req.vendor_extension = &ve.tl;
+		*/
+
+		mac->dl_config_req(mac, &dl_config_req);	
+
+
+		nfapi_ul_config_request_t ul_config_req;
+		memset(&ul_config_req, 0, sizeof(ul_config_req));
+		ul_config_req.header.message_id = NFAPI_UL_CONFIG_REQUEST;
+		ul_config_req.header.phy_id = phy_id;
+		ul_config_req.sfn_sf = sfn_sf;
+		mac->ul_config_req(mac, &ul_config_req);
+
+		nfapi_hi_dci0_request_t hi_dci0_req;
+		memset(&hi_dci0_req, 0, sizeof(hi_dci0_req));
+		hi_dci0_req.header.message_id = NFAPI_HI_DCI0_REQUEST;
+		hi_dci0_req.header.phy_id = phy_id;
+		hi_dci0_req.sfn_sf = sfn_sf;
+		mac->hi_dci0_req(mac, &hi_dci0_req);
+
+
+
+		nfapi_tx_request_t tx_req;
+		memset(&tx_req, 0, sizeof(tx_req));
+		tx_req.header.message_id = NFAPI_TX_REQUEST;
+		tx_req.header.phy_id = phy_id;
+		tx_req.sfn_sf = sfn_sf;
+
+		nfapi_tx_request_pdu_t tx_pdus[8];
+
+		tx_req.tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
+		tx_req.tx_request_body.number_of_pdus = 0;
+		tx_req.tx_request_body.tx_pdu_list = &tx_pdus[0];
+
+		mac_pdu* buff = 0;
+		int i = 0;
+		std::list<mac_pdu*> free_list;
+		do
+		{
+			buff = instance->mac->pop_rx_buffer();
+			if(buff != 0)
+			{
+				if(buff->len == 0)
+				{
+					printf("[MAC] Buffer length = 0\n");
+				}
+
+				tx_req.tx_request_body.tx_pdu_list[i].pdu_length = buff->len;
+				tx_req.tx_request_body.tx_pdu_list[i].pdu_index = i;
+				tx_req.tx_request_body.tx_pdu_list[i].num_segments = 1;
+				tx_req.tx_request_body.tx_pdu_list[i].segments[0].segment_length = buff->len;
+				tx_req.tx_request_body.tx_pdu_list[i].segments[0].segment_data = (uint8_t*)buff->buffer;
+
+				tx_req.tx_request_body.number_of_pdus++;
+				i++;
+
+				instance->mac->byte_count += buff->len;
+
+				free_list.push_back(buff);
+			}
+		}while(buff != 0 && i < 8);
+
+		mac->tx_req(mac, &tx_req);
+
+		//for(int j = 0; j < tx_req.tx_request_body.number_of_pdus; ++j)
+		for(mac_pdu* pdu : free_list)
+		{
+			instance->mac->release_mac_pdu(pdu);
+			//free(tx_req.tx_request_body.tx_pdu_list[j].segments[0].segment_data);
+		}
+	}
+	
+	void mac_subframe_ind(mac_t *mac, uint16_t phy_id, uint16_t sfn_sf)
+	{
+
+		
+		//printf("[MAC] subframe indication phyid:%d sfnsf:%d\n", phy_id, sfn_sf);
+		mac_internal_t* instance = (mac_internal_t*)mac;
+
+		if(instance->mac->tick == 1000)
+		{
+			if(instance->mac->byte_count > 0)
+			{
+				printf("[MAC] Rx rate %d bytes/sec\n", instance->mac->byte_count);
+				instance->mac->byte_count = 0;
+			}
+			instance->mac->tick = 0;
+		}
+		instance->mac->tick++;
+		
+		if(instance->mac->wireshark_test_mode)
+		{
+			generate_test_subframe(mac, phy_id, sfn_sf);
+		}
+		else
+		{
+			generate_subframe(mac, phy_id, sfn_sf);
+		}
+	}	
+	
+	void mac_harq_ind(mac_t* mac, nfapi_harq_indication_t* ind)
+	{
+	}
+	void mac_crc_ind(mac_t* mac, nfapi_crc_indication_t* ind)
+	{
+	}
+	void mac_rx_ind(mac_t* mac, nfapi_rx_indication_t* ind)
+	{
+		mac_internal_t* instance = (mac_internal_t*)mac;
+
+		for(int i = 0; i < ind->rx_indication_body.number_of_pdus; ++i)
+		{
+			uint16_t len = ind->rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length;
+			uint8_t* data = ind->rx_indication_body.rx_pdu_list[i].data;
+			//printf("[MAC] sfnsf:%d len:%d\n", ind->sfn_sf,len);
+			//
+			instance->tx_byte_count += len;
+
+			int sendto_result = sendto(instance->tx_sock, data, len, 0, (struct sockaddr*)&(instance->tx_addr), sizeof(instance->tx_addr));
+			
+			if(sendto_result < 0)
+			{
+				// error
+			}
+		}
+
+	}
+	void mac_rach_ind(mac_t* mac, nfapi_rach_indication_t* ind)
+	{
+	}
+	void mac_srs_ind(mac_t* mac, nfapi_srs_indication_t* ind)
+	{
+	}
+	void mac_sr_ind(mac_t* mac, nfapi_sr_indication_t* ind)
+	{
+	}
+	void mac_cqi_ind(mac_t* mac, nfapi_cqi_indication_t* ind)
+	{
+	}
+	void mac_lbt_dl_ind(mac_t* mac, nfapi_lbt_dl_indication_t* ind)
+	{
+	}
+	void mac_nb_harq_ind(mac_t* mac, nfapi_nb_harq_indication_t* ind)
+	{
+	}
+	void mac_nrach_ind(mac_t* mac, nfapi_nrach_indication_t* ind)
+	{
+	}
+}
+
diff --git a/nfapi/open-nFAPI/vnf_sim/src/main.cpp b/nfapi/open-nFAPI/vnf_sim/src/main.cpp
new file mode 100644
index 0000000000..5dc7161157
--- /dev/null
+++ b/nfapi/open-nFAPI/vnf_sim/src/main.cpp
@@ -0,0 +1,1525 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * 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 <stdlib.h>
+#include <stdarg.h>
+
+#include <string.h>
+#include "debug.h"
+#include <map>
+#include <vector>
+#include <list>
+#include <string>
+#include <algorithm>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+
+#include "pool.h"
+
+#include <boost/foreach.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/exception/diagnostic_information.hpp> 
+#include <boost/exception_ptr.hpp> 
+
+extern "C" {
+#include <nfapi_vnf_interface.h>
+#include <nfapi.h>
+#include "mac.h"
+
+#include <vendor_ext.h>
+
+//int vnf_main(int iPortP5, int, int);
+int start_simulated_mac(int*, int*);
+int read_xml(const char *xml_file);
+
+}
+
+static uint32_t rand_range(uint32_t min, uint32_t max)
+{
+	return ((rand() % (max + 1 - min)) + min);
+}
+
+
+void* vnf_allocate(size_t size)
+{
+	return (void*)memory_pool::allocate(size);
+}
+
+void vnf_deallocate(void* ptr)
+{
+	memory_pool::deallocate((uint8_t*)ptr);
+}
+
+
+
+class udp_data
+{
+	public:
+		bool enabled;
+		uint32_t rx_port;
+		uint32_t tx_port;
+		std::string tx_addr;
+};
+
+
+class phy_info
+{
+	public:
+
+		uint16_t index;
+		uint16_t id;
+
+		std::vector<uint16_t> rfs;
+		std::vector<uint16_t> excluded_rfs;
+
+		int remote_port;
+		std::string remote_addr;
+
+		uint16_t earfcn;
+
+};
+
+class rf_info
+{
+	public:
+
+		uint16_t index;
+		uint16_t band;
+};
+
+class pnf_info
+{
+	public:
+
+		std::vector<phy_info> phys;
+		std::vector<rf_info> rfs;
+};
+
+class vnf_p7_info
+{
+	public:
+
+		vnf_p7_info()
+			: thread_started(false), 
+			  config(nfapi_vnf_p7_config_create(), 
+				     [] (nfapi_vnf_p7_config_t* f) { nfapi_vnf_p7_config_destory(f); }),
+			  mac(0)
+		{
+			local_port = 0;
+			
+			timing_window = 0;
+			periodic_timing_enabled = 0;
+			aperiodic_timing_enabled = 0;
+			periodic_timing_period = 0;
+			
+			//config = nfapi_vnf_p7_config_create();
+		}
+		
+		vnf_p7_info(const vnf_p7_info& other)  = default;
+		
+		vnf_p7_info(vnf_p7_info&& other) = default;
+		
+		vnf_p7_info& operator=(const vnf_p7_info&) = default;
+		
+		vnf_p7_info& operator=(vnf_p7_info&&) = default;
+		
+		
+		
+		virtual	~vnf_p7_info()
+		{
+			//NFAPI_TRACE(NFAPI_TRACE_INFO, "*** vnf_p7_info delete ***\n");
+			
+			//nfapi_vnf_p7_config_destory(config);
+			
+			// should we delete the mac?
+		}
+		
+
+		int local_port;
+		std::string local_addr;
+
+		unsigned timing_window;
+		unsigned periodic_timing_enabled;
+		unsigned aperiodic_timing_enabled;
+		unsigned periodic_timing_period;
+
+		// This is not really the right place if we have multiple PHY, 
+		// should be part of the phy struct
+		udp_data udp;
+
+		bool thread_started;
+
+		//nfapi_vnf_p7_config_t* config;
+		std::shared_ptr<nfapi_vnf_p7_config_t> config;
+
+		mac_t* mac;
+
+
+};
+
+class vnf_info
+{
+	public:
+	
+		uint8_t wireshark_test_mode;
+
+		std::map<uint16_t, pnf_info> pnfs;
+
+		std::vector<vnf_p7_info> p7_vnfs;
+		
+};
+
+
+/// maybe these should be in the mac file...
+int phy_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t *end, void** ve, nfapi_p7_codec_config_t* codec)
+{
+	(void)tl;
+	(void)ppReadPackedMessage;
+	(void)ve;
+	return -1;
+}
+
+int phy_pack_vendor_extension_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* codec)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "phy_pack_vendor_extension_tlv\n");
+
+	nfapi_tl_t* tlv = (nfapi_tl_t*)ve;
+	switch(tlv->tag)
+	{
+		case VENDOR_EXT_TLV_1_TAG:
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_1\n");
+				vendor_ext_tlv_1* ve = (vendor_ext_tlv_1*)tlv;
+				if(!push32(ve->dummy, ppWritePackedMsg, end))
+					return 0;
+				return 1;
+			}
+			break;
+		default:
+			return -1;
+			break;
+	}
+}
+
+int vnf_sim_pack_vendor_extension_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* codec)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_sim_pack_vendor_extension_tlv\n");
+	nfapi_tl_t* tlv = (nfapi_tl_t*)ve;
+	switch(tlv->tag)
+	{
+		case VENDOR_EXT_TLV_2_TAG:
+			{
+				//NFAPI_TRACE(NFAPI_TRACE_INFO, "Packing VENDOR_EXT_TLV_2\n");
+				vendor_ext_tlv_2* ve = (vendor_ext_tlv_2*)tlv;
+				if(!push32(ve->dummy, ppWritePackedMsg, end))
+					return 0;
+				return 1;
+			}
+			break;
+	}
+	return -1;
+}
+
+int vnf_sim_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t *end, void** ve, nfapi_p4_p5_codec_config_t* codec)
+{
+	return -1;
+}
+
+
+
+
+int phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P7_VENDOR_EXT_IND)
+	{
+		vendor_ext_p7_ind* req = (vendor_ext_p7_ind*)(header);
+		if(!pull16(ppReadPackedMessage, &req->error_code, end))
+			return 0;
+	}
+	return 1;
+}
+
+int phy_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P7_VENDOR_EXT_REQ)
+	{
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+		vendor_ext_p7_req* req = (vendor_ext_p7_req*)(header);
+		if(!(push16(req->dummy1, ppWritePackedMsg, end) &&
+			 push16(req->dummy2, ppWritePackedMsg, end)))
+			return 0;
+	}
+	return 1;
+}
+
+int vnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t* codec)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P5_VENDOR_EXT_RSP)
+	{
+		vendor_ext_p5_rsp* req = (vendor_ext_p5_rsp*)(header);
+		return(!pull16(ppReadPackedMessage, &req->error_code, end));
+	}
+	return 0;
+}
+
+int vnf_sim_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* codec)
+{
+	//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
+	if(header->message_id == P5_VENDOR_EXT_REQ)
+	{
+		vendor_ext_p5_req* req = (vendor_ext_p5_req*)(header);
+		//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s %d %d\n", __FUNCTION__, req->dummy1, req->dummy2);
+		return (!(push16(req->dummy1, ppWritePackedMsg, end) &&
+				  push16(req->dummy2, ppWritePackedMsg, end)));
+	}
+	return 0;
+}
+
+void vnf_sim_trace(nfapi_trace_level_t level, const char* message, ...)
+{
+	va_list args;
+	va_start(args, message);
+	vprintf(message, args);
+	va_end(args);
+}
+
+void mac_dl_config_req(mac_t* mac, nfapi_dl_config_request_t* req)
+{
+	vnf_p7_info* info = (vnf_p7_info*)(mac->user_data);
+
+	nfapi_vnf_p7_dl_config_req(info->config.get(), req);
+}
+
+void mac_ul_config_req(mac_t* mac, nfapi_ul_config_request_t* req)
+{
+	vnf_p7_info* info = (vnf_p7_info*)(mac->user_data);
+
+	nfapi_vnf_p7_ul_config_req(info->config.get(), req);
+}
+
+void mac_hi_dci0_req(mac_t* mac, nfapi_hi_dci0_request_t* req)
+{
+	vnf_p7_info* info = (vnf_p7_info*)(mac->user_data);
+
+	nfapi_vnf_p7_hi_dci0_req(info->config.get(), req);
+}
+
+void mac_tx_req(mac_t* mac, nfapi_tx_request_t* req)
+{
+	vnf_p7_info* info = (vnf_p7_info*)(mac->user_data);
+
+	nfapi_vnf_p7_tx_req(info->config.get(), req);
+}
+
+int phy_subframe_indication(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn_sf)
+{
+	//printf("[VNF_SIM] subframe indication %d\n", sfn_sf);
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_subframe_ind(p7_vnf->mac, phy_id, sfn_sf);
+	return 0;
+}
+int phy_harq_indication(struct nfapi_vnf_p7_config* config, nfapi_harq_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_harq_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_crc_indication(struct nfapi_vnf_p7_config* config, nfapi_crc_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_crc_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_rx_indication(struct nfapi_vnf_p7_config* config, nfapi_rx_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_rx_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_rach_indication(struct nfapi_vnf_p7_config* config, nfapi_rach_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_rach_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_srs_indication(struct nfapi_vnf_p7_config* config, nfapi_srs_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_srs_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_sr_indication(struct nfapi_vnf_p7_config* config, nfapi_sr_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_sr_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_cqi_indication(struct nfapi_vnf_p7_config* config, nfapi_cqi_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_cqi_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_lbt_dl_indication(struct nfapi_vnf_p7_config* config, nfapi_lbt_dl_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_lbt_dl_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_nb_harq_indication(struct nfapi_vnf_p7_config* config, nfapi_nb_harq_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_nb_harq_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_nrach_indication(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind)
+{
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
+	mac_nrach_ind(p7_vnf->mac, ind);
+	return 1;
+}
+int phy_vendor_ext(struct nfapi_vnf_p7_config* config, nfapi_p7_message_header_t* msg)
+{
+	if(msg->message_id == P7_VENDOR_EXT_IND)
+	{
+		//vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)msg;
+		//printf("[VNF_SIM] vendor_ext (error_code:%d)\n", ind->error_code);
+	}
+	else
+	{
+		printf("[VNF_SIM] unknown %d\n", msg->message_id);
+	}
+	return 0;
+}
+nfapi_p7_message_header_t* phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t* msg_size)
+{
+	if(message_id == P7_VENDOR_EXT_IND)
+	{
+		*msg_size = sizeof(vendor_ext_p7_ind);
+		return (nfapi_p7_message_header_t*)malloc(sizeof(vendor_ext_p7_ind));
+	}
+	return 0;
+}
+void phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t* header)
+{
+	free(header);
+}
+
+//static pthread_t vnf_start_pthread;
+static pthread_t vnf_p7_start_pthread;
+void* vnf_p7_start_thread(void *ptr)
+{
+  printf("%s()\n", __FUNCTION__);
+
+  //std::shared_ptr<nfapi_vnf_p7_config> config = std::shared_ptr<nfapi_vnf_p7_config>(ptr);
+  nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr;
+
+  nfapi_vnf_p7_start(config);
+
+  return 0;
+}
+
+void set_thread_priority(int priority)
+{
+	//printf("%s(priority:%d)\n", __FUNCTION__, priority);
+	
+	pthread_attr_t ptAttr;
+	
+	struct sched_param schedParam;
+	schedParam.__sched_priority = priority; //79;
+	if(sched_setscheduler(0, SCHED_RR, &schedParam) != 0)
+	{
+		printf("Failed to set scheduler to SCHED_RR\n");
+	}
+
+	if(pthread_attr_setschedpolicy(&ptAttr, SCHED_RR) != 0)
+	{
+		printf("Failed to set pthread sched policy SCHED_RR\n");
+	}
+
+	pthread_attr_setinheritsched(&ptAttr, PTHREAD_EXPLICIT_SCHED);
+
+	struct sched_param thread_params;
+	thread_params.sched_priority = 20;
+	if(pthread_attr_setschedparam(&ptAttr, &thread_params) != 0)
+	{
+		printf("failed to set sched param\n");
+	}
+}
+
+void* vnf_p7_thread_start(void* ptr)
+{
+  printf("%s()\n", __FUNCTION__);
+
+	set_thread_priority(79);
+
+	vnf_p7_info* p7_vnf = (vnf_p7_info*)ptr;
+
+	p7_vnf->config->port = p7_vnf->local_port;
+	p7_vnf->config->subframe_indication = &phy_subframe_indication;
+	p7_vnf->config->harq_indication = &phy_harq_indication;
+	p7_vnf->config->crc_indication = &phy_crc_indication;
+	p7_vnf->config->rx_indication = &phy_rx_indication;
+	p7_vnf->config->rach_indication = &phy_rach_indication;
+	p7_vnf->config->srs_indication = &phy_srs_indication;
+	p7_vnf->config->sr_indication = &phy_sr_indication;
+	p7_vnf->config->cqi_indication = &phy_cqi_indication;
+	p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication;
+	p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication;
+	p7_vnf->config->nrach_indication = &phy_nrach_indication;
+	p7_vnf->config->malloc = &vnf_allocate;
+	p7_vnf->config->free = &vnf_deallocate;
+
+	p7_vnf->config->trace = &vnf_sim_trace;
+
+	p7_vnf->config->vendor_ext = &phy_vendor_ext;
+	p7_vnf->config->user_data = p7_vnf;
+
+	p7_vnf->mac->user_data = p7_vnf;
+
+	p7_vnf->config->codec_config.unpack_p7_vendor_extension = &phy_unpack_p7_vendor_extension;
+	p7_vnf->config->codec_config.pack_p7_vendor_extension = &phy_pack_p7_vendor_extension;
+	p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &phy_unpack_vendor_extension_tlv;
+	p7_vnf->config->codec_config.pack_vendor_extension_tlv = &phy_pack_vendor_extension_tlv;
+	p7_vnf->config->codec_config.allocate = &vnf_allocate;
+	p7_vnf->config->codec_config.deallocate = &vnf_deallocate;
+
+	p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext;
+	p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext;
+
+        printf("[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__);
+        pthread_create(&vnf_p7_start_pthread, NULL, &vnf_p7_start_thread, p7_vnf->config.get());
+
+	return 0;
+}
+
+int pnf_connection_indication_cb(nfapi_vnf_config_t* config, int p5_idx)
+{
+	printf("[VNF_SIM] pnf connection indication idx:%d\n", p5_idx);
+
+	pnf_info pnf;
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+	vnf->pnfs.insert(std::pair<uint16_t, pnf_info>(p5_idx, pnf));
+
+	nfapi_pnf_param_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_PNF_PARAM_REQUEST;
+	nfapi_vnf_pnf_param_req(config, p5_idx, &req);
+	return 0;
+}
+int pnf_disconnection_indication_cb(nfapi_vnf_config_t* config, int p5_idx)
+{
+	printf("[VNF_SIM] pnf disconnection indication idx:%d\n", p5_idx);
+
+	
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+	auto find_result = vnf->pnfs.find(p5_idx);
+	
+	if(find_result != vnf->pnfs.end())
+	{
+		pnf_info& pnf = find_result->second;
+
+		for(phy_info& phy : pnf.phys)
+		{
+			vnf_p7_info& p7_vnf = vnf->p7_vnfs[0];
+			nfapi_vnf_p7_del_pnf((p7_vnf.config.get()), phy.id);
+		}
+	}
+
+	return 0;
+}
+
+int pnf_param_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_response_t* resp)
+{
+	printf("[VNF_SIM] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code);
+
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+
+	auto find_result = vnf->pnfs.find(p5_idx);
+	if(find_result != vnf->pnfs.end())
+	{
+		pnf_info& pnf = find_result->second;
+
+		for(int i = 0; i < resp->pnf_phy.number_of_phys; ++i)
+		{
+			phy_info phy;
+			phy.index = resp->pnf_phy.phy[i].phy_config_index;
+
+			printf("[VNF_SIM] (PHY:%d) phy_config_idx:%d\n", i, resp->pnf_phy.phy[i].phy_config_index);
+
+			nfapi_vnf_allocate_phy(config, p5_idx, &(phy.id));
+
+
+
+			for(int j = 0; j < resp->pnf_phy.phy[i].number_of_rfs; ++j)
+			{
+				printf("[VNF_SIM] (PHY:%d) (RF%d) %d\n", i, j, resp->pnf_phy.phy[i].rf_config[j].rf_config_index);
+				phy.rfs.push_back(resp->pnf_phy.phy[i].rf_config[j].rf_config_index);
+			}
+
+
+			pnf.phys.push_back(phy);
+		}
+		for(int i = 0; i < resp->pnf_rf.number_of_rfs; ++i)
+		{
+			rf_info rf;
+			rf.index = resp->pnf_rf.rf[i].rf_config_index;
+
+			printf("[VNF_SIM] (RF:%d) rf_config_idx:%d\n", i, resp->pnf_rf.rf[i].rf_config_index);
+
+			pnf.rfs.push_back(rf);
+		}
+
+		nfapi_pnf_config_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
+
+		req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
+		req.pnf_phy_rf_config.number_phy_rf_config_info = pnf.phys.size();
+
+		for(unsigned i = 0; i < pnf.phys.size(); ++i)
+		{
+			req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf.phys[i].id;
+			req.pnf_phy_rf_config.phy_rf_config[i].phy_config_index = pnf.phys[i].index;
+			req.pnf_phy_rf_config.phy_rf_config[i].rf_config_index = pnf.phys[i].rfs[0];
+		}
+
+
+		nfapi_vnf_pnf_config_req(config, p5_idx, &req);
+	}
+	return 0;
+}
+
+int pnf_config_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* resp)
+{
+	printf("[VNF_SIM] pnf config response idx:%d\n", p5_idx);
+	
+	if(1)
+	{
+		vnf_info* vnf = (vnf_info*)(config->user_data);
+		auto find_result = vnf->pnfs.find(p5_idx);
+		if(find_result != vnf->pnfs.end())
+		{
+			//pnf_info& pnf = find_result->second;
+
+			nfapi_pnf_start_request_t req;
+			memset(&req, 0, sizeof(req));
+			req.header.message_id = NFAPI_PNF_START_REQUEST;
+			nfapi_vnf_pnf_start_req(config, p5_idx, &req);
+		}
+	}
+	else
+	{
+		// Rather than send the pnf_start_request we will demonstrate
+		// sending a vendor extention message. The start request will be
+		// send when the vendor extension response is received 
+
+		//vnf_info* vnf = (vnf_info*)(config->user_data);
+		vendor_ext_p5_req req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = P5_VENDOR_EXT_REQ;
+		req.dummy1 = 45;
+		req.dummy2 = 1977;
+		nfapi_vnf_vendor_extension(config, p5_idx, &req.header);
+	}
+	return 0;
+}
+
+int pnf_start_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp)
+{
+	printf("[VNF_SIM] pnf start response idx:%d\n", p5_idx);
+
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+	vnf_p7_info& p7_vnf = vnf->p7_vnfs[0];
+
+	if(p7_vnf.thread_started == false)
+	{
+		pthread_t vnf_p7_thread;
+		pthread_create(&vnf_p7_thread, NULL, &vnf_p7_thread_start, &p7_vnf);
+		p7_vnf.thread_started = true;
+	}
+	else
+	{
+		// P7 thread already running. 
+	}
+
+	// start all the phys in the pnf.
+	
+	auto find_result = vnf->pnfs.find(p5_idx);
+	if(find_result != vnf->pnfs.end())
+	{
+		pnf_info& pnf = find_result->second;
+
+		for(unsigned i = 0; i < pnf.phys.size(); ++i)
+		{
+			pnf_info& pnf = find_result->second;
+
+			nfapi_param_request_t req;
+			memset(&req, 0, sizeof(req));
+			req.header.message_id = NFAPI_PARAM_REQUEST;
+			req.header.phy_id = pnf.phys[i].id;
+			nfapi_vnf_param_req(config, p5_idx, &req);
+		}
+	}
+
+	return 0;
+}
+int param_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* resp)
+{
+	printf("[VNF_SIM] param response idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id);
+
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+
+	auto find_result = vnf->pnfs.find(p5_idx);
+	if(find_result != vnf->pnfs.end())
+	{
+		pnf_info& pnf = find_result->second;
+		
+		
+		auto found = std::find_if(pnf.phys.begin(), pnf.phys.end(), [&](phy_info& item)
+								  { return item.id == resp->header.phy_id; });
+
+		if(found != pnf.phys.end())
+		{
+			phy_info& phy = (*found);
+
+			phy.remote_port = resp->nfapi_config.p7_pnf_port.value;
+			
+			struct sockaddr_in pnf_p7_sockaddr;
+			memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4);
+
+			phy.remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr);
+
+			// for now just 1
+			vnf_p7_info& p7_vnf = vnf->p7_vnfs[0];
+
+			printf("[VNF_SIM] %d.%d pnf p7 %s:%d timing %d %d %d %d\n", p5_idx, phy.id, phy.remote_addr.c_str(), phy.remote_port, p7_vnf.timing_window, p7_vnf.periodic_timing_period, p7_vnf.aperiodic_timing_enabled, p7_vnf.periodic_timing_period);
+
+
+			nfapi_config_request_t req;
+			memset(&req, 0, sizeof(req));
+			req.header.message_id = NFAPI_CONFIG_REQUEST;
+			req.header.phy_id = phy.id;
+
+			
+			req.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NFAPI_P7_VNF_PORT_TAG;
+			req.nfapi_config.p7_vnf_port.value = p7_vnf.local_port;
+			req.num_tlv++;
+
+			req.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+			struct sockaddr_in vnf_p7_sockaddr;
+			vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf.local_addr.c_str());
+			memcpy(&(req.nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4);
+			req.num_tlv++;
+
+			req.nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG;
+			req.nfapi_config.timing_window.value = p7_vnf.timing_window;
+			req.num_tlv++;
+
+			if(p7_vnf.periodic_timing_enabled || p7_vnf.aperiodic_timing_enabled)
+			{
+				req.nfapi_config.timing_info_mode.tl.tag = NFAPI_NFAPI_TIMING_INFO_MODE_TAG;
+				req.nfapi_config.timing_info_mode.value = (p7_vnf.aperiodic_timing_enabled << 1) | (p7_vnf.periodic_timing_enabled);
+				req.num_tlv++;
+
+				if(p7_vnf.periodic_timing_enabled)
+				{
+					req.nfapi_config.timing_info_period.tl.tag = NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG;
+					req.nfapi_config.timing_info_period.value = p7_vnf.periodic_timing_period;
+					req.num_tlv++;
+				}
+			}
+
+			req.nfapi_config.earfcn.tl.tag = NFAPI_NFAPI_EARFCN_TAG;
+			req.nfapi_config.earfcn.value = phy.earfcn;
+			req.num_tlv++;
+			
+			
+			if(1)
+			{
+				// Poplate all tlv for wireshark testing
+				req.subframe_config.duplex_mode.tl.tag = NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG;
+				req.num_tlv++;
+				
+				req.subframe_config.pcfich_power_offset.tl.tag = NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG;
+				req.num_tlv++;
+				req.subframe_config.pb.tl.tag = NFAPI_SUBFRAME_CONFIG_PB_TAG;
+				req.num_tlv++;
+				req.subframe_config.dl_cyclic_prefix_type.tl.tag = NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG;
+				req.num_tlv++;
+				req.subframe_config.ul_cyclic_prefix_type.tl.tag = NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG;
+				req.num_tlv++;
+	
+				req.rf_config.dl_channel_bandwidth.tl.tag = NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG;
+				req.num_tlv++;
+				req.rf_config.ul_channel_bandwidth.tl.tag = NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG;
+				req.num_tlv++;
+				req.rf_config.reference_signal_power.tl.tag = NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG;
+				req.num_tlv++;
+				req.rf_config.tx_antenna_ports.tl.tag = NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG;
+				req.num_tlv++;
+				req.rf_config.rx_antenna_ports.tl.tag = NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG;		
+				req.num_tlv++;
+	
+				req.phich_config.phich_resource.tl.tag = NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG;
+				req.num_tlv++;
+				req.phich_config.phich_duration.tl.tag = NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG;
+				req.num_tlv++;
+				req.phich_config.phich_power_offset.tl.tag = NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG;	
+				req.num_tlv++;
+	
+				req.sch_config.primary_synchronization_signal_epre_eprers.tl.tag = NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG;
+				req.num_tlv++;
+				req.sch_config.secondary_synchronization_signal_epre_eprers.tl.tag = NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG;
+				req.num_tlv++;
+				req.sch_config.physical_cell_id.tl.tag = NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG;				
+				req.num_tlv++;
+	
+				req.prach_config.configuration_index.tl.tag = NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG;
+				req.num_tlv++;
+				req.prach_config.root_sequence_index.tl.tag = NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG;
+				req.num_tlv++;
+				req.prach_config.zero_correlation_zone_configuration.tl.tag = NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG;
+				req.num_tlv++;
+				req.prach_config.high_speed_flag.tl.tag = NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG;
+				req.num_tlv++;
+				req.prach_config.frequency_offset.tl.tag = NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG;				
+				req.num_tlv++;
+	
+				req.pusch_config.hopping_mode.tl.tag = NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG;
+				req.num_tlv++;
+				req.pusch_config.hopping_offset.tl.tag = NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG;
+				req.num_tlv++;
+				req.pusch_config.number_of_subbands.tl.tag = NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG;
+				req.num_tlv++;
+	
+				req.pucch_config.delta_pucch_shift.tl.tag = NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG;
+				req.num_tlv++;
+				req.pucch_config.n_cqi_rb.tl.tag = NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG;
+				req.num_tlv++;
+				req.pucch_config.n_an_cs.tl.tag = NFAPI_PUCCH_CONFIG_N_AN_CS_TAG;
+				req.num_tlv++;
+				req.pucch_config.n1_pucch_an.tl.tag = NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG;
+				req.num_tlv++;
+	
+				req.srs_config.bandwidth_configuration.tl.tag = NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG;
+				req.num_tlv++;
+				req.srs_config.max_up_pts.tl.tag = NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG;
+				req.num_tlv++;
+				req.srs_config.srs_subframe_configuration.tl.tag = NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG;
+				req.num_tlv++;
+				req.srs_config.srs_acknack_srs_simultaneous_transmission.tl.tag = NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG;				
+				req.num_tlv++;
+	
+				req.uplink_reference_signal_config.uplink_rs_hopping.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG;
+				req.num_tlv++;
+				req.uplink_reference_signal_config.group_assignment.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG;
+				req.num_tlv++;
+				req.uplink_reference_signal_config.cyclic_shift_1_for_drms.tl.tag = NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG;				
+				req.num_tlv++;
+	
+				req.laa_config.ed_threshold_lbt_pdsch.tl.tag = NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG;
+				req.num_tlv++;
+				req.laa_config.ed_threshold_lbt_drs.tl.tag = NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG;
+				req.num_tlv++;
+				req.laa_config.pd_threshold.tl.tag = NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG;
+				req.num_tlv++;
+				req.laa_config.multi_carrier_type.tl.tag = NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG;
+				req.num_tlv++;
+				req.laa_config.multi_carrier_tx.tl.tag = NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG;
+				req.num_tlv++;
+				req.laa_config.multi_carrier_freeze.tl.tag = NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG;
+				req.num_tlv++;
+				req.laa_config.tx_antenna_ports_drs.tl.tag = NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG;
+				req.num_tlv++;
+				req.laa_config.tx_power_drs.tl.tag = NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG;				
+				req.num_tlv++;
+	
+				req.emtc_config.pbch_repetitions_enable_r13.tl.tag = NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_catm_root_sequence_index.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_catm_zero_correlation_zone_configuration.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_catm_high_speed_flag.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_configuration_index.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_frequency_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_starting_subframe_periodicity.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_hopping_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_0_hopping_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_configuration_index.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_frequency_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_starting_subframe_periodicity.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_hopping_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_1_hopping_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_configuration_index.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_frequency_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_starting_subframe_periodicity.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_hopping_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_2_hopping_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_configuration_index.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_frequency_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_starting_subframe_periodicity.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_hopping_enable.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG;
+				req.num_tlv++;
+				req.emtc_config.prach_ce_level_3_hopping_offset.tl.tag = NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG;
+				req.num_tlv++;
+				req.emtc_config.pucch_interval_ulhoppingconfigcommonmodea.tl.tag = NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG;
+				req.num_tlv++;
+				req.emtc_config.pucch_interval_ulhoppingconfigcommonmodeb.tl.tag = NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG;			
+				req.num_tlv++;
+				
+				req.nb_iot_config.operating_mode.tl.tag = NFAPI_NB_IOT_CONFIG_OPERATING_MODE_TAG;
+				req.nb_iot_config.operating_mode.value = rand_range(0, 3);
+				req.num_tlv++;				
+				req.nb_iot_config.anchor.tl.tag = NFAPI_NB_IOT_CONFIG_ANCHOR_TAG;
+				req.nb_iot_config.anchor.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.prb_index.tl.tag = NFAPI_NB_IOT_CONFIG_PRB_INDEX_TAG;
+				req.nb_iot_config.prb_index.value = rand_range(0, 0x1F);
+				req.num_tlv++;
+				req.nb_iot_config.control_region_size.tl.tag = NFAPI_NB_IOT_CONFIG_CONTROL_REGION_SIZE_TAG;
+				req.nb_iot_config.control_region_size.value = rand_range(1, 4);
+				req.num_tlv++;
+				req.nb_iot_config.assumed_crs_aps.tl.tag = NFAPI_NB_IOT_CONFIG_ASSUMED_CRS_APS_TAG;
+				req.nb_iot_config.assumed_crs_aps.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_enabled.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_ENABLED_TAG;
+				req.nb_iot_config.nprach_config_0_enabled.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_sf_periodicity.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SF_PERIODICITY_TAG;
+				req.nb_iot_config.nprach_config_0_sf_periodicity.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_start_time.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_START_TIME_TAG;
+				req.nb_iot_config.nprach_config_0_start_time.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_subcarrier_offset.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SUBCARRIER_OFFSET_TAG;
+				req.nb_iot_config.nprach_config_0_subcarrier_offset.value = rand_range(0, 6);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_number_of_subcarriers.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_SUBCARRIERS_TAG;
+				req.nb_iot_config.nprach_config_0_number_of_subcarriers.value = rand_range(0, 3);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_cp_length.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_CP_LENGTH_TAG;
+				req.nb_iot_config.nprach_config_0_cp_length.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_0_number_of_repetitions_per_attempt.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.nb_iot_config.nprach_config_0_number_of_repetitions_per_attempt.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_enabled.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_ENABLED_TAG;
+				req.nb_iot_config.nprach_config_1_enabled.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_sf_periodicity.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SF_PERIODICITY_TAG;
+				req.nb_iot_config.nprach_config_1_sf_periodicity.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_start_time.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_START_TIME_TAG;
+				req.nb_iot_config.nprach_config_1_start_time.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_subcarrier_offset.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SUBCARRIER_OFFSET_TAG;
+				req.nb_iot_config.nprach_config_1_subcarrier_offset.value = rand_range(0, 6);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_number_of_subcarriers.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_SUBCARRIERS_TAG;
+				req.nb_iot_config.nprach_config_1_number_of_subcarriers.value = rand_range(0, 3);				
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_cp_length.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_CP_LENGTH_TAG;
+				req.nb_iot_config.nprach_config_1_cp_length.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_1_number_of_repetitions_per_attempt.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.nb_iot_config.nprach_config_1_number_of_repetitions_per_attempt.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_enabled.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_ENABLED_TAG;
+				req.nb_iot_config.nprach_config_2_enabled.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_sf_periodicity.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SF_PERIODICITY_TAG;
+				req.nb_iot_config.nprach_config_2_sf_periodicity.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_start_time.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_START_TIME_TAG;
+				req.nb_iot_config.nprach_config_2_start_time.value = rand_range(0, 7);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_subcarrier_offset.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SUBCARRIER_OFFSET_TAG;
+				req.nb_iot_config.nprach_config_2_subcarrier_offset.value = rand_range(0, 6);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_number_of_subcarriers.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_SUBCARRIERS_TAG;
+				req.nb_iot_config.nprach_config_2_number_of_subcarriers.value = rand_range(0, 3);				
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_cp_length.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_CP_LENGTH_TAG;
+				req.nb_iot_config.nprach_config_2_cp_length.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.nprach_config_2_number_of_repetitions_per_attempt.tl.tag = NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG;
+				req.nb_iot_config.nprach_config_2_number_of_repetitions_per_attempt.value = rand_range(0, 7);				
+				req.num_tlv++;
+				req.nb_iot_config.three_tone_base_sequence.tl.tag = NFAPI_NB_IOT_CONFIG_THREE_TONE_BASE_SEQUENCE_TAG;
+				req.nb_iot_config.three_tone_base_sequence.value = rand_range(0, 0x0F);				
+				req.num_tlv++;
+				req.nb_iot_config.six_tone_base_sequence.tl.tag = NFAPI_NB_IOT_CONFIG_SIX_TONE_BASE_SEQUENCE_TAG;
+				req.nb_iot_config.six_tone_base_sequence.value = rand_range(0, 0x03);				
+				req.num_tlv++;
+				req.nb_iot_config.twelve_tone_base_sequence.tl.tag = NFAPI_NB_IOT_CONFIG_TWELVE_TONE_BASE_SEQUENCE_TAG;
+				req.nb_iot_config.twelve_tone_base_sequence.value = rand_range(0, 0x1F);				
+				req.num_tlv++;
+				req.nb_iot_config.three_tone_cyclic_shift.tl.tag = NFAPI_NB_IOT_CONFIG_THREE_TONE_CYCLIC_SHIFT_TAG;
+				req.nb_iot_config.three_tone_cyclic_shift.value = rand_range(0, 5); // what is the max
+				req.num_tlv++;
+				req.nb_iot_config.six_tone_cyclic_shift.tl.tag = NFAPI_NB_IOT_CONFIG_SIX_TONE_CYCLIC_SHIFT_TAG;
+				req.nb_iot_config.six_tone_cyclic_shift.value = rand_range(0, 5); // what is the max
+				req.num_tlv++;
+				req.nb_iot_config.dl_gap_config_enable.tl.tag = NFAPI_NB_IOT_CONFIG_DL_GAP_CONFIG_ENABLE_TAG;
+				req.nb_iot_config.dl_gap_config_enable.value = rand_range(0, 1);
+				req.num_tlv++;
+				req.nb_iot_config.dl_gap_threshold.tl.tag = NFAPI_NB_IOT_CONFIG_DL_GAP_THRESHOLD_TAG;
+				req.nb_iot_config.dl_gap_threshold.value = rand_range(0, 3);
+				req.num_tlv++;
+				req.nb_iot_config.dl_gap_periodicity.tl.tag = NFAPI_NB_IOT_CONFIG_DL_GAP_PERIODICITY_TAG;
+				req.nb_iot_config.dl_gap_periodicity.value = rand_range(0, 3);
+				req.num_tlv++;
+				req.nb_iot_config.dl_gap_duration_coefficient.tl.tag = NFAPI_NB_IOT_CONFIG_DL_GAP_DURATION_COEFFICIENT_TAG;
+				req.nb_iot_config.dl_gap_duration_coefficient.value = rand_range(0, 3);
+				req.num_tlv++;
+				
+				req.tdd_frame_structure_config.subframe_assignment.tl.tag = NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG;
+				req.num_tlv++;
+				req.tdd_frame_structure_config.special_subframe_patterns.tl.tag = NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG;		
+				req.num_tlv++;
+				
+				req.l23_config.data_report_mode.tl.tag = NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG;
+				req.num_tlv++;
+				req.l23_config.sfnsf.tl.tag = NFAPI_L23_CONFIG_SFNSF_TAG;				
+				req.num_tlv++;
+			}
+
+			vendor_ext_tlv_2 ve2;
+			memset(&ve2, 0, sizeof(ve2));
+			ve2.tl.tag = VENDOR_EXT_TLV_2_TAG;
+			ve2.dummy = 2016;
+			req.vendor_extension = &ve2.tl;
+
+			nfapi_vnf_config_req(config, p5_idx, &req);
+		}
+		else
+		{
+			printf("[VNF_SIM] param response failed to find pnf %d phy %d\n", p5_idx, resp->header.phy_id);
+		}
+	}
+	else
+	{
+		printf("[VNF_SIM] param response failed to find pnf %d\n", p5_idx);
+	}
+
+	return 0;
+}
+
+int config_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* resp)
+{
+	printf("[VNF_SIM] config response idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id);
+
+
+	nfapi_start_request_t req;
+	memset(&req, 0, sizeof(req));
+	req.header.message_id = NFAPI_START_REQUEST;
+	req.header.phy_id = resp->header.phy_id;
+	nfapi_vnf_start_req(config, p5_idx, &req);
+
+	return 0;
+}
+
+void test_p4_requests(nfapi_vnf_config_t* config, int p5_idx, int phy_id)
+{
+	{
+		nfapi_measurement_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_MEASUREMENT_REQUEST;
+		req.header.phy_id = phy_id;
+		
+		req.dl_rs_tx_power.tl.tag = NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG;
+		req.dl_rs_tx_power.value = 42;
+		req.received_interference_power.tl.tag = NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG;
+		req.received_interference_power.value = 42;
+		req.thermal_noise_power.tl.tag = NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG;
+		req.thermal_noise_power.value = 42;
+		
+		nfapi_vnf_measurement_req(config, p5_idx, &req);
+	}
+	{
+		nfapi_rssi_request_t lte_req;
+		memset(&lte_req, 0, sizeof(lte_req));
+		lte_req.header.message_id = NFAPI_RSSI_REQUEST;
+		lte_req.header.phy_id = phy_id;
+		
+		lte_req.rat_type = NFAPI_RAT_TYPE_LTE;
+		lte_req.lte_rssi_request.tl.tag = NFAPI_LTE_RSSI_REQUEST_TAG;
+		lte_req.lte_rssi_request.frequency_band_indicator = 2;
+		lte_req.lte_rssi_request.measurement_period = 1000;
+		lte_req.lte_rssi_request.bandwidth = 50;
+		lte_req.lte_rssi_request.timeout = 0;
+		lte_req.lte_rssi_request.number_of_earfcns = 2;
+		lte_req.lte_rssi_request.earfcn[0] = 389;
+		lte_req.lte_rssi_request.earfcn[1] = 123;
+		
+		nfapi_vnf_rssi_request(config, p5_idx, &lte_req);
+		
+		nfapi_rssi_request_t utran_req;
+		memset(&utran_req, 0, sizeof(utran_req));
+		utran_req.header.message_id = NFAPI_RSSI_REQUEST;
+		utran_req.header.phy_id = phy_id;
+		
+		utran_req.rat_type = NFAPI_RAT_TYPE_UTRAN;
+		utran_req.utran_rssi_request.tl.tag = NFAPI_UTRAN_RSSI_REQUEST_TAG;
+		utran_req.utran_rssi_request.frequency_band_indicator = 2;
+		utran_req.utran_rssi_request.measurement_period = 1000;
+		utran_req.utran_rssi_request.timeout = 0;
+		utran_req.utran_rssi_request.number_of_uarfcns = 2;
+		utran_req.utran_rssi_request.uarfcn[0] = 2348;
+		utran_req.utran_rssi_request.uarfcn[1] = 52;
+		
+		nfapi_vnf_rssi_request(config, p5_idx, &utran_req);		
+		
+		
+		nfapi_rssi_request_t geran_req;
+		memset(&geran_req, 0, sizeof(geran_req));
+		geran_req.header.message_id = NFAPI_RSSI_REQUEST;
+		geran_req.header.phy_id = phy_id;
+		
+		geran_req.rat_type = NFAPI_RAT_TYPE_GERAN;
+		geran_req.geran_rssi_request.tl.tag = NFAPI_GERAN_RSSI_REQUEST_TAG;
+		geran_req.geran_rssi_request.frequency_band_indicator = 2;
+		geran_req.geran_rssi_request.measurement_period = 1000;
+		geran_req.geran_rssi_request.timeout = 0;
+		geran_req.geran_rssi_request.number_of_arfcns = 1;
+		geran_req.geran_rssi_request.arfcn[0].arfcn = 34;
+		geran_req.geran_rssi_request.arfcn[0].direction = 0;
+		
+		nfapi_vnf_rssi_request(config, p5_idx, &geran_req);		
+	}
+	{
+		nfapi_cell_search_request_t lte_req;
+		memset(&lte_req, 0, sizeof(lte_req));
+		lte_req.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+		lte_req.header.phy_id = phy_id;		
+		
+		lte_req.rat_type = NFAPI_RAT_TYPE_LTE;
+		lte_req.lte_cell_search_request.tl.tag = NFAPI_LTE_CELL_SEARCH_REQUEST_TAG;
+		lte_req.lte_cell_search_request.earfcn = 1234;
+		lte_req.lte_cell_search_request.measurement_bandwidth = 50;
+		lte_req.lte_cell_search_request.exhaustive_search = 1;
+		lte_req.lte_cell_search_request.timeout = 1000;
+		lte_req.lte_cell_search_request.number_of_pci = 1;
+		lte_req.lte_cell_search_request.pci[0] = 234;
+		
+		nfapi_vnf_cell_search_request(config, p5_idx, &lte_req);
+		
+		nfapi_cell_search_request_t utran_req;
+		memset(&utran_req, 0, sizeof(utran_req));
+		utran_req.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+		utran_req.header.phy_id = phy_id;		
+		
+		utran_req.rat_type = NFAPI_RAT_TYPE_UTRAN;
+		utran_req.utran_cell_search_request.tl.tag = NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG;
+		utran_req.utran_cell_search_request.uarfcn = 1234;
+		utran_req.utran_cell_search_request.exhaustive_search = 0;
+		utran_req.utran_cell_search_request.timeout = 1000;
+		utran_req.utran_cell_search_request.number_of_psc = 1;
+		utran_req.utran_cell_search_request.psc[0] = 234;
+		
+		nfapi_vnf_cell_search_request(config, p5_idx, &utran_req);		
+		
+		nfapi_cell_search_request_t geran_req;
+		memset(&geran_req, 0, sizeof(geran_req));
+		geran_req.header.message_id = NFAPI_CELL_SEARCH_REQUEST;
+		geran_req.header.phy_id = phy_id;		
+		
+		geran_req.rat_type = NFAPI_RAT_TYPE_GERAN;
+		geran_req.geran_cell_search_request.tl.tag = NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG;
+		geran_req.geran_cell_search_request.timeout = 1000;
+		geran_req.geran_cell_search_request.number_of_arfcn = 1;
+		geran_req.geran_cell_search_request.arfcn[0] = 8765;
+		
+		nfapi_vnf_cell_search_request(config, p5_idx, &geran_req);				
+	}
+	{
+		nfapi_broadcast_detect_request_t lte_req;
+		memset(&lte_req, 0, sizeof(lte_req));
+		lte_req.header.message_id = NFAPI_BROADCAST_DETECT_REQUEST;
+		lte_req.header.phy_id = phy_id;		
+		
+		lte_req.rat_type = NFAPI_RAT_TYPE_LTE;
+		lte_req.lte_broadcast_detect_request.tl.tag = NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG;
+		lte_req.lte_broadcast_detect_request.earfcn = 1234;
+		lte_req.lte_broadcast_detect_request.pci = 50;
+		lte_req.lte_broadcast_detect_request.timeout = 1000;
+		
+		lte_req.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+		lte_req.pnf_cell_search_state.length = 3;
+		
+		nfapi_vnf_broadcast_detect_request(config, p5_idx, &lte_req);
+		
+		nfapi_broadcast_detect_request_t utran_req;
+		memset(&utran_req, 0, sizeof(utran_req));
+		utran_req.header.message_id = NFAPI_BROADCAST_DETECT_REQUEST;
+		utran_req.header.phy_id = phy_id;		
+		
+		utran_req.rat_type = NFAPI_RAT_TYPE_LTE;
+		utran_req.utran_broadcast_detect_request.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG;
+		utran_req.utran_broadcast_detect_request.uarfcn = 1234;
+		utran_req.utran_broadcast_detect_request.psc = 50;
+		utran_req.utran_broadcast_detect_request.timeout = 1000;
+		
+		utran_req.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
+		utran_req.pnf_cell_search_state.length = 3;
+		
+		nfapi_vnf_broadcast_detect_request(config, p5_idx, &utran_req);		
+	}
+	{
+		nfapi_system_information_schedule_request_t lte_req;
+		memset(&lte_req, 0, sizeof(lte_req));
+		lte_req.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST;
+		lte_req.header.phy_id = phy_id;		
+		
+		lte_req.rat_type = NFAPI_RAT_TYPE_LTE;
+		lte_req.lte_system_information_schedule_request.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG;
+		lte_req.lte_system_information_schedule_request.earfcn = 1234;
+		lte_req.lte_system_information_schedule_request.pci = 50;
+		lte_req.lte_system_information_schedule_request.downlink_channel_bandwidth = 100;
+		lte_req.lte_system_information_schedule_request.phich_configuration = 3;
+		lte_req.lte_system_information_schedule_request.number_of_tx_antenna = 2;
+		lte_req.lte_system_information_schedule_request.retry_count = 4;
+		lte_req.lte_system_information_schedule_request.timeout = 1000;
+		
+		lte_req.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
+		lte_req.pnf_cell_broadcast_state.length = 3;
+		
+		nfapi_vnf_system_information_schedule_request(config, p5_idx, &lte_req);
+	}
+	{
+		nfapi_system_information_request_t lte_req;
+		memset(&lte_req, 0, sizeof(lte_req));
+		lte_req.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+		lte_req.header.phy_id = phy_id;		
+		
+		lte_req.rat_type = NFAPI_RAT_TYPE_LTE;		
+		lte_req.lte_system_information_request.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG;
+		lte_req.lte_system_information_request.earfcn = 1234;
+		lte_req.lte_system_information_request.pci= 456;
+		lte_req.lte_system_information_request.downlink_channel_bandwidth = 5;
+		lte_req.lte_system_information_request.phich_configuration = 2;
+		lte_req.lte_system_information_request.number_of_tx_antenna = 2;
+		lte_req.lte_system_information_request.number_of_si_periodicity = 1;
+		lte_req.lte_system_information_request.si_periodicity[0].si_periodicity = 3;
+		lte_req.lte_system_information_request.si_periodicity[0].si_index = 3;
+		lte_req.lte_system_information_request.si_window_length = 15;
+		lte_req.lte_system_information_request.timeout = 1000;
+		
+		nfapi_vnf_system_information_request(config, p5_idx, &lte_req);
+		
+		nfapi_system_information_request_t utran_req;
+		memset(&utran_req, 0, sizeof(utran_req));
+		utran_req.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+		utran_req.header.phy_id = phy_id;		
+		
+		utran_req.rat_type = NFAPI_RAT_TYPE_UTRAN;
+		utran_req.utran_system_information_request.tl.tag = NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG;
+		utran_req.utran_system_information_request.uarfcn = 1234;
+		utran_req.utran_system_information_request.psc = 456;
+		utran_req.utran_system_information_request.timeout = 1000;
+		
+		nfapi_vnf_system_information_request(config, p5_idx, &utran_req);		
+		
+		nfapi_system_information_request_t geran_req;
+		memset(&geran_req, 0, sizeof(geran_req));
+		geran_req.header.message_id = NFAPI_SYSTEM_INFORMATION_REQUEST;
+		geran_req.header.phy_id = phy_id;		
+		
+		geran_req.rat_type = NFAPI_RAT_TYPE_GERAN;
+		geran_req.geran_system_information_request.tl.tag = NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG;
+		geran_req.geran_system_information_request.arfcn = 1234;
+		geran_req.geran_system_information_request.bsic = 21;
+		geran_req.geran_system_information_request.timeout = 1000;
+		
+		nfapi_vnf_system_information_request(config, p5_idx, &geran_req);	
+	}
+	{
+		nfapi_nmm_stop_request_t req;
+		memset(&req, 0, sizeof(req));
+		req.header.message_id = NFAPI_NMM_STOP_REQUEST;
+		req.header.phy_id = phy_id;		
+		nfapi_vnf_nmm_stop_request(config, p5_idx, &req);	
+	}
+}
+
+
+int start_resp_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp)
+{
+	printf("[VNF_SIM] start response idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id);
+
+	vnf_info* vnf = (vnf_info*)(config->user_data);
+	
+	if(vnf->wireshark_test_mode)
+		test_p4_requests(config, p5_idx,  resp->header.phy_id);
+
+	auto find_result = vnf->pnfs.find(p5_idx);
+	if(find_result != vnf->pnfs.end())
+	{
+		pnf_info& pnf = find_result->second;
+		
+		
+		auto found = std::find_if(pnf.phys.begin(), pnf.phys.end(), [&](phy_info& item)
+								  { return item.id == resp->header.phy_id; });
+
+		if(found != pnf.phys.end())
+		{
+			phy_info& phy = (*found);
+
+			vnf_p7_info& p7_vnf = vnf->p7_vnfs[0];
+
+			nfapi_vnf_p7_add_pnf((p7_vnf.config.get()), phy.remote_addr.c_str(), phy.remote_port, phy.id);
+			
+
+		}
+
+
+	}
+	return 0;
+}
+
+
+nfapi_p4_p5_message_header_t* vnf_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t* msg_size)
+{
+	if(message_id == P5_VENDOR_EXT_RSP)
+	{
+		*msg_size = sizeof(vendor_ext_p5_rsp);
+		return (nfapi_p4_p5_message_header_t*)malloc(sizeof(vendor_ext_p5_rsp));
+	}
+	return 0;
+}
+void vnf_sim_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t* header)
+{
+	free(header);
+}
+int vendor_ext_cb(nfapi_vnf_config_t* config, int p5_idx, nfapi_p4_p5_message_header_t* msg)
+{
+	printf("[VNF_SIM] %s\n", __FUNCTION__);
+
+	switch(msg->message_id)
+	{
+		case P5_VENDOR_EXT_RSP:
+			{
+				vendor_ext_p5_rsp* rsp = (vendor_ext_p5_rsp*)msg;
+				printf("[VNF_SIM] P5_VENDOR_EXT_RSP error_code:%d\n", rsp->error_code);
+
+				// send the start request
+	
+				nfapi_pnf_start_request_t req;
+				memset(&req, 0, sizeof(req));
+				req.header.message_id = NFAPI_PNF_START_REQUEST;
+				nfapi_vnf_pnf_start_req(config, p5_idx, &req);
+			}
+			break;
+
+	}
+
+	return 0;
+}
+
+int read_vnf_xml(vnf_info& vnf, const char* xml_file)
+{
+	try
+	{
+		
+		std::ifstream input(xml_file);
+	
+		using boost::property_tree::ptree;
+		ptree pt;
+	
+		read_xml(input, pt);
+		
+		
+	
+		for(const auto& v : pt.get_child("vnf.vnf_p7_list"))
+		{
+			if(v.first == "vnf_p7")
+			{
+				vnf_p7_info vnf_p7;
+				vnf_p7.local_port = v.second.get<unsigned>("port");
+				vnf_p7.local_addr = v.second.get<std::string>("address");
+	
+				vnf_p7.timing_window = v.second.get<unsigned>("timing_window");
+				vnf_p7.periodic_timing_enabled = v.second.get<unsigned>("periodic_timing_enabled");
+				vnf_p7.aperiodic_timing_enabled = v.second.get<unsigned>("aperiodic_timing_enabled");
+				vnf_p7.periodic_timing_period = v.second.get<unsigned>("periodic_timing_window");
+	
+				
+				boost::optional<const boost::property_tree::ptree&> d = v.second.get_child_optional("data.udp");
+				if(d.is_initialized())
+				{
+					vnf_p7.udp.enabled = true;
+					vnf_p7.udp.rx_port = d.get().get<unsigned>("rx_port");
+					vnf_p7.udp.tx_port = d.get().get<unsigned>("tx_port");
+					vnf_p7.udp.tx_addr = d.get().get<std::string>("tx_addr");
+				}
+				else
+				{
+					vnf_p7.udp.enabled = false;
+				}
+				
+				vnf.wireshark_test_mode = v.second.get<unsigned>("wireshark_test_mode", 0);
+	
+				vnf_p7.mac = mac_create(vnf.wireshark_test_mode);
+				vnf_p7.mac->dl_config_req = &mac_dl_config_req;
+				vnf_p7.mac->ul_config_req = &mac_ul_config_req;
+				vnf_p7.mac->hi_dci0_req = &mac_hi_dci0_req;
+				vnf_p7.mac->tx_req = &mac_tx_req;
+	
+				if(vnf_p7.udp.enabled)
+				{
+					mac_start_data(vnf_p7.mac, 
+								   vnf_p7.udp.rx_port, 
+								   vnf_p7.udp.tx_addr.c_str(), 
+								   vnf_p7.udp.tx_port);
+				}
+	
+				vnf.p7_vnfs.push_back(vnf_p7);
+			}
+		}
+	}
+	catch(std::exception& e)
+	{
+		printf("%s", e.what());
+		return -1;
+	}
+	catch(boost::exception& e)
+	{
+		printf("%s", boost::diagnostic_information(e).c_str());
+	}
+
+	struct ifaddrs *ifaddr;
+	getifaddrs(&ifaddr);
+
+
+	while(ifaddr)
+	{
+		int family = ifaddr->ifa_addr->sa_family;
+		if(family == AF_INET)
+		{
+			char host[128];
+			getnameinfo(ifaddr->ifa_addr, sizeof(sockaddr_in), host, sizeof(host),	NULL, 0, 0);
+			printf("%s\n", host);
+		}
+		ifaddr = ifaddr->ifa_next;
+	}
+	
+	return 0;
+
+}
+
+
+int main(int argc, char *argv[])
+{
+	if (argc < 3)
+	{
+		printf("Use parameters: <P5 Port> <xml config file>\n");
+		return 0;
+	}
+
+	set_thread_priority(50);
+
+	vnf_info vnf;
+
+	if(read_vnf_xml(vnf, argv[2]) < 0)
+	{
+		printf("Failed to read xml file>\n");
+		return 0;
+	}
+
+	nfapi_vnf_config_t* config = nfapi_vnf_config_create();
+
+	config->vnf_ipv4 = 1;
+	config->vnf_p5_port = atoi(argv[1]);
+	config->pnf_connection_indication = &pnf_connection_indication_cb;
+	config->pnf_disconnect_indication = &pnf_disconnection_indication_cb;
+	config->pnf_param_resp = &pnf_param_resp_cb;
+	config->pnf_config_resp = &pnf_config_resp_cb;
+	config->pnf_start_resp = &pnf_start_resp_cb;
+	config->param_resp = &param_resp_cb;
+	config->config_resp = &config_resp_cb;
+	config->start_resp = &start_resp_cb;
+	config->vendor_ext = &vendor_ext_cb;
+	
+	
+	
+	config->trace = &vnf_sim_trace;
+	
+	config->malloc = &vnf_allocate;
+	config->free = &vnf_deallocate;
+
+	config->user_data = &vnf;
+
+	config->codec_config.unpack_vendor_extension_tlv = &vnf_sim_unpack_vendor_extension_tlv;
+	config->codec_config.pack_vendor_extension_tlv = &vnf_sim_pack_vendor_extension_tlv;
+
+	config->codec_config.unpack_p4_p5_vendor_extension = &vnf_sim_unpack_p4_p5_vendor_extension;
+	config->codec_config.pack_p4_p5_vendor_extension = &vnf_sim_pack_p4_p5_vendor_extension;
+	config->allocate_p4_p5_vendor_ext = &vnf_sim_allocate_p4_p5_vendor_ext;
+	config->deallocate_p4_p5_vendor_ext = &vnf_sim_deallocate_p4_p5_vendor_ext;
+	config->codec_config.allocate = &vnf_allocate;
+	config->codec_config.deallocate = &vnf_deallocate;
+
+
+	printf("Calling nfapi_vnf_start\n");
+	return nfapi_vnf_start(config);
+}
diff --git a/nfapi/open-nFAPI/xml/pnf_phy_1_A.xml b/nfapi/open-nFAPI/xml/pnf_phy_1_A.xml
new file mode 100644
index 0000000000..45f8f46831
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/pnf_phy_1_A.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pnf>
+	<sync_mode>0</sync_mode>
+	<location_mode>0</location_mode>
+	<location_coordinates></location_coordinates>
+
+	<dl_config_timing>500</dl_config_timing>
+	<ul_config_timing>500</ul_config_timing>
+	<tx_timing>500</tx_timing>
+	<hi_dci0_timing>500</hi_dci0_timing>
+
+	<max_phys>1</max_phys>
+	<max_total_bandwidth>30</max_total_bandwidth>
+	<max_total_num_dl_layers>1</max_total_num_dl_layers>
+	<max_total_num_ul_layers>1</max_total_num_ul_layers>
+
+	<shared_bands>0</shared_bands>
+	<shared_pas>0</shared_pas>
+
+	<maximum_total_power>0</maximum_total_power>
+
+	<oui>ALPHA</oui>
+
+
+	<phys>
+		<phy>
+			<index>88</index>
+			<port>2500</port>
+			<address>192.168.1.74</address>
+
+			<duplex_mode>1</duplex_mode>
+
+			<downlink_channel_bandwidth_support>22</downlink_channel_bandwidth_support>
+			<uplink_channel_bandwidth_support>22</uplink_channel_bandwidth_support>
+
+			<number_of_dl_layers>1</number_of_dl_layers>
+			<number_of_ul_layers>1</number_of_ul_layers>
+
+			<3gpp_release_supported>31</3gpp_release_supported>
+
+			<nmm_modes_supported>0</nmm_modes_supported>
+			
+			<dl_ues_per_subframe>8</dl_ues_per_subframe>
+			<ul_ues_per_subframe>8</ul_ues_per_subframe>
+
+			<!-- todo adn the other release parameters -->
+
+			<rfs>
+				<index>0</index>
+			</rfs>
+			<excluded_rfs>
+				<index>1</index>
+			</excluded_rfs>
+
+			<data>
+				<udp>
+					<rx_port>5201</rx_port>
+					<tx_addr>192.168.1.28</tx_addr>
+					<tx_port>5200</tx_port>
+				</udp>
+			</data>
+		</phy>
+	</phys>
+	<rfs>
+		<rf>
+			<index>0</index>
+			<band>2</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+		<rf>
+			<index>1</index>
+			<band>3</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+	</rfs>
+</pnf>
diff --git a/nfapi/open-nFAPI/xml/pnf_phy_1_A_ws.xml b/nfapi/open-nFAPI/xml/pnf_phy_1_A_ws.xml
new file mode 100644
index 0000000000..5eb0284148
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/pnf_phy_1_A_ws.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pnf>
+	<wireshark_test_mode>1</wireshark_test_mode>
+	
+	<sync_mode>0</sync_mode>
+	<location_mode>0</location_mode>
+	<location_coordinates></location_coordinates>
+
+	<dl_config_timing>500</dl_config_timing>
+	<ul_config_timing>500</ul_config_timing>
+	<tx_timing>500</tx_timing>
+	<hi_dci0_timing>500</hi_dci0_timing>
+
+	<max_phys>1</max_phys>
+	<max_total_bandwidth>30</max_total_bandwidth>
+	<max_total_num_dl_layers>1</max_total_num_dl_layers>
+	<max_total_num_ul_layers>1</max_total_num_ul_layers>
+
+	<shared_bands>0</shared_bands>
+	<shared_pas>0</shared_pas>
+
+	<maximum_total_power>0</maximum_total_power>
+
+	<oui>ALPHA</oui>
+
+
+	<phys>
+		<phy>
+			<index>88</index>
+			<port>2500</port>
+			<address>127.0.0.1</address>
+
+			<duplex_mode>1</duplex_mode>
+
+			<downlink_channel_bandwidth_support>22</downlink_channel_bandwidth_support>
+			<uplink_channel_bandwidth_support>22</uplink_channel_bandwidth_support>
+
+			<number_of_dl_layers>1</number_of_dl_layers>
+			<number_of_ul_layers>1</number_of_ul_layers>
+
+			<3gpp_release_supported>31</3gpp_release_supported>
+
+			<nmm_modes_supported>0</nmm_modes_supported>
+			
+			<dl_ues_per_subframe>8</dl_ues_per_subframe>
+			<ul_ues_per_subframe>8</ul_ues_per_subframe>
+
+			<!-- todo adn the other release parameters -->
+
+			<rfs>
+				<index>0</index>
+			</rfs>
+			<excluded_rfs>
+				<index>1</index>
+			</excluded_rfs>
+
+			<data>
+				<udp>
+					<rx_port>7722</rx_port>
+					<tx_addr>127.0.0.1</tx_addr>
+					<tx_port>7733</tx_port>
+				</udp>
+			</data>
+		</phy>
+	</phys>
+	<rfs>
+		<rf>
+			<index>0</index>
+			<band>2</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+		<rf>
+			<index>1</index>
+			<band>3</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+	</rfs>
+</pnf>
diff --git a/nfapi/open-nFAPI/xml/pnf_phy_1_B.xml b/nfapi/open-nFAPI/xml/pnf_phy_1_B.xml
new file mode 100644
index 0000000000..302e1e19c5
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/pnf_phy_1_B.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pnf>
+	<sync_mode>0</sync_mode>
+	<location_mode>0</location_mode>
+	<location_coordinates></location_coordinates>
+
+	<dl_config_timing>500</dl_config_timing>
+	<ul_config_timing>500</ul_config_timing>
+	<tx_timing>500</tx_timing>
+	<hi_dci0_timing>500</hi_dci0_timing>
+
+	<max_phys>1</max_phys>
+	<max_total_bandwidth>30</max_total_bandwidth>
+	<max_total_num_dl_layers>1</max_total_num_dl_layers>
+	<max_total_num_ul_layers>1</max_total_num_ul_layers>
+
+	<shared_bands>0</shared_bands>
+	<shared_pas>0</shared_pas>
+
+	<maximum_total_power>0</maximum_total_power>
+
+	<oui>ALPHA</oui>
+
+
+	<phys>
+		<phy>
+			<index>89</index>
+			<port>2510</port>
+			<address>127.0.0.1</address>
+
+			<duplex_mode>1</duplex_mode>
+
+			<downlink_channel_bandwidth_support>22</downlink_channel_bandwidth_support>
+			<uplink_channel_bandwidth_support>22</uplink_channel_bandwidth_support>
+
+			<number_of_dl_layers>1</number_of_dl_layers>
+			<number_of_ul_layers>1</number_of_ul_layers>
+
+			<3gpp_release_supported>31</3gpp_release_supported>
+
+			<nmm_modes_supported>0</nmm_modes_supported>
+			
+			<dl_ues_per_subframe>8</dl_ues_per_subframe>
+			<ul_ues_per_subframe>8</ul_ues_per_subframe>
+
+			<!-- todo adn the other release parameters -->
+
+			<rfs>
+				<index>0</index>
+			</rfs>
+			<excluded_rfs>
+				<index>1</index>
+			</excluded_rfs>
+
+			<data>
+				<udp>
+					<rx_port>7744</rx_port>
+					<tx_addr>127.0.0.1</tx_addr>
+					<tx_port>7755</tx_port>
+				</udp>
+			</data>
+		</phy>
+	</phys>
+	<rfs>
+		<rf>
+			<index>0</index>
+			<band>2</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+		<rf>
+			<index>1</index>
+			<band>3</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+	</rfs>
+</pnf>
diff --git a/nfapi/open-nFAPI/xml/pnf_phy_2_A.xml b/nfapi/open-nFAPI/xml/pnf_phy_2_A.xml
new file mode 100644
index 0000000000..b820fa135e
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/pnf_phy_2_A.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pnf>
+	<sync_mode>0</sync_mode>
+	<location_mode>0</location_mode>
+	<location_coordinates></location_coordinates>
+
+	<dl_config_timing>500</dl_config_timing>
+	<ul_config_timing>500</ul_config_timing>
+	<tx_timing>500</tx_timing>
+	<hi_dci0_timing>500</hi_dci0_timing>
+
+	<max_phys>1</max_phys>
+	<max_total_bandwidth>30</max_total_bandwidth>
+	<max_total_num_dl_layers>1</max_total_num_dl_layers>
+	<max_total_num_ul_layers>1</max_total_num_ul_layers>
+
+	<shared_bands>0</shared_bands>
+	<shared_pas>0</shared_pas>
+
+	<maximum_total_power>0</maximum_total_power>
+
+	<oui>ALPHA</oui>
+	
+	<phys>
+		<phy>
+			<index>88</index>
+			<port>2500</port>
+			<address>127.0.0.1</address>
+
+			<duplex_mode>1</duplex_mode>
+			<downlink_channel_bandwidth_support>22</downlink_channel_bandwidth_support>
+			<uplink_channel_bandwidth_support>22</uplink_channel_bandwidth_support>
+			<number_of_dl_layers>1</number_of_dl_layers>
+			<number_of_ul_layers>1</number_of_ul_layers>
+			<3gpp_release_supported>31</3gpp_release_supported>
+			<nmm_modes_supported>0</nmm_modes_supported>
+			<dl_ues_per_subframe>8</dl_ues_per_subframe>
+			<ul_ues_per_subframe>8</ul_ues_per_subframe>
+
+			<rfs>
+				<index>0</index>
+			</rfs>
+			<excluded_rfs/>
+		</phy>
+		<phy>
+			<index>44</index>
+			<port>2600</port>
+			<address>127.0.0.1</address>
+
+			<duplex_mode>1</duplex_mode>
+			<downlink_channel_bandwidth_support>22</downlink_channel_bandwidth_support>
+			<uplink_channel_bandwidth_support>22</uplink_channel_bandwidth_support>
+			<number_of_dl_layers>1</number_of_dl_layers>
+			<number_of_ul_layers>1</number_of_ul_layers>
+			<3gpp_release_supported>31</3gpp_release_supported>
+			<nmm_modes_supported>0</nmm_modes_supported>
+			<dl_ues_per_subframe>8</dl_ues_per_subframe>
+			<ul_ues_per_subframe>8</ul_ues_per_subframe>
+
+			<rfs>
+				<index>1</index>
+			</rfs>
+			<excluded_rfs/>
+		</phy>
+	</phys>
+	<rfs>
+		<rf>
+			<index>0</index>
+			<band>2</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+		<rf>
+			<index>1</index>
+			<band>4</band>
+			<max_transmit_power>-30</max_transmit_power>
+			<min_transmit_power>-230</min_transmit_power>
+			<num_antennas_supported>2</num_antennas_supported>
+			<min_downlink_frequency>1890</min_downlink_frequency>
+			<max_downlink_frequency>1890</max_downlink_frequency>
+			<max_uplink_frequency>1890</max_uplink_frequency>
+			<min_uplink_frequency>1890</min_uplink_frequency>
+		</rf>
+	</rfs>
+</pnf>
diff --git a/nfapi/open-nFAPI/xml/vnf_A.xml b/nfapi/open-nFAPI/xml/vnf_A.xml
new file mode 100644
index 0000000000..3791239ce7
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/vnf_A.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<vnf>
+	<vnf_p7_list>
+		<vnf_p7>
+			<port>5201</port>
+			<address>192.168.1.28</address>
+			<timing_window>10</timing_window>
+			<periodic_timing_enabled>0</periodic_timing_enabled>
+			<periodic_timing_window>0</periodic_timing_window>
+			<aperiodic_timing_enabled>0</aperiodic_timing_enabled>
+
+			<data>
+				<udp>
+					<rx_port>8891</rx_port>
+					<tx_addr>192.168.1.28</tx_addr>
+					<tx_port>8892</tx_port>
+				</udp>
+			</data>
+		</vnf_p7>
+	</vnf_p7_list>
+</vnf>
diff --git a/nfapi/open-nFAPI/xml/vnf_A_ws.xml b/nfapi/open-nFAPI/xml/vnf_A_ws.xml
new file mode 100644
index 0000000000..c26adc3cfa
--- /dev/null
+++ b/nfapi/open-nFAPI/xml/vnf_A_ws.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<vnf>
+	
+	<vnf_p7_list>
+		<vnf_p7>
+			<wireshark_test_mode>1</wireshark_test_mode>
+			<port>5200</port>
+			<address>127.0.0.1</address>
+			<timing_window>10</timing_window>
+			<periodic_timing_enabled>0</periodic_timing_enabled>
+			<periodic_timing_window>0</periodic_timing_window>
+			<aperiodic_timing_enabled>0</aperiodic_timing_enabled>
+
+			<data>
+				<udp>
+					<rx_port>8891</rx_port>
+					<tx_addr>127.0.0.1</tx_addr>
+					<tx_port>8892</tx_port>
+				</udp>
+			</data>
+		</vnf_p7>
+	</vnf_p7_list>
+</vnf>
diff --git a/oaienv b/oaienv
index 2e5ce16960..f6b298debf 100644
--- a/oaienv
+++ b/oaienv
@@ -17,14 +17,3 @@ alias oait='cd $OPENAIR_TARGETS'
 alias oailte='cd $OPENAIR_TARGETS/RT/USER'
 alias oais='cd $OPENAIR_TARGETS/SIMU/USER'
 alias oaiex='cd $OPENAIR_TARGETS/SIMU/EXAMPLES'
-
-export NFAPI_DIR=${HOME}/open-nFAPI
-
-alias bld='cd $OPENAIR_HOME/cmake_targets ; ./build_oai --eNB -w USRP'
-alias b='cd $OPENAIR_HOME/cmake_targets ; ./build_oai --eNB -w USRP'
-alias run='cd $OPENAIR_HOME/cmake_targets/lte_build_oai/build'
-alias nf='cd $OPENAIR_HOME/nfapi'
-alias conf='cd $OPENAIR_HOME/targets/PROJECTS/GENERIC-LTE-EPC/CONF'
-
-alias ttracer='cd $OPENAIR_HOME/cmake_targets ; ./build_oai --eNB -x -w USRP --T-tracer'
-alias rec='cd $OPENAIR_HOME/common/utils/T/tracer ; ./record -d ../T_messages.txt -o record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG'
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
index f852235c18..cd032e688f 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
@@ -258,7 +258,7 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,uint8_t UE_id)
     max_pos = max_pos-frame_parms->ofdm_symbol_size;
 
   //#ifdef DEBUG_PHY
-  //LOG_D(PHY,"frame %d: max_pos = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,sync_pos);
+  LOG_D(PHY,"frame %d: max_pos = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,sync_pos);
   //#endif //DEBUG_PHY
 
   return max_pos - sync_pos;
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index 6ec745293f..36638f383b 100755
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -2219,11 +2219,6 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
   int Msymb2;
   int split_flag=0;
 
-  if (num_dci>0)
-  {
-    //LOG_D(PHY,"%s(num_pdcch_symbols:%d num_dci:%d dci_alloc:%p n_rnti:%04x amp:%d frame_parms:%p txdataF:%p subframe:%d)\n", __FUNCTION__, num_pdcch_symbols, num_dci, dci_alloc, n_rnti, amp, frame_parms, txdataF, subframe);
-  }
-
   switch (frame_parms->N_RB_DL) {
   case 100:
     Msymb2 = Msymb;
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index bab605b573..50ee086884 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -801,28 +801,6 @@ void generate_RIV_tables()
 //       n_tilde_PRB(0,1) = (0,2)
 
 
-void check_dlsch(char *file, int line)
-{
-  PHY_VARS_eNB *eNB = RC.eNB[0][0];
-  static char oldbuf[13*NUMBER_OF_UE_MAX+100]="";
-  char buf[13*NUMBER_OF_UE_MAX+100];
-  char *pbuf=buf;
-
-  for (int i=0; i<NUMBER_OF_UE_MAX; i++) {
-    pbuf+=sprintf(pbuf, "[%02d]:%02x:%04x ", i, eNB->dlsch[i][0]->harq_mask, eNB->dlsch[i][0]->rnti);
-  }
-
-  int diff_size = memcmp(oldbuf, buf, strlen(buf));
-  
-  if (diff_size!=0)
-  {
-    LOG_I(PHY,"check_dlsch:%s:%d:%s\n", file, line, buf);
-    LOG_I(PHY,"check_dlsch:%s:%d:%s\n", file, line, oldbuf);
-  }
-
-  memcpy(oldbuf, buf, sizeof(buf));
-}
-
 int8_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type)
 {
   uint8_t i;
@@ -2444,8 +2422,7 @@ void fill_dci0(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
 
   void *dci_pdu = (void*)dci_alloc->dci_pdu;
 
-  if (cqi_req)
-    LOG_W(PHY,"SFN/SF:%04d%d DCI0[rnti %x cqi %d mcs %d hopping %d rballoc %x (%d,%d) ndi %d TPC %d cshift %d]\n",
+  LOG_D(PHY,"SFN/SF:%04d%d DCI0[rnti %x cqi %d mcs %d hopping %d rballoc %x (%d,%d) ndi %d TPC %d cshift %d]\n",
         frame,subframe,
         pdu->dci_pdu_rel8.rnti,cqi_req, mcs,hopping,rballoc,
         pdu->dci_pdu_rel8.resource_block_start,
@@ -2764,7 +2741,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
         break;
 
       case 25:
-        LOG_I(PHY,"DCI format0 (FDD, 5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n",
+        LOG_D(PHY,"DCI format0 (FDD, 5MHz), rnti %x (%x): hopping %d, rb_alloc %x, mcs %d, ndi %d, TPC %d, cshift %d, cqi_req %d\n",
               dci->rnti,
               ((uint32_t*)&dci->dci_pdu[0])[0],
               ((DCI0_5MHz_FDD_t *)&dci->dci_pdu[0])->hopping,
@@ -6574,7 +6551,7 @@ uint32_t pdcch_alloc2ul_frame(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, ui
   else
     ul_frame = (frame+(n>=6 ? 1 : 0));
 
-  //LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame);
+  LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame);
   return ul_frame % 1024;
 }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index c8da27bcb8..9a19b0ddaf 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -2455,9 +2455,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
         *(1+payload) = (stat_im<0) ? 1 : 2;
     } else { // insufficient energy on PUCCH so NAK
 #if defined(USRP_REC_PLAY)
-      LOG_I(PHY,"PUCCH 1a/b: NAK subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres);
+      LOG_D(PHY,"PUCCH 1a/b: NAK subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres);
 #else
-      LOG_I(PHY,"PUCCH 1a/b: subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres);
+      LOG_D(PHY,"PUCCH 1a/b: subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres);
 #endif      
       *payload = 4;  // DTX
       ((int16_t*)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re);
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index edbca69433..1b3e634e6c 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -1577,7 +1577,7 @@ unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
 #endif
   }
 
-  LOG_I(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]);
+  LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]);
 
   // Do ULSCH Decoding for data portion
 
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
index 5f05d33f60..795ed5896b 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
@@ -1192,13 +1192,6 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
     
     pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[i],
 						    ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)/correction_factor;
-    if(0)LOG_E(PHY,"rx_ulsch() i:%i drs: UE_id:%d harq_pid:%d nb_rb:%d correction_factor:%d\n",
-        i,
-        //pusch_vars->drs_ch_estimates[i],
-        UE_id,
-        harq_pid,
-        ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,
-        correction_factor);
     /*    printf("%4.4d.%d power harq_pid %d rb %2.2d TBS %2.2d (MPR_times_Ks %d correction %d)  power %d dBtimes10\n", proc->frame_rx, proc->subframe_rx, harq_pid, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, ulsch[UE_id]->harq_processes[harq_pid]->TBS,MPR_times_100Ks,correction_factor,dB_fixed_times10(pusch_vars->ulsch_power[i])); 
      */
   }
diff --git a/openair1/PHY/TOOLS/file_output.c b/openair1/PHY/TOOLS/file_output.c
index c2256707b5..1a4adb04cd 100644
--- a/openair1/PHY/TOOLS/file_output.c
+++ b/openair1/PHY/TOOLS/file_output.c
@@ -33,7 +33,7 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d
   int i;
 
 
-  //printf("Writing %d elements of type %d to %s\n",length,format,fname);
+  printf("Writing %d elements of type %d to %s\n",length,format,fname);
 
 
   if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
@@ -68,11 +68,9 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d
   case 15:
 
     for (i=0; i<length<<1; i+=(2*dec)) {
-      //fprintf(fp,"%d + j*(%d)\n",((short *)data)[i],((short *)data)[i+1]);
-      fprintf(fp,"%d,%d,",((short *)data)[i],((short *)data)[i+1]);
+      fprintf(fp,"%d + j*(%d)\n",((short *)data)[i],((short *)data)[i+1]);
 
     }
-    fprintf(fp,"\n");
 
 
     break;
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 68b7192eab..0e44a7f8bd 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -1604,8 +1604,6 @@ static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *
     return(-1);
   }
 
-  //LOG_D(PHY, "%s() name:%s instance_cnt:%u - about to decrement\n", __FUNCTION__, name, *instance_cnt);
-
   *instance_cnt=*instance_cnt-1;
 
   if (pthread_mutex_unlock(mutex) != 0) {
diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c
index 620c34b68a..d005d6cd0a 100644
--- a/openair1/SCHED/fapi_l1.c
+++ b/openair1/SCHED/fapi_l1.c
@@ -314,7 +314,7 @@ void handle_ulsch_cqi_ri_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request
   if (ulsch_harq->O_RI>1) ulsch_harq->Or2 = rel9->aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[1];
   ulsch->beta_offset_ri_times8            = to_beta_offset_ri[rel9->delta_offset_ri];
   ulsch->beta_offset_cqi_times8           = to_beta_offset_cqi[rel9->delta_offset_cqi];
-  LOG_E(PHY,"Filling ulsch_cqi_ri information for frame %d, subframe %d : O_RI %d, Or1 %d, beta_offset_cqi_times8 %d (%d)\n",
+  LOG_D(PHY,"Filling ulsch_cqi_ri information for frame %d, subframe %d : O_RI %d, Or1 %d, beta_offset_cqi_times8 %d (%d)\n",
         frame,subframe,ulsch_harq->O_RI,ulsch_harq->Or1,ulsch->beta_offset_cqi_times8,
         rel9->delta_offset_cqi);
 }
@@ -622,7 +622,6 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
   // DJP - AssertFatal(proc->subframe_tx == subframe, "Current subframe %d != NFAPI subframe %d\n",proc->subframe_tx,subframe);
   // DJP - AssertFatal(proc->subframe_tx == subframe, "Current frame %d != NFAPI frame %d\n",proc->frame_tx,frame);
 
-  uint8_t number_dci                = DL_req->dl_config_request_body.number_dci;
   uint8_t number_pdcch_ofdm_symbols = DL_req->dl_config_request_body.number_pdcch_ofdm_symbols;
 
   uint8_t number_dl_pdu             = DL_req->dl_config_request_body.number_pdu;
@@ -636,18 +635,16 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
   int i;
 
   eNB->pdcch_vars[subframe&1].num_pdcch_symbols = number_pdcch_ofdm_symbols;
-  eNB->pdcch_vars[subframe&1].num_dci           = number_dci;
+  eNB->pdcch_vars[subframe&1].num_dci           = 0;
   eNB->phich_vars[subframe&1].num_hi            = 0;
 
-  if (number_dl_pdu || TX_req->tx_request_body.number_of_pdus || number_hi_dci0_pdu || number_ul_pdu) {
-    LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SF:%04d%d DL_req:SFN/SF:%04d%d:dl_pdu:%d tx_req:SFN/SF:%04d%d:pdus:%d hi_dci0:SFN/SF:%04d%d:pdus:%d ul_cfg:SFN/SF:%04d%d:pdus:%d num_pdcch_symbols:%d\n",
+  LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SF:%04d%d DL_req:SFN/SF:%04d%d:dl_pdu:%d tx_req:SFN/SF:%04d%d:pdus:%d hi_dci0:SFN/SF:%04d%d:pdus:%d ul_cfg:SFN/SF:%04d%d:pdus:%d num_pdcch_symbols:%d\n",
         frame,subframe,
         NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),number_dl_pdu,
         NFAPI_SFNSF2SFN(TX_req->sfn_sf),NFAPI_SFNSF2SF(TX_req->sfn_sf),TX_req->tx_request_body.number_of_pdus,
         NFAPI_SFNSF2SFN(HI_DCI0_req->sfn_sf),NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf),number_hi_dci0_pdu,
         NFAPI_SFNSF2SFN(UL_req->sfn_sf),NFAPI_SFNSF2SF(UL_req->sfn_sf),number_ul_pdu, 
         eNB->pdcch_vars[subframe&1].num_pdcch_symbols);
-  }
 
   int do_oai =0;
   int dont_send =0;
diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h
index a912fa9f01..725bb31c45 100644
--- a/openair1/SCHED/fapi_l1.h
+++ b/openair1/SCHED/fapi_l1.h
@@ -48,7 +48,7 @@ void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_r
 				  nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu);
 void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
 				 nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu);
-void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,  
+void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
 			    nfapi_dl_config_request_pdu_t *dl_config_pdu,
 			    uint8_t codeword_index,
 			    uint8_t *sdu);
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 5c0b8cd7fd..db729187cb 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -271,8 +271,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
   int input_buffer_length = dlsch_harq->TBS/8;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
 
-  if (1){
-  //if (dlsch->rnti == 0x02) {//frame < 200) {
+  if (dlsch->rnti == 0x02) {//frame < 200) {
 
     LOG_D(PHY,
 	  "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", pdsch_start %d, G %d, nb_rb %"PRIu16", rb0 %x, rb1 %x, TBS %"PRIu16", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
@@ -490,17 +489,15 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   num_dci           = eNB->pdcch_vars[subframe&1].num_dci;
   //  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
   //        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
-  //LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
+  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
 
 
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);
 
   if (num_dci > 0)
-  {
-    //LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
-  }
-    
+    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
+
   //LOG_D(PHY,"Before generate_dci_top num_pdcch_symbols:%d num_dci:%d dci_alloc:dci_length:%d\n", num_pdcch_symbols, num_dci, eNB->pdcch_vars[subframe&1].dci_alloc[0].dci_length);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
@@ -640,8 +637,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,
 	   );
 
   //#ifdef DEBUG_PHY_PROC
-  if (max_preamble_energy[0]/10 > 32)
-    LOG_E(PHY,"[RAPROC] Frame %d, subframe %d : Most likely preamble %d, energy %d dB delay %d\n",
+  LOG_D(PHY,"[RAPROC] Frame %d, subframe %d : Most likely preamble %d, energy %d dB delay %d\n",
         frame,subframe,
         max_preamble[0],
         max_preamble_energy[0]/10,
@@ -699,7 +695,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,
       if ((eNB->prach_energy_counter == 100) && 
           (max_preamble_energy[0] > eNB->measurements.prach_I0+100)) {
 
-	LOG_E(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
+	LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
 	      eNB->Mod_id,
 	      eNB->CC_id,
 	      frame,
@@ -729,7 +725,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,
 	    
             if (nfapi_mode == 1) {  // If NFAPI PNF then we need to send the message to the VNF
 
-              LOG_E(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n",
+              LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n",
                   NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf),
                   eNB->preamble_list[0].preamble_rel8.timing_advance,
                   eNB->preamble_list[0].preamble_rel8.preamble,
@@ -1300,14 +1296,14 @@ void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
       }
     
       if (SR_payload == 1) {
-	LOG_E(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
+	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
 	      uci->rnti,frame,subframe);
 	
 	if (eNB->first_sr[i] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
 	  eNB->first_sr[i] = 0;
 	  eNB->dlsch[i][0]->harq_processes[0]->round=0;
 	  eNB->dlsch[i][0]->harq_processes[0]->status=SCH_IDLE;
-	  LOG_E(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
+	  LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
 		eNB->Mod_id,
 		eNB->ulsch[i]->rnti,frame,subframe);
 	}
@@ -1324,7 +1320,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
   LTE_eNB_ULSCH_t *ulsch;
   LTE_UL_eNB_HARQ_t *ulsch_harq;
-  struct timespec t_decode, t_crc,t_rx_ind,t_rx_ind_b,t_harq_a,t_harq_b,t_end;
 
   const int subframe = proc->subframe_rx;
   const int frame    = proc->frame_rx;
@@ -1354,7 +1349,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
       }
 
-      //LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
+      LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
 
       nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
 
@@ -1362,7 +1357,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
           fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
           nPRS)%12;
 
-      if(0)LOG_D(PHY,
+      LOG_D(PHY,
           "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n",
           eNB->Mod_id,harq_pid,frame,subframe,
           ulsch_harq->dci_alloc,
@@ -1385,8 +1380,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 
         stop_meas(&eNB->ulsch_demodulation_stats);
 
-        clock_gettime(CLOCK_MONOTONIC,&t_decode);
-
         start_meas(&eNB->ulsch_decoding_stats);
 
         ret = ulsch_decoding(eNB,proc,
@@ -1440,7 +1433,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 	      ulsch->Mlimit,
 	      ulsch_harq->o_ACK[0],
 	      ulsch_harq->o_ACK[1]);
-
         if (ulsch_harq->round >= 3)  {
            ulsch_harq->status  = SCH_IDLE;
            ulsch_harq->handled = 0;
@@ -1466,12 +1458,8 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
         ulsch_harq->handled = 1;
       }  // ulsch in error
       else {
-        clock_gettime(CLOCK_MONOTONIC,&t_crc);
-
 	fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC
-        clock_gettime(CLOCK_MONOTONIC,&t_rx_ind);
 	fill_rx_indication(eNB,i,frame,subframe);  // indicate SDU to MAC
-        clock_gettime(CLOCK_MONOTONIC,&t_rx_ind_b);
 
         ulsch_harq->status = SCH_IDLE;
         ulsch->harq_mask   &= ~(1 << harq_pid);
@@ -1502,9 +1490,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 #endif
         }  // ulsch not in error
 
-      clock_gettime(CLOCK_MONOTONIC,&t_harq_a);
       if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling);
-      clock_gettime(CLOCK_MONOTONIC,&t_harq_b);
 
       LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
             eNB->Mod_id,frame,subframe,
@@ -1533,15 +1519,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
             ulsch->rnti, harq_pid, ulsch->harq_mask);
     }
   }   //   for (i=0; i<NUMBER_OF_UE_MAX; i++)
-  clock_gettime(CLOCK_MONOTONIC,&t_end);
-  if (0)LOG_E(PHY,"%s() TIMING:decode:%ld.%09ld crc:%ld.%09ld rx_ind:%ld.%09ld-%ld.%09ld harq:%ld.%09ld-%ld.%09ld end:%ld.%09ld\n", __FUNCTION__, 
-      t_decode.tv_sec, t_decode.tv_nsec, 
-      t_crc.tv_sec, t_crc.tv_nsec, 
-      t_rx_ind.tv_sec, t_rx_ind.tv_nsec, 
-      t_rx_ind_b.tv_sec, t_rx_ind_b.tv_nsec, 
-      t_harq_a.tv_sec, t_harq_a.tv_nsec,
-      t_harq_b.tv_sec, t_harq_b.tv_nsec,
-      t_end.tv_sec, t_end.tv_nsec);
 }
 
 extern int oai_exit;
@@ -1769,7 +1746,7 @@ void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,
     return;
   }
 
-  LOG_I(PHY,"%s(eNB, ulsch_harq, rnti:%04x, frame:%d, subframe:%d, bundling:%d) harq_pdus:%d O_ACK:%d\n", __FUNCTION__, rnti, frame, subframe, bundling,eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,ulsch_harq->O_ACK);
+  LOG_D(PHY,"%s(eNB, ulsch_harq, rnti:%04x, frame:%d, subframe:%d, bundling:%d) harq_pdus:%d O_ACK:%d\n", __FUNCTION__, rnti, frame, subframe, bundling,eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,ulsch_harq->O_ACK);
 
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
   nfapi_harq_indication_pdu_t *pdu =   &eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs];
@@ -2038,7 +2015,7 @@ void fill_crc_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint
   //  pdu->rx_ue_information.handle                       = handle;
   pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
   pdu->rx_ue_information.rnti                         = eNB->ulsch[UE_id]->rnti;
-  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG; 
+  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
   pdu->crc_indication_rel8.crc_flag                   = crc_flag;
 
   eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs++;
@@ -2067,13 +2044,17 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 );
 
-  //LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
+  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
 
   eNB->rb_mask_ul[0]=0;
   eNB->rb_mask_ul[1]=0;
   eNB->rb_mask_ul[2]=0;
   eNB->rb_mask_ul[3]=0;
 
+  // Fix me here, these should be locked
+  eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus  = 0;
+  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0;
+
   // Call SRS first since all others depend on presence of SRS or lack thereof
   srs_procedures(eNB,proc);
 
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index ce49d72c68..d9943f03d9 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -369,16 +369,6 @@ void feptx_prec(RU_t *ru) {
     
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
 
-    //LOG_D(PHY, "%s() subframe:%d\n", __FUNCTION__, subframe);
-
-    if (0) LOG_E(PHY,"%s() run->nb_tx:%u subframe:%u fp->symbols_per_tti:%u fp->ofdm_symbol_size:%u symbols:(%d, %d), (%d,%d)\n", 
-    __FUNCTION__, ru->nb_tx, subframe, fp->symbols_per_tti, fp->ofdm_symbol_size,
-    ((short*)&eNB->common_vars.txdataF[0][1])[0],
-    ((short*)&eNB->common_vars.txdataF[0][1])[1],
-    ((short*)&eNB->common_vars.txdataF[0][2])[0],
-    ((short*)&eNB->common_vars.txdataF[0][2])[1]
-    );
-
     for (aa=0;aa<ru->nb_tx;aa++)
       memcpy((void*)ru->common.txdataF_BF[aa],
 	     (void*)&eNB->common_vars.txdataF[aa][subframe*fp->symbols_per_tti*fp->ofdm_symbol_size],
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 01872c0697..c7585521f1 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -241,22 +241,22 @@ void RCconfig_L1(void) {
 
 
   if (RC.eNB == NULL) {
-    RC.eNB                       = (PHY_VARS_eNB ***)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
+    RC.eNB                       = (PHY_VARS_eNB ***)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB**));
     LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
-    memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
+    memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB**));
     RC.nb_L1_CC = malloc((1+RC.nb_L1_inst)*sizeof(int));
   }
 
-  config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);    
+  config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);
   if (L1_ParamList.numelt > 0) {
 
     for (j = 0; j < RC.nb_L1_inst; j++) {
       RC.nb_L1_CC[j] = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr);
 
       if (RC.eNB[j] == NULL) {
-	RC.eNB[j]                       = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
+	RC.eNB[j]                       = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB*));
 	LOG_I(PHY,"RC.eNB[%d] = %p\n",j,RC.eNB[j]);
-	memset(RC.eNB[j],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
+	memset(RC.eNB[j],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB*));
       }
 
       for (i=0;i<RC.nb_L1_CC[j];i++) {
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 4d95cf6c62..f03a3961f6 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -589,19 +589,6 @@ clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP,
 
       TX_req[CC_idP].tx_request_body.number_of_pdus                 = 0;
 
-      if (0) LOG_D(MAC,"%s() SFN_SF:%d%d ZERO PDUs of TX_req:(SFN_SF:%d):%d UL_req:(SFN_SF:%d):%d HI_DCI0_req:(SFN_SF:%d):dci:%d hi:%d DL:(SFN_SF:%d):dci:%d DL:pdu:%d\n", 
-          __FUNCTION__,
-          frameP, subframeP,
-          NFAPI_SFNSF2DEC(TX_req[CC_idP].sfn_sf),
-          TX_req[CC_idP].tx_request_body.number_of_pdus,
-          NFAPI_SFNSF2DEC(UL_req[CC_idP].sfn_sf),
-          UL_req[CC_idP].ul_config_request_body.number_of_pdus,
-          NFAPI_SFNSF2DEC(HI_DCI0_req[CC_idP].sfn_sf),
-          HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_dci,
-          HI_DCI0_req[CC_idP].hi_dci0_request_body.number_of_hi,
-          NFAPI_SFNSF2DEC(DL_req[CC_idP].sfn_sf),
-          DL_req[CC_idP].dl_config_request_body.number_dci,
-          DL_req[CC_idP].dl_config_request_body.number_pdu);
     }
 }
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index 14cdb4b5f3..7b45401b06 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -70,7 +70,7 @@ extern int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req);
 
 void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset)
 {
-    *frameP    = *frameP + ((*subframeP + offset) / 10);
+    *frameP    = (*frameP + ((*subframeP + offset) / 10)) % 1024;
 
     *subframeP = ((*subframeP + offset) % 10);
 }
@@ -487,7 +487,7 @@ generate_Msg2(module_id_t module_idP, int CC_idP, frame_t frameP,
 		      "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming PDSCH\n",
 		      module_idP, frameP, subframeP);
 		ra->state = WAITMSG3;
-                LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG3\n", module_idP, frameP, subframeP);
+                LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG3\n", module_idP, frameP, subframeP);
 
 		dl_config_pdu =
 		    &dl_req->dl_config_pdu_list[dl_req->number_pdu];
@@ -553,7 +553,7 @@ generate_Msg2(module_id_t module_idP, int CC_idP, frame_t frameP,
                 mac->DL_req[CC_idP].sfn_sf = (frameP<<4)+subframeP;
                 mac->DL_req[CC_idP].header.message_id = NFAPI_DL_CONFIG_REQUEST;
 
-                LOG_E(MAC,"DL_CONFIG SFN/SF:%d/%d MESSAGE2\n", frameP, subframeP);
+                LOG_D(MAC,"DL_CONFIG SFN/SF:%d/%d MESSAGE2\n", frameP, subframeP);
 
 		// Program UL processing for Msg3, same as regular LTE
 		get_Msg3alloc(&cc[CC_idP], subframeP, frameP,
@@ -693,7 +693,7 @@ generate_Msg2(module_id_t module_idP, int CC_idP, frame_t frameP,
 			 cc[CC_idP].RAR_pdu.payload, N_RB_DL, 7);
 		add_msg3(module_idP, CC_idP, ra, frameP, subframeP);
 		ra->state = WAITMSG3;
-                LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG3\n", module_idP, frameP, subframeP);
+                LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG3\n", module_idP, frameP, subframeP);
 
 		// DL request
 		mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP;
@@ -828,7 +828,7 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
 
     dl_req        = &mac->DL_req[CC_idP];
     dl_req_body   = &dl_req->dl_config_request_body;
-    dl_config_pdu = &dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu]; 
+    dl_config_pdu = &dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu];
     N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth);
 
     UE_id = find_UE_id(module_idP, ra->rnti);
@@ -1058,7 +1058,7 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
                 mac->DL_req[CC_idP].header.message_id = NFAPI_DL_CONFIG_REQUEST;
 	
 		ra->state = WAITMSG4ACK;
-                LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG4ACK\n", module_idP, frameP, subframeP);
+                LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG4ACK\n", module_idP, frameP, subframeP);
 
 		lcid = 0;
 
@@ -1270,7 +1270,7 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
 		dl_req_body->number_pdu++;
 
 		ra->state = WAITMSG4ACK;
-                LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG4ACK\n", module_idP, frameP, subframeP);
+                LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG4ACK\n", module_idP, frameP, subframeP);
 
 		// increment Absolute subframe by 8 for Msg4 retransmission
 		LOG_D(MAC,
@@ -1575,7 +1575,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
 	      "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",
 	      module_idP, CC_idP, frameP, subframeP);
 	ra->state = IDLE;
-        LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP);
+        LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP);
 	UE_id = find_UE_id(module_idP, ra->rnti);
 	DevAssert(UE_id != -1);
 	mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].
@@ -1653,7 +1653,7 @@ initiate_ra_proc(module_id_t module_idP,
 	prach_ParametersListCE_r13 =
 	    &ext4_prach->prach_ParametersListCE_r13;
     }
-    LOG_I(MAC,
+    LOG_D(MAC,
 	  "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d  Initiating RA procedure for preamble index %d\n",
 	  module_idP, CC_id, frameP, subframeP, preamble_index);
 #ifdef Rel14
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index 777d8b6061..5b0fc58bb7 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -608,11 +608,11 @@ schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 
 	mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0], 1, module_idP, 0);	// not used in this case
 
-	//LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length);
+	LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length);
 
 	if (mib_sdu_length > 0) {
 
-	    //LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length);
+	    LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length);
 
 	    if ((frameP & 1023) < 40)
 		LOG_D(MAC,
@@ -638,7 +638,7 @@ schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
             dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST;
             dl_config_request->sfn_sf = sfn_sf;
 
-	    //LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu);
+	    LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu);
 	    // DL request
 
 	    TX_req =
@@ -695,7 +695,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 	    bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, BCCH, 1, &cc->BCCH_pdu.payload[0], 1, module_idP, 0);	// not used in this case
 
 	    if (bcch_sdu_length > 0) {
-		//LOG_D(MAC, "[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length);
+		LOG_D(MAC, "[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n", module_idP, frameP, CC_id, bcch_sdu_length);
 
 		// Allocate 4 PRBs in a random location
 		/*
@@ -786,7 +786,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 		    (module_idP, CC_id, 0, subframeP,
 		     dl_config_pdu->dci_dl_pdu.
 		     dci_dl_pdu_rel8.aggregation_level, SI_RNTI)) {
-		    //LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", frameP, subframeP);
+		    LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", frameP, subframeP);
 		    dl_req->number_dci++;
 		    dl_req->number_pdu++;
 		    dl_config_pdu =
@@ -888,7 +888,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 			  "[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n",
 			  frameP, CC_id, bcch_sdu_length, mcs);
 		} else {
-		    //LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
+		    LOG_D(MAC, "[eNB] Frame %d : Scheduling BCCH->DLSCH (FDD) for CC_id %d SI %d bytes (mcs %d, rb 3)\n", frameP, CC_id, bcch_sdu_length, mcs);
 		}
 
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 5687889e96..fe6c045fe7 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -547,7 +547,7 @@ schedule_ue_spec(module_id_t module_idP,
 	(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT);
 
     for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-	//LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id);
+	LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id);
 
 	dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
 
@@ -675,7 +675,7 @@ schedule_ue_spec(module_id_t module_idP,
 		    = 0;
 	    }
 
-	    LOG_I(MAC,
+	    LOG_D(MAC,
 		  "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n",
 		  module_idP, frameP, UE_id, CC_id, rnti, harq_pid, round,
 		  nb_available_rb, ue_sched_ctl->dl_cqi[CC_id],
@@ -761,7 +761,7 @@ schedule_ue_spec(module_id_t module_idP,
 		    case 2:
 		    case 7:
 		    default:
-                      LOG_I(MAC,"retransmission DL_REQ: rnti:%x\n",rnti);
+                      LOG_D(MAC,"retransmission DL_REQ: rnti:%x\n",rnti);
 
 			dl_config_pdu =
 			    &dl_req->dl_config_pdu_list[dl_req->
@@ -1223,8 +1223,8 @@ schedule_ue_spec(module_id_t module_idP,
 						   padding, post_padding);
 
 		    //#ifdef DEBUG_eNB_SCHEDULER
-		    if (1 || ta_update != 31) {
-			LOG_I(MAC,
+		    if (ta_update != 31) {
+			LOG_D(MAC,
 			      "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n",
 			      module_idP, frameP, UE_id, CC_id,
 			      sdu_length_total, num_sdus, sdu_lengths[0],
@@ -1553,7 +1553,7 @@ fill_DLSCH_dci(module_id_t module_idP,
 	(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN);
 
     for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-	//LOG_D(MAC, "Doing fill DCI for CC_id %d\n", CC_id);
+	LOG_D(MAC, "Doing fill DCI for CC_id %d\n", CC_id);
 
 	if (mbsfn_flagP[CC_id] > 0)
 	    continue;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 7bba9145fc..1bffb83d49 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -1036,7 +1036,7 @@ fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t * dl_config_pdu,
     dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
     dl_config_pdu->pdu_size =
 	(uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
-    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = 
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag =
       NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
     dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format =
 	NFAPI_DL_DCI_FORMAT_1A;
@@ -2030,7 +2030,7 @@ get_aggregation(uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt)
 	LOG_W(MAC, "unsupported DCI format %d\n", dci_fmt);
     }
 
-    //LOG_D(MAC, "Aggregation level %d (cqi %d, bw_index %d, format %d)\n", 1 << aggregation, cqi, bw_index, dci_fmt);
+    LOG_D(MAC, "Aggregation level %d (cqi %d, bw_index %d, format %d)\n", 1 << aggregation, cqi, bw_index, dci_fmt);
 
     return 1 << aggregation;
 }
@@ -3100,8 +3100,7 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
     int i, j, idci;
     int nCCE = 0;
 
-    if (0 && (DL_req->number_pdu || DL_req->number_dci || HI_DCI0_req->number_of_dci))
-      LOG_D(MAC,
+    LOG_D(MAC,
           "Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n",
           subframeP, test_onlyP, DL_req->number_pdu, DL_req->number_dci,
           HI_DCI0_req->number_of_dci);
@@ -3116,7 +3115,6 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 	if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
 	    && (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type ==
 		2)) {
-#if 0
 	    LOG_D(MAC,
 		  "Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
 		  idci, DL_req->number_dci + HI_DCI0_req->number_of_dci,
@@ -3125,7 +3123,6 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 		  dl_config_pdu[i].dci_dl_pdu.
 		  dci_dl_pdu_rel8.aggregation_level, nCCE, nCCE_max,
 		  DL_req->number_pdcch_ofdm_symbols);
-#endif
 
 	    if (nCCE +
 		(dl_config_pdu[i].dci_dl_pdu.
@@ -3197,16 +3194,14 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 	    nCCE +=
 		dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.
 		aggregation_level;
-	    //LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
+	    LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
 	    if (test_onlyP == 0) {
 		dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
-#if 0
 		LOG_D(MAC,
 		      "Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n",
 		      subframeP, test_onlyP,
 		      dl_config_pdu[i].dci_dl_pdu.
 		      dci_dl_pdu_rel8.aggregation_level, fCCE);
-#endif
 	    }
 	    idci++;
 	}
@@ -3293,7 +3288,7 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 
 	    // the allocation is feasible, rnti rule passes
 	    nCCE += hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level;
-	    //LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
+	    LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
 	    if (test_onlyP == 0) {
 		hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.cce_index = fCCE;
 		LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
@@ -3308,7 +3303,6 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 	if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
 	    && (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type ==
 		1)) {
-#if 0
 	    LOG_D(MAC,
 		  "Trying to allocate DL UE-SPECIFIC DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
 		  idci, DL_req->number_dci + HI_DCI0_req->number_of_dci,
@@ -3317,7 +3311,6 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 		  dl_config_pdu[i].dci_dl_pdu.
 		  dci_dl_pdu_rel8.aggregation_level, nCCE, nCCE_max,
 		  DL_req->number_pdcch_ofdm_symbols);
-#endif
 
 	    if (nCCE +
 		(dl_config_pdu[i].dci_dl_pdu.
@@ -3390,7 +3383,7 @@ allocate_CCEs(int module_idP, int CC_idP, int subframeP, int test_onlyP)
 	    nCCE +=
 		dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.
 		aggregation_level;
-	    //LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
+	    LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
 	    if (test_onlyP == 0) {
 		dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
 		LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
@@ -3566,7 +3559,6 @@ CCE_allocation_infeasible(int module_idP,
 	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level =
 		aggregation;
 	    DL_req->number_pdu++;
-#if 0
 	    LOG_D(MAC,
 		  "Subframe %d: Checking CCE feasibility format %d : (%x,%d) (%x,%d,%d)\n",
 		  subframe, format_flag, rnti, aggregation,
@@ -3574,7 +3566,6 @@ CCE_allocation_infeasible(int module_idP,
 		  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.
 		  aggregation_level,
 		  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type);
-#endif
 	    ret = allocate_CCEs(module_idP, CC_idP, subframe, 0);
 	    if (ret == -1)
 		res = TRUE;
@@ -3674,7 +3665,7 @@ extract_harq(module_id_t mod_idP, int CC_idP, int UE_id,
 
 	uint8_t harq_pid = ((10 * frameP) + subframeP + 10236) & 7;
 
-        LOG_I(MAC,"frame %d subframe %d harq_pid %d mode %d tmode[0] %d num_ack_nak %d round %d\n",frameP,subframeP,harq_pid,harq_indication_fdd->mode,tmode[0],num_ack_nak,sched_ctl->round[CC_idP][harq_pid]);
+        LOG_D(MAC,"frame %d subframe %d harq_pid %d mode %d tmode[0] %d num_ack_nak %d round %d\n",frameP,subframeP,harq_pid,harq_indication_fdd->mode,tmode[0],num_ack_nak,sched_ctl->round[CC_idP][harq_pid]);
 
 	switch (harq_indication_fdd->mode) {
 	case 0:		// Format 1a/b (10.1.2.1)
@@ -4368,7 +4359,7 @@ cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP,
 
     if (UE_id >= 0) {
 
-        LOG_E(MAC,"%s() UE_id:%d channel:%d cqi:%d\n", __FUNCTION__, UE_id, ul_cqi_information->channel, ul_cqi_information->ul_cqi);
+        LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n", __FUNCTION__, UE_id, ul_cqi_information->channel, ul_cqi_information->ul_cqi);
 
 	if (ul_cqi_information->channel == 0) {	// PUCCH
 
@@ -4476,7 +4467,7 @@ harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP,
     UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
     COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
     // extract HARQ Information
-    LOG_I(MAC,
+    LOG_D(MAC,
 	  "Frame %d, subframe %d: Received harq indication (%d) from UE %d/%x, ul_cqi %d\n",
 	  frameP, subframeP, channel, UE_id, rnti, ul_cqi);
     if (cc->tdd_Config)
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 405c7d2a75..def57639f6 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -185,7 +185,7 @@ rx_sdu(const module_id_t enb_mod_idP,
 		    maxHARQ_Msg3Tx);
 
 	LOG_D(MAC,
-	      "[eNB %d][PUSCH %d] CC_id %d Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n",
+	      "[eNB %d][PUSCH %d] CC_id %d [RAPROC Msg3] Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n",
 	      enb_mod_idP, harq_pid, CC_idP, ra[RA_id].msg3_round,
 	      current_rnti, RA_id, ul_cqi);
 
@@ -211,10 +211,8 @@ rx_sdu(const module_id_t enb_mod_idP,
 		    first_rb_ul[harq_pid];
 		ra[RA_id].msg3_round++;
 		// prepare handling of retransmission
-		ra[RA_id].Msg3_frame +=
-		    ((ra[RA_id].Msg3_subframe > 1) ? 1 : 0);
-		ra[RA_id].Msg3_subframe =
-		    (ra[RA_id].Msg3_subframe + 8) % 10;
+		ra[RA_id].Msg3_frame    = (ra[RA_id].Msg3_frame + ((ra[RA_id].Msg3_subframe > 1) ? 1 : 0)) % 1024;
+		ra[RA_id].Msg3_subframe = (ra[RA_id].Msg3_subframe + 8) % 10;
 		add_msg3(enb_mod_idP, CC_idP, &ra[RA_id], frameP,
 			 subframeP);
 	    }
@@ -1235,7 +1233,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
 
 		// this is the normalized RX power and this should be constant (regardless of mcs
 		normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
-		target_rx_power = 204;
+		target_rx_power = 178;
 
 		// this assumes accumulated tpc
 		// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index 11fd11e4b8..23d3f3bd60 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -1234,7 +1234,8 @@ dlsch_scheduler_pre_processor_reset(int module_idP,
 		break;
 	    }
 	}
-	//LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]);
+	LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",
+	      frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]);
 	MIMO_mode_indicator[CC_id][i] = 2;
     }
 }
@@ -1339,11 +1340,11 @@ ulsch_scheduler_pre_processor(module_id_t module_idP,
     UE_TEMPLATE *UE_template = 0;
     int N_RB_DL;
     int N_RB_UL;
-    //LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n");
+    LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n");
     // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB
     assign_max_mcs_min_rb(module_idP, frameP, subframeP, first_rb);
 
-    //LOG_D(MAC, "In ulsch_preprocessor: sort ue \n");
+    LOG_D(MAC, "In ulsch_preprocessor: sort ue \n");
     // sort ues
     sort_ue_ul(module_idP, frameP, subframeP);
 
@@ -1366,7 +1367,7 @@ ulsch_scheduler_pre_processor(module_id_t module_idP,
 	}
     }
 
-    //LOG_D(MAC, "In ulsch_preprocessor: step2 \n");
+    LOG_D(MAC, "In ulsch_preprocessor: step2 \n");
     // step 2: calculate the average rb per UE
     total_ue_count = 0;
     max_num_ue_to_be_scheduled = 0;
@@ -1384,11 +1385,12 @@ ulsch_scheduler_pre_processor(module_id_t module_idP,
 
 	UE_id = i;
 
-	//LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", UE_id, rnti);
+	LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", UE_id,
+	      rnti);
 	for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) {
 	    // This is the actual CC_id in the list
 	    CC_id = UE_list->ordered_ULCCids[n][UE_id];
-	    if(0)LOG_D(MAC,
+	    LOG_D(MAC,
 		  "In ulsch_preprocessor: handling UE %d/%x CCid %d\n",
 		  UE_id, rnti, CC_id);
 	    UE_template = &UE_list->UE_template[CC_id][UE_id];
@@ -1468,7 +1470,7 @@ ulsch_scheduler_pre_processor(module_id_t module_idP,
 	    }
 
 	    total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id];
-	    if(0)LOG_D(MAC,
+	    LOG_D(MAC,
 		  "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n",
 		  nb_allocated_rbs[CC_id][UE_id], UE_id, rnti, CC_id,
 		  harq_pid);
diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c
index 6402f3322f..d0b8e57558 100644
--- a/openair2/PHY_INTERFACE/IF_Module.c
+++ b/openair2/PHY_INTERFACE/IF_Module.c
@@ -75,7 +75,7 @@ void handle_sr(UL_IND_t *UL_info) {
   }
   else
   {
-    for (i=0;i<UL_info->sr_ind.sr_indication_body.number_of_srs;i++) 
+    for (i=0;i<UL_info->sr_ind.sr_indication_body.number_of_srs;i++)
       SR_indication(UL_info->module_id,
           UL_info->CC_id,
           UL_info->frame,
@@ -127,8 +127,6 @@ void handle_harq(UL_IND_t *UL_info) {
 
   int i;
 
-  //if (UL_info->harq_ind.number_of_harqs>0)
-
   if (nfapi_mode == 1 && UL_info->harq_ind.harq_indication_body.number_of_harqs>0) // PNF
   {
     //LOG_D(PHY, "UL_info->harq_ind.harq_indication_body.number_of_harqs:%d Send to VNF\n", UL_info->harq_ind.harq_indication_body.number_of_harqs);
@@ -144,7 +142,7 @@ void handle_harq(UL_IND_t *UL_info) {
   }
   else
   {
-    for (i=0;i<UL_info->harq_ind.harq_indication_body.number_of_harqs;i++) 
+    for (i=0;i<UL_info->harq_ind.harq_indication_body.number_of_harqs;i++)
       harq_indication(UL_info->module_id,
           UL_info->CC_id,
           NFAPI_SFNSF2SFN(UL_info->harq_ind.sfn_sf),
@@ -303,7 +301,7 @@ static void dump_ul(UL_IND_t *u)
 
   A("XXXX     crc_ind  %d\n", u->crc_ind.crc_indication_body.number_of_crcs);
 
-  A("XXXX     sr_ind   %d\n", u->sr_ind.number_of_srs);
+  A("XXXX     sr_ind   %d\n", u->sr_ind.sr_indication_body.number_of_srs);
 
   A("XXXX     cqi_ind  %d\n", u->cqi_ind.number_of_cqis);
       for (i = 0; i < u->cqi_ind.number_of_cqis; i++) {
@@ -544,17 +542,10 @@ void UL_indication(UL_IND_t *UL_info)
   IF_Module_t  *ifi        = if_inst[module_id];
   eNB_MAC_INST *mac        = RC.mac[module_id];
 
-  if (UL_info->rx_ind.rx_indication_body.number_of_pdus || 
-      UL_info->harq_ind.harq_indication_body.number_of_harqs ||
-      UL_info->crc_ind.crc_indication_body.number_of_crcs ||
-      UL_info->cqi_ind.number_of_cqis ||
-      UL_info->rach_ind.rach_indication_body.number_of_preambles ||
-      UL_info->sr_ind.sr_indication_body.number_of_srs) {
-    LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rx_ind:%d harqs:%d crcs:%d cqis:%d preambles:%d sr_ind:%d]\n", 
+  LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rx_ind:%d harqs:%d crcs:%d cqis:%d preambles:%d sr_ind:%d]\n",
         UL_info->frame,UL_info->subframe,
         module_id,CC_id,
         UL_info->rx_ind.rx_indication_body.number_of_pdus, UL_info->harq_ind.harq_indication_body.number_of_harqs, UL_info->crc_ind.crc_indication_body.number_of_crcs, UL_info->cqi_ind.number_of_cqis, UL_info->rach_ind.rach_indication_body.number_of_preambles, UL_info->sr_ind.sr_indication_body.number_of_srs);
-  }
 
   if (nfapi_mode != 1)
   {
@@ -570,12 +561,9 @@ void UL_indication(UL_IND_t *UL_info)
   }
 
 
-  //LOG_D(PHY,"%s() SFN_SF:%d%d About to call clear_nfapi_information()\n", __FUNCTION__, UL_info->frame, UL_info->subframe);
-
   // clear DL/UL info for new scheduling round
   clear_nfapi_information(RC.mac[module_id],CC_id,
 			  UL_info->frame,UL_info->subframe);
-  //LOG_D(PHY,"%s() SFN_SF:%d%d Returned from call clear_nfapi_information()\n", __FUNCTION__, UL_info->frame, UL_info->subframe);
 
   handle_rach(UL_info);
 
@@ -607,7 +595,7 @@ void UL_indication(UL_IND_t *UL_info)
       sched_info->DL_req      = &mac->DL_req[CC_id];
       sched_info->HI_DCI0_req = &mac->HI_DCI0_req[CC_id];
       if ((mac->common_channels[CC_id].tdd_Config==NULL) ||
-          (is_UL_sf(&mac->common_channels[CC_id],(sched_info->subframe+sf_ahead)%10)>0)) 
+          (is_UL_sf(&mac->common_channels[CC_id],(sched_info->subframe+sf_ahead)%10)>0))
         sched_info->UL_req      = &mac->UL_req[CC_id];
       else
         sched_info->UL_req      = NULL;
@@ -627,9 +615,8 @@ void UL_indication(UL_IND_t *UL_info)
         ifi->schedule_response(sched_info);
       }
 
-      if (sched_info->DL_req->dl_config_request_body.number_pdu)
-        LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu);
-    }						 
+      LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu);
+    }
   }
 }
 
diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c
index 23232f563d..3077b9ba80 100644
--- a/openair2/RRC/LITE/L2_interface.c
+++ b/openair2/RRC/LITE/L2_interface.c
@@ -147,7 +147,6 @@ mac_rrc_data_req(
         return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1);
       } // All RFN mod 8 transmit SIB2-3 in SF 5
       else if ((frameP%8) == 1) {
-      //LOG_D(RRC, "%s() frameP mod 8==1 (frameP:%d) copy into buffer SIB23 size:%d\n", __FUNCTION__, frameP, RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23);
         memcpy(&buffer_pP[0],
                RC.rrc[Mod_idP]->carrier[CC_id].SIB23,
                RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23);
@@ -197,7 +196,7 @@ mac_rrc_data_req(
 					 (void*)mib,
 					 carrier->MIB,
 					 24);
-	//LOG_D(RRC,"Encoded MIB for frame %d (%p), bits %lu\n",sfn,carrier->MIB,enc_rval.encoded);
+	LOG_D(RRC,"Encoded MIB for frame %d (%p), bits %lu\n",sfn,carrier->MIB,enc_rval.encoded);
 	buffer_pP[0]=carrier->MIB[0];
 	buffer_pP[1]=carrier->MIB[1];
 	buffer_pP[2]=carrier->MIB[2];
@@ -312,7 +311,7 @@ mac_rrc_data_req(
                RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_BR);
         return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_BR);
     }
- 
+
     if ((Srb_id & RAB_OFFSET) == BCCH_SI_BR){ // First SI message with SIB2/3
         memcpy(&buffer_pP[0],
                RC.rrc[Mod_idP]->carrier[CC_id].SIB23_BR,
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 15a60a6902..ad9b63c798 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -135,7 +135,7 @@ init_SI(
   SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext=(SystemInformationBlockType1_v1310_IEs_t *)NULL;
 #endif
 
-  LOG_E(RRC,"%s()\n\n\n\n",__FUNCTION__);
+  LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__);
 
   RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MIB = (uint8_t*) malloc16(4);
   // copy basic parameters
@@ -284,7 +284,7 @@ init_SI(
   }
 #endif
 
-  LOG_E(RRC, "About to call rrc_mac_config_req_eNB\n");
+  LOG_D(RRC, "About to call rrc_mac_config_req_eNB\n");
 
   rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id,
 			 RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId,
diff --git a/openair2/UTIL/LOG/log.c b/openair2/UTIL/LOG/log.c
index 47ff5d0fce..08672022d4 100644
--- a/openair2/UTIL/LOG/log.c
+++ b/openair2/UTIL/LOG/log.c
@@ -861,7 +861,7 @@ void nfapi_log(char *file, char *func, int line, int comp, int level, const char
 }
 
 //log record: add to a list
-void logRecord(const char *file, const char *func, int line, pthread_t thread_id, int comp,
+void logRecord(const char *file, const char *func, int line,  int comp,
                int level, const char *format, ...)
 {
   va_list    args;
@@ -876,7 +876,6 @@ void logRecord(const char *file, const char *func, int line, pthread_t thread_id
   log_params.file = strdup(file);
   log_params.func = strdup(func);
   log_params.line = line;
-  log_params.thread_id = thread_id;
   log_params.comp = comp;
   log_params.level = level;
   log_params.format = format;
@@ -915,7 +914,7 @@ void logRecord(const char *file, const char *func, int line, pthread_t thread_id
 }
 
 void logRecord_thread_safe(const char *file, const char *func,
-                           int line, pthread_t thread_id, int comp, int level, 
+                           int line,  int comp, int level,
                            int len, const char *params_string)
 {
   log_component_t *c;
@@ -967,8 +966,6 @@ void logRecord_thread_safe(const char *file, const char *func,
                             func);
     }
 
-    //total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%08lx] ", thread_id);
-
     if ((g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) )  {
       total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%s:%d]",
                             file, line);
@@ -1068,7 +1065,6 @@ void *log_thread_function(void *list)
     logRecord_thread_safe(log_params.file,
                           log_params.func,
                           log_params.line,
-                          log_params.thread_id,
                           log_params.comp,
                           log_params.level,
                           log_params.len,
@@ -1357,8 +1353,8 @@ void logRecord_mt(const char *file, const char *func, int line, int comp,
 #endif /* #if 0 */
 
 //log record, format, and print:  executed in the main thread (mt)
-void logRecord_mt(const char *file, const char *func, int line, 
-    pthread_t thread_id, int comp, int level, const char *format, ...)
+void logRecord_mt(const char *file, const char *func, int line, int comp,
+                  int level, const char *format, ...)
 {
   int len = 0;
   va_list args;
@@ -1389,7 +1385,8 @@ void logRecord_mt(const char *file, const char *func, int line,
     return;
   }
 
-  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD, VCD_FUNCTION_IN);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
+                                          VCD_FUNCTION_IN);
 
   va_start(args, format);
 
@@ -1452,16 +1449,13 @@ void logRecord_mt(const char *file, const char *func, int line,
       if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
     }
 
-    //len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%08lx]", thread_id);
-    //if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
-
     len += vsnprintf(&log_buffer[len], MAX_LOG_TOTAL - len, format, args);
     if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
     log_end = log_buffer + len;
 
     if ( (g_log->flag & FLAG_COLOR) || (c->flag & FLAG_COLOR) ) {
       len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
-          log_level_highlight_end[level]);
+                      log_level_highlight_end[level]);
       if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
     }
   }
@@ -1480,7 +1474,7 @@ void logRecord_mt(const char *file, const char *func, int line,
   }
 
 #else
-  fwrite(log_buffer, len, 1, stdout);
+    fwrite(log_buffer, len, 1, stdout);
 #endif
 
 #ifndef RTAI
diff --git a/openair2/UTIL/LOG/log.h b/openair2/UTIL/LOG/log.h
index 4cc5291774..1d795740b6 100644
--- a/openair2/UTIL/LOG/log.h
+++ b/openair2/UTIL/LOG/log.h
@@ -240,7 +240,6 @@ typedef struct LOG_params {
     const char *file;
     const char *func;
     int line;
-    pthread_t thread_id;
     int comp;
     int level;
     const char *format;
@@ -263,8 +262,8 @@ void log_set_instance_type (log_instance_type_t instance);
 #    include "log_if.h"
 /*----------------------------------------------------------------------------*/
 int  logInit (void);
-void logRecord_mt(const char *file, const char *func, int line,pthread_t thread_id, int comp, int level, const char *format, ...) __attribute__ ((format (printf, 7, 8)));
-void logRecord(const char *file, const char *func, int line, pthread_t thread_id, int comp, int level, const char *format, ...) __attribute__ ((format (printf, 7, 8)));
+void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
+void logRecord(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
 int  set_comp_log(int component, int level, int verbosity, int interval);
 int  set_log(int component, int level, int interval);
 void set_glog(int level, int verbosity);
@@ -286,15 +285,15 @@ void *log_thread_function(void * list);
 #ifdef USER_MODE
 //#define logIt(component, level, format, args...) do {logRecord(__FILE__, __FUNCTION__, __LINE__, component, level, format, ##args);} while(0);
 #ifdef LOG_NO_THREAD
-#define logIt(component, level, format, args...) logRecord_mt(__FILE__, __FUNCTION__, __LINE__, pthread_self(), component, level, format, ##args)
+#define logIt(component, level, format, args...) logRecord_mt(__FILE__, __FUNCTION__, __LINE__, component, level, format, ##args)
 #else //default
-#define logIt(component, level, format, args...) logRecord(__FILE__, __FUNCTION__, __LINE__, pthread_self(), component, level, format, ##args)
+#define logIt(component, level, format, args...) logRecord(__FILE__, __FUNCTION__, __LINE__, component, level, format, ##args)
 #endif
 #else
 #ifdef LOG_NO_THREAD
-#define logIt(component, level, format, args...) logRecord_mt(NULL, __FUNCTION__, __LINE__, pthread_self(), component, level, format, ##args)
+#define logIt(component, level, format, args...) logRecord_mt(NULL, __FUNCTION__, __LINE__, component, level, format, ##args)
 #else // default
-#define logIt(component, level, format, args...) logRecord(NULL, __FUNCTION__, __LINE__, pthread_self(), component, level, format, ##args)
+#define logIt(component, level, format, args...) logRecord(NULL, __FUNCTION__, __LINE__, component, level, format, ##args)
 #endif
 #endif
 /* @}*/
@@ -353,19 +352,6 @@ void *log_thread_function(void * list);
 #        define LOG_N(c, x...) /* */
 #        define LOG_F(c, x...) /* */
 #    else  /*DISABLE_LOG_X*/
-#if      0
-         extern log_t *g_log;
-#        define LOG_G(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_EMERG   > g_log->log_component[c].level || LOG_EMERG   > g_log->level) logIt(c, LOG_EMERG, x); } while(0)
-#        define LOG_A(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_ALERT   > g_log->log_component[c].level || LOG_ALERT   > g_log->level) logIt(c, LOG_ALERT, x); } while(0)
-#        define LOG_C(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_CRIT    > g_log->log_component[c].level || LOG_CRIT    > g_log->level) logIt(c, LOG_CRIT, x); } while(0)
-#        define LOG_E(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_ERR     > g_log->log_component[c].level || LOG_ERR     > g_log->level) logIt(c, LOG_ERR, x); } while(0)
-#        define LOG_W(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_WARNING > g_log->log_component[c].level || LOG_WARNING > g_log->level) logIt(c, LOG_WARNING, x); } while(0)
-#        define LOG_N(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_NOTICE  > g_log->log_component[c].level || LOG_NOTICE  > g_log->level) logIt(c, LOG_NOTICE, x); } while(0)
-#        define LOG_I(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_INFO    > g_log->log_component[c].level || LOG_INFO    > g_log->level) logIt(c, LOG_INFO, x); } while(0)
-#        define LOG_D(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_DEBUG   > g_log->log_component[c].level || LOG_DEBUG   > g_log->level) logIt(c, LOG_DEBUG, x); } while(0)
-#        define LOG_F(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_FILE    > g_log->log_component[c].level || LOG_FILE    > g_log->level) logIt(c, LOG_FILE, x); } while(0)
-#        define LOG_T(c, x...) do { if (g_log->log_component[c].level > g_log->level || LOG_TRACE   > g_log->log_component[c].level || LOG_TRACE   > g_log->level) logIt(c, LOG_TRACE, x); } while(0)
-#else
 #        define LOG_G(c, x...) logIt(c, LOG_EMERG, x)
 #        define LOG_A(c, x...) logIt(c, LOG_ALERT, x)
 #        define LOG_C(c, x...) logIt(c, LOG_CRIT,  x)
@@ -376,7 +362,6 @@ void *log_thread_function(void * list);
 #        define LOG_D(c, x...) logIt(c, LOG_DEBUG, x)
 #        define LOG_F(c, x...) logIt(c, LOG_FILE, x)  // log to a file, useful for the MSC chart generation
 #        define LOG_T(c, x...) logIt(c, LOG_TRACE, x)
-#        endif /* 0 */
 #    endif /*DISABLE_LOG_X*/
 #  endif /* T_TRACER */
 #else /* USER_MODE */
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 8e747e46f5..358186dca3 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -1013,6 +1013,10 @@ extern "C" {
 
             openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
 
+#if defined(USRP_REC_PLAY)
+	    std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info
+#endif
+
             LOG_I(PHY,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
 
             switch ((int)openair0_cfg[0].sample_rate) {
diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c
index 35b29e31b4..b911fbc5a4 100644
--- a/targets/COMMON/create_tasks.c
+++ b/targets/COMMON/create_tasks.c
@@ -42,7 +42,7 @@
 
 int create_tasks(uint32_t enb_nb, uint32_t ue_nb)
 {
-  LOG_E(ENB_APP, "%s(enb_nb:%d ue_nb:%d)\n", __FUNCTION__, enb_nb, ue_nb);
+  LOG_D(ENB_APP, "%s(enb_nb:%d ue_nb:%d)\n", __FUNCTION__, enb_nb, ue_nb);
 
   itti_wait_ready(1);
   if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
index 3a9276008b..ff302811e9 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
@@ -17,8 +17,7 @@ eNBs =
 
     mobile_country_code =  "208";
 
-    #mobile_network_code =  "93";
-    mobile_network_code =  "92";
+    mobile_network_code =  "93";
 
     tr_s_preference     = "local_mac"
 
@@ -37,14 +36,13 @@ eNBs =
       downlink_frequency      			      = 2685000000L;
       uplink_frequency_offset 			      = -120000000;
       Nid_cell					      = 0;
-#N_RB_DL                 			      = 25;
       N_RB_DL                 			      = 50;
       Nid_cell_mbsfn          			      = 0;
       nb_antenna_ports                                = 1;
       nb_antennas_tx          			      = 1;
       nb_antennas_rx          			      = 1;
       tx_gain                                            = 90;
-      rx_gain                                            = 115;
+      rx_gain                                            = 125;
       pbch_repetition                                 = "FALSE";
       prach_root              			      = 0;
       prach_config_index      			      = 0;
@@ -75,7 +73,7 @@ eNBs =
 
       pusch_p0_Nominal                                   = -96;
       pusch_alpha                                        = "AL1";
-      pucch_p0_Nominal                                   = -96;
+      pucch_p0_Nominal                                   = -104;
       msg3_delta_Preamble                                = 6;
       pucch_deltaF_Format1                               = "deltaF2";
       pucch_deltaF_Format1b                              = "deltaF3";
@@ -142,7 +140,7 @@ eNBs =
 
 
     ////////// MME parameters:
-    mme_ip_address      = ( { ipv4       = "192.168.1.78";
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
                               ipv6       = "192:168:30::17";
                               active     = "yes";
                               preference = "ipv4";
@@ -152,10 +150,10 @@ eNBs =
     NETWORK_INTERFACES :
     {
 
-        ENB_INTERFACE_NAME_FOR_S1_MME            = "eno1";
-        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.1.78/24";
-        ENB_INTERFACE_NAME_FOR_S1U               = "eno1";
-        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.1.74/24";
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.19/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.19/24";
         ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
     };
   }
@@ -178,33 +176,34 @@ L1s = (
 
 RUs = (
     {		  
-	local_rf       = "yes"
-	nb_tx          = 1
-	nb_rx          = 1
-	att_tx         = 0
-	att_rx         = 0;
-	bands          = [7];
-       max_pdschReferenceSignalPower = -27;
-       max_rxgain                    = 105;
-	eNB_instances  = [0];
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 125;
+         eNB_instances  = [0];
+
     }
 );  
 
      log_config :
      {
-       global_log_level                      ="debug";
+       global_log_level                      ="info";
        global_log_verbosity                  ="medium";
        hw_log_level                          ="info";
        hw_log_verbosity                      ="medium";
        phy_log_level                         ="info";
-       phy_log_verbosity                     ="low";
+       phy_log_verbosity                     ="medium";
        mac_log_level                         ="info";
-       mac_log_verbosity                     ="medium";
+       mac_log_verbosity                     ="high";
        rlc_log_level                         ="info";
-       rlc_log_verbosity                     ="high";
+       rlc_log_verbosity                     ="medium";
        pdcp_log_level                        ="info";
        pdcp_log_verbosity                    ="medium";
        rrc_log_level                         ="info";
-       rrc_log_verbosity                     ="high";
+       rrc_log_verbosity                     ="medium";
     };
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
index f2e37638ab..9393872b30 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
@@ -19,13 +19,13 @@ L1s = (
     	{
 	num_cc = 1;
 	tr_n_preference = "nfapi";
-      	local_n_if_name  = "eno1";
-      	remote_n_address = "192.168.1.28";
-    	local_n_address  = "192.168.1.74";
-    	local_n_portc    = 50000;
-    	remote_n_portc   = 50001;
-    	local_n_portd    = 50010;
-    	remote_n_portd   = 50011;
+      	local_n_if_name  = "lo";			  
+      	remote_n_address = "127.0.0.2";
+    	local_n_address  = "127.0.0.1"; 
+    	local_n_portc    = 50000;	
+        remote_n_portc   = 50001;
+        local_n_portd    = 50010;
+        remote_n_portd   = 50011;
         }  
 );
 
@@ -34,10 +34,11 @@ RUs = (
        local_rf       = "yes"
        nb_tx          = 1
        nb_rx          = 1
-       att_tx         = 90
+       att_tx         = 0
        att_rx         = 0;
        bands          = [7,38,42,43];
        max_pdschReferenceSignalPower = -27;
-       max_rxgain                    = 115;
+       max_rxgain                    = 125;
+       eNB_instances  = [0];
     }		      
-);
+);  
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
index 88aacde36b..1c9ad09141 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
@@ -17,8 +17,7 @@ eNBs =
 
     mobile_country_code =  "208";
 
-    #mobile_network_code =  "93";
-    mobile_network_code =  "92";
+    mobile_network_code =  "93";
 
     tr_s_preference     = "local_mac"
 
@@ -37,8 +36,7 @@ eNBs =
       downlink_frequency      			      = 2685000000L;
       uplink_frequency_offset 			      = -120000000;
       Nid_cell					      = 0;
-      #N_RB_DL                 			      = 50;
-      N_RB_DL                 			      = 25;
+      N_RB_DL                 			      = 50;
       Nid_cell_mbsfn          			      = 0;
       nb_antenna_ports                                = 1;
       nb_antennas_tx          			      = 1;
@@ -73,9 +71,9 @@ eNBs =
       srs_ackNackST                                      =;
       srs_MaxUpPts                                       =;*/
 
-      pusch_p0_Nominal                                   = -86;
+      pusch_p0_Nominal                                   = -96;
       pusch_alpha                                        = "AL1";
-      pucch_p0_Nominal                                   = -96;
+      pucch_p0_Nominal                                   = -104;
       msg3_delta_Preamble                                = 6;
       pucch_deltaF_Format1                               = "deltaF2";
       pucch_deltaF_Format1b                              = "deltaF3";
@@ -91,8 +89,7 @@ eNBs =
       rach_messagePowerOffsetGroupB                      = ;
       */
       rach_powerRampingStep                              = 4;
-      #rach_preambleInitialReceivedTargetPower            = -108;
-      rach_preambleInitialReceivedTargetPower            = -104;
+      rach_preambleInitialReceivedTargetPower            = -108;
       rach_preambleTransMax                              = 10;
       rach_raResponseWindowSize                          = 10;
       rach_macContentionResolutionTimer                  = 48;
@@ -143,7 +140,7 @@ eNBs =
 
 
     ////////// MME parameters:
-    mme_ip_address      = ( { ipv4       = "192.168.1.78";
+    mme_ip_address      = ( { ipv4       = "127.0.0.3";
                               ipv6       = "192:168:30::17";
                               active     = "yes";
                               preference = "ipv4";
@@ -153,23 +150,21 @@ eNBs =
     NETWORK_INTERFACES :
     {
 
-        ENB_INTERFACE_NAME_FOR_S1_MME            = "eno1";
-        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.1.28/24";
-        ENB_INTERFACE_NAME_FOR_S1U               = "eno1";
-        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.1.28/24";
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "lo";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "127.0.0.2/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "lo";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "127.0.0.5/24";
         ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
     };
-
   }
 );
 
 MACRLCs = (
 	{
 	num_cc = 1;
-      	local_s_if_name  = "eno1";			  
-      	remote_s_address = "192.168.1.74";
-    	#local_s_address  = "192.168.1.78"; 
-    	local_s_address  = "192.168.1.28"; 
+      	local_s_if_name  = "lo";			  
+      	remote_s_address = "127.0.0.1";
+    	local_s_address  = "127.0.0.2"; 
     	local_s_portc    = 50001;	
     	remote_s_portc   = 50000;
     	local_s_portd    = 50011;	
@@ -179,21 +174,20 @@ MACRLCs = (
         }  
 );
 
-     log_config :
-     {
-       global_log_level                      ="debug";
-       global_log_verbosity                  ="medium";
-       hw_log_level                          ="info";
-       hw_log_verbosity                      ="medium";
-       phy_log_level                         ="info";
-       phy_log_verbosity                     ="medium";
-       mac_log_level                         ="info";
-       mac_log_verbosity                     ="medium";
-       rlc_log_level                         ="info";
-       rlc_log_verbosity                     ="high";
-       pdcp_log_level                        ="info";
-       pdcp_log_verbosity                    ="medium";
-       rrc_log_level                         ="info";
-       rrc_log_verbosity                     ="high";
-    };
-
+log_config =
+    {
+      global_log_level                      ="info";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="info";
+      phy_log_verbosity                     ="medium";
+      mac_log_level                         ="info";
+      mac_log_verbosity                     ="high";
+      rlc_log_level                         ="info";
+      rlc_log_verbosity                     ="medium";
+      pdcp_log_level                        ="info";
+      pdcp_log_verbosity                    ="medium";
+      rrc_log_level                         ="info";
+      rrc_log_verbosity                     ="medium";
+   };
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index d50cbbb854..79973d3814 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -217,12 +217,9 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
 
   // if this is IF5 or 3GPP_eNB
   if (eNB && eNB->RU_list && eNB->RU_list[0] && eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
-    //LOG_D(PHY,"%s:%s() %u/%u Before wakeup_prach_eNB() proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
     wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
-    //LOG_D(PHY,"%s:%s() %u/%u Before wakeup_prach_eNB_br() proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
 #ifdef Rel14
     wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
-    //LOG_D(PHY,"%s:%s() %u/%u proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
 #endif
   }
 
@@ -299,8 +296,6 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
       );
 #endif
   
-      //softmodem_stats_rxtx_sf.in, softmodem_stats_rxtx_sf.diff_now, softmodem_stats_rxtx_sf.max,
-
   return(0);
 }
 
@@ -320,7 +315,6 @@ static void* eNB_thread_rxtx( void* param ) {
 
   char thread_name[100];
 
-  //LOG_D(PHY,"%s()\n", __FUNCTION__);
 
   // set default return value
   eNB_thread_rxtx_status = 0;
@@ -329,29 +323,21 @@ static void* eNB_thread_rxtx( void* param ) {
   sprintf(thread_name,"RXn_TXnp4_%d",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
   thread_top_init(thread_name,1,850000L,1000000L,2000000L);
 
-  //LOG_D(PHY,"%s() thread_name:%s\n", __FUNCTION__, thread_name);
-
   while (!oai_exit) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
 
-    //LOG_D(PHY,"%s:%s() TX:%u/%u About to wait on proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
     if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
 
-    //LOG_D(PHY,"%s:%s() TX:%u/%u - WOKEN on proc->instance_cnt_rxtx proc->instance_cnt_rxtx:%d \n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
-
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
 
     if (oai_exit) break;
 
-    //LOG_D(PHY,"%s:%s() TX:%u/%u About to rxtx()\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx);
     if (eNB->CC_id==0)
     {
       if (rxtx(eNB,proc,thread_name) < 0) break;
 
     }
 
-    //LOG_D(PHY,"%s:%s() TX:%u/%u DONE rxtx()\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx);
-
     if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
 
   } // while !oai_exit
@@ -397,9 +383,6 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
   proc->subframe_rx = subframe_rx;
 
   if (!oai_exit) {
-    //LOG_D(PHY,"eNB_top in %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n",
-	  //(void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
-
     T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
 
     proc_rxtx->subframe_rx = proc->subframe_rx;
@@ -410,7 +393,6 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
     proc_rxtx->timestamp_tx = proc->timestamp_tx;
 
     if (rxtx(eNB,proc_rxtx,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
-    //LOG_D(PHY,"eNB_top out %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n", (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
   }
 }
 
@@ -426,14 +408,9 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   int i;
   struct timespec wait;
   
-  LOG_D(PHY,"About to wake RUs\n");
-
   pthread_mutex_lock(&proc->mutex_RU);
-  LOG_D(PHY,"eNB->num_RU:%d\n", eNB->num_RU);
   for (i=0;i<eNB->num_RU;i++) {
-    LOG_D(PHY,"eNB->RU_list[%d]:%p\n",i,eNB->RU_list[i]);
     if (ru == eNB->RU_list[i]) {
-      LOG_D(PHY,"proc->RU_mask:%02x\n", proc->RU_mask);
       if ((proc->RU_mask&(1<<i)) > 0)
 	LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
 	      eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
@@ -456,19 +433,17 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
 
-#if 0
   /* accept some delay in processing - up to 5ms */
   for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
     LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->subframe_tx, proc_rxtx->instance_cnt_rxtx);
     usleep(500);
   }
   if (proc_rxtx->instance_cnt_rxtx == 0) {
-    //exit_fun( "TX thread busy" ); - DJP - this is commented out just whilst I work out what has gone wrong
+    exit_fun( "TX thread busy" );
     return(-1);
   }
-#endif
 
-  // wake up TX for subframe n+2
+  // wake up TX for subframe n+sf_ahead
   // lock the TX mutex and make sure the thread is ready
   if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
     LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
@@ -477,7 +452,6 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   }
   
   ++proc_rxtx->instance_cnt_rxtx;
-  LOG_D(PHY,"%s() %u/%u Just incremented proc->instance_cnt_rxtx:%d\n", __FUNCTION__, proc_rxtx->frame_tx, proc_rxtx->subframe_tx, proc_rxtx->instance_cnt_rxtx);
   
   // We have just received and processed the common part of a subframe, say n. 
   // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
@@ -490,8 +464,6 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   proc_rxtx->subframe_rx  = proc->subframe_rx;
   proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > (9-sf_ahead)) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
   proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + sf_ahead)%10;
-  
-  LOG_D(PHY,"Signal &proc_rxtx->cond_rxtx\n");
 
   // the thread can now be woken up
   if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
@@ -534,7 +506,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
     
   // check if we have to detect PRACH first
   if (is_prach_subframe(fp,frame,subframe)>0) { 
-    //LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
+    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
     if (proc->instance_cnt_prach == 0) {
       LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
       return;
@@ -650,7 +622,7 @@ static void* eNB_thread_prach( void* param ) {
     
     if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
 
-    //LOG_D(PHY,"Running eNB prach procedures\n");
+    LOG_D(PHY,"Running eNB prach procedures\n");
     prach_procedures(eNB
 #ifdef Rel14
 		     ,0
@@ -691,7 +663,7 @@ static void* eNB_thread_prach_br( void* param ) {
 
     if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
 
-    //LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
+    LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
     prach_procedures(eNB,1);
     
     if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
@@ -920,7 +892,7 @@ void init_transport(PHY_VARS_eNB *eNB) {
   int j;
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
 
-  LOG_E(PHY, "Initialise transport\n");
+  LOG_I(PHY, "Initialise transport\n");
 
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
     LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
@@ -999,12 +971,12 @@ void init_eNB_afterRU(void) {
       LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
       eNB->frame_parms.nb_antennas_rx       = 0;
 
-      LOG_E(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);
+      LOG_I(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);
 
       eNB->prach_vars.rxsigF[0] = (int16_t**)malloc16(64*sizeof(int16_t*));
 #ifdef Rel14
       for (int ce_level=0;ce_level<4;ce_level++) {
-        LOG_E(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
+        LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
         eNB->prach_vars_br.rxsigF[ce_level] = (int16_t**)malloc16(64*sizeof(int16_t*));
       }
 #endif
@@ -1035,7 +1007,10 @@ void init_eNB_afterRU(void) {
 
 
 
-
+      /* TODO: review this code, there is something wrong.
+       * In monolithic mode, we come here with nb_antennas_rx == 0
+       * (not tested in other modes).
+       */
       if (eNB->frame_parms.nb_antennas_rx < 1)
       {
         LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx);
@@ -1043,7 +1018,7 @@ void init_eNB_afterRU(void) {
       }
       else
       {
-        LOG_I(PHY," Delete code\n");
+        //LOG_I(PHY," Delete code\n");
       }
 
       if (eNB->frame_parms.nb_antennas_tx < 1)
@@ -1053,7 +1028,7 @@ void init_eNB_afterRU(void) {
       }
       else
       {
-        LOG_I(PHY," Delete code\n");
+        //LOG_I(PHY," Delete code\n");
       }
 
 
@@ -1066,12 +1041,9 @@ void init_eNB_afterRU(void) {
       init_transport(eNB);
       //init_precoding_weights(RC.eNB[inst][CC_id]);
     }
-    printf("RC.nb_CC[inst:%d]:%d CC_id:%d AFTER LOOP - About to init_eNB_proc\n", inst, RC.nb_CC[inst], CC_id);
     init_eNB_proc(inst);
   }
-  printf("%s() RC.nb_inst:%d AFTER LOOP\n", __FUNCTION__, RC.nb_inst);
 
-  printf("%s:%d RC.nb_RU:%d\n", __FILE__, __LINE__, RC.nb_RU);
   for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
 
     AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
@@ -1081,8 +1053,6 @@ void init_eNB_afterRU(void) {
     RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
     RC.ru[ru_id]->eNB_top             = eNB_top;
   }
-
-  LOG_I(PHY,"%s() Exitting\n", __FUNCTION__);
 }
 
 void init_eNB(int single_thread_flag,int wait_for_sync) {
diff --git a/targets/RT/USER/lte-ran.c b/targets/RT/USER/lte-ran.c
index 4f9f45df86..597ceb0654 100644
--- a/targets/RT/USER/lte-ran.c
+++ b/targets/RT/USER/lte-ran.c
@@ -1278,8 +1278,6 @@ void init_eNB_proc(int inst) {
   eNB_rxtx_proc_t *proc_rxtx;
   pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te;
 
-  printf("%s()\n", __FUNCTION__);
-
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
     LOG_I(PHY,"Initializing eNB %d CC_id %d (%s,%s),\n",inst,CC_id,eNB_functions[eNB->node_function],eNB_timing[eNB->node_timing]);
@@ -1675,15 +1673,10 @@ void init_RAN(RAN_CONTEXT *rc,eNB_func_t node_function[], eNB_timing_t node_timi
   PHY_VARS_eNB *eNB;
   int ret;
 
-  printf("%s() rc->nb_inst:%d\n", __FUNCTION__, rc->nb_inst);
-
   for (inst=0;inst<rc->nb_inst;inst++) {
-    printf("%s() rc->nb_inst:%d rc->nb_CC:%d\n", __FUNCTION__, rc->nb_inst, rc->nb_CC);
     for (CC_id=0;CC_id<rc->nb_CC;CC_id++) {
       eNB = rc->eNB[inst][CC_id]; 
-      printf("%s() rc->nb_inst:%d rc->nb_CC:%d eNB:%p rc->eNB[%d][%d]:%p\n", __FUNCTION__, rc->nb_inst, rc->nb_CC, eNB, inst, CC_id, rc->eNB[inst][CC_id]);
       if (eNB) {
-
 	eNB->node_function      = node_function[CC_id];
 	eNB->node_timing        = node_timing[CC_id];
 	eNB->abstraction_flag   = 0;
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 66cd5daffa..9f67e75b1c 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -592,7 +592,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
   uint32_t symbol_number,symbol_mask,symbol_mask_full;
   int subframe_tx,frame_tx;
 
-LOG_E(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
+  LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
   symbol_number = 0;
   symbol_mask = 0;
   symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
@@ -720,13 +720,11 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
   proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
   
-#if 0
   LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
 	ru->idx, 
 	0, 
 	(unsigned long long int)proc->timestamp_rx,
 	(int)ru->ts_offset,proc->frame_rx,proc->subframe_rx);
-#endif
 
     // dump VCD output for first RU in list
   if (ru == RC.ru[0]) {
@@ -759,6 +757,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   if (rxs != fp->samples_per_tti)
   {
     //exit_fun( "problem receiving samples" );
+    LOG_E(PHY, "problem receiving samples");
   }
 }
 
@@ -819,8 +818,8 @@ void tx_rf(RU_t *ru) {
 				      ru->nb_tx,
 				      flags);
     
-    //LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
-	  //(long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
+    LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
+	  (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
     
     
@@ -948,8 +947,6 @@ static void* ru_thread_prach( void* param ) {
 
   thread_top_init("ru_thread_prach",1,500000L,1000000L,20000000L);
 
-LOG_E(PHY,"In rach thread\n");
-
   while (RC.ru_mask>0) {
     usleep(1e6);
     LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
@@ -1117,14 +1114,14 @@ void wakeup_eNBs(RU_t *ru) {
   int i;
   PHY_VARS_eNB **eNB_list = ru->eNB_list;
 
-  //LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
+  LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
 
   if (ru->num_eNB==1 && ru->eNB_top!=0) {
     // call eNB function directly
 
     char string[20];
     sprintf(string,"Incoming RU %d",ru->idx);
-    //LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
+    LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
     ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
   }
   else {
@@ -1164,7 +1161,7 @@ static inline int wakeup_prach_ru(RU_t *ru) {
     ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
     ru->eNB_list[0]->proc.subframe_prach = ru->proc.subframe_rx;
 
-    //LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
+    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
     // the thread can now be woken up
     AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
   }
@@ -1203,40 +1200,6 @@ static inline int wakeup_prach_ru_br(RU_t *ru) {
 }
 #endif
 
-#if 0
-static inline int wakeup_nfapi_subframe_thread(RU_t *ru) {
-
-  int i;
-  PHY_VARS_eNB **eNB_list = ru->eNB_list;
-
-  LOG_D(PHY,"wakeup_nfapi_subframe_thread (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
-
-  if (ru->num_eNB==1 && ru->eNB_top!=0) {
-    // call eNB function directly
-
-    char string[20];
-    sprintf(string,"Incoming RU %d",ru->idx);
-    //LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
-    ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
-  }
-  else {
-
-    LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB);
-
-    for (i=0;i<ru->num_eNB;i++)
-    {
-      LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
-
-      if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
-      {
-	LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
-      }
-    }
-  }
-}
-#endif
-
-
 // this is for RU with local RF unit
 void fill_rf_config(RU_t *ru, char *rf_config_file) {
 
@@ -1490,13 +1453,12 @@ static void* ru_thread( void* param ) {
         RC.eNB[0][0]->proc.frame_rx,RC.eNB[0][0]->proc.subframe_rx,
         RC.eNB[0][0]->proc.frame_tx);
 
-    if (0 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx))
       LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
           ru->do_prach,
           is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx),
           proc->frame_rx,proc->subframe_rx);
  
-    if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) { 
+    if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) {
       wakeup_prach_ru(ru);
     }
 #ifdef Rel14
@@ -1516,15 +1478,12 @@ static void* ru_thread( void* param ) {
     // If this proc is to provide synchronization, do so
     wakeup_slaves(proc);
 
-    //LOG_E(PHY,"RU %d/%d frame_tx %d, subframe_tx %d - wakeup_eNBs...\n",0,ru->idx,proc->frame_tx,proc->subframe_tx);
     // wakeup all eNB processes waiting for this RU
     if (ru->num_eNB>0) wakeup_eNBs(ru);
 
-    //LOG_E(PHY,"%s() Before wait_on_condition()\n", __FUNCTION__);
     // wait until eNBs are finished subframe RX n and TX n+sf_ahead
     wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread");
 
-    //LOG_E(PHY,"%s() AFTER wait_on_condition() ru->feptx_prec:%p ru->fh_north_asynch_in:%p ru->feptx_ofdm:%p ru->fh_south_out:%p ru->fh_north_out:%p\n", __FUNCTION__, ru->feptx_prec, ru->fh_north_asynch_in, ru->feptx_ofdm, ru->fh_south_out, ru->fh_north_out);
 
     // do TX front-end processing if needed (precoding and/or IDFTs)
     if (ru->feptx_prec) ru->feptx_prec(ru);
@@ -1654,7 +1613,6 @@ void init_RU_proc(RU_t *ru) {
 #endif
   char name[100];
 
-  LOG_E(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
 #ifndef OCP_FRAMEWORK
   LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
 #endif
@@ -1709,8 +1667,6 @@ void init_RU_proc(RU_t *ru) {
   
   pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
 
-  LOG_E(PHY,"%s() DJP - ru->function:%d\n", __FUNCTION__, ru->function);
-
   if (ru->function == NGFI_RRU_IF4p5) {
     pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
 #ifdef Rel14  
@@ -1728,7 +1684,7 @@ void init_RU_proc(RU_t *ru) {
     
   }
   else if (ru->function == eNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
-    LOG_E(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
+    LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
     pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
   }
 
@@ -1941,9 +1897,9 @@ void init_RU(char *rf_config_file) {
     for (i=0;i<RC.nb_L1_inst;i++) 
       for (CC_id=0;CC_id<RC.nb_CC[i];CC_id++) RC.eNB[i][CC_id]->num_RU=0;
 
-LOG_E(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
+  LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
   for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
-LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
+    LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
     ru               = RC.ru[ru_id];
     ru->rf_config_file = rf_config_file;
     ru->idx          = ru_id;              
@@ -1951,7 +1907,7 @@ LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
     // use eNB_list[0] as a reference for RU frame parameters
     // NOTE: multiple CC_id are not handled here yet!
 
-    printf("%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
+    LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
 
     if (ru->eNB_list[0] == 0)
     {
@@ -1968,8 +1924,8 @@ LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
     }
 
     eNB0             = ru->eNB_list[0];
-    printf("RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
-    printf("eNB0:%p\n", eNB0);
+    LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
+    LOG_D(PHY, "eNB0:%p\n", eNB0);
     if (eNB0)
     {
       if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
@@ -1980,7 +1936,7 @@ LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
         memcpy((void*)&ru->frame_parms,(void*)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS));
 
         // attach all RU to all eNBs in its list/
-        LOG_E(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
+        LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
         for (i=0;i<ru->num_eNB;i++) {
           eNB0 = ru->eNB_list[i];
           eNB0->RU_list[eNB0->num_RU++] = ru;
@@ -1990,7 +1946,7 @@ LOG_E(PHY,"Process RC.ru[%d]\n",ru_id);
     //    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
 
 
-LOG_E(PHY,"ru->if_south:%d\n", ru->if_south);
+    LOG_D(PHY,"ru->if_south:%d\n", ru->if_south);
 
     switch (ru->if_south) {
     case LOCAL_RF:   // this is an RU with integrated RF (RRU, eNB)
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index c786a62e2e..792f16e92a 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -873,8 +873,8 @@ void wait_eNBs(void) {
 
 
   while (waiting==1) {
-    printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
-    usleep(5000000);
+    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
+    usleep(50*1000);
     waiting=0;
     for (i=0;i<RC.nb_L1_inst;i++) {
 
@@ -1255,7 +1255,7 @@ int main( int argc, char **argv )
 #endif
   
   rt_sleep_ns(10*100000000ULL);
-  
+
   if (nfapi_mode) {
 
     printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
-- 
GitLab