diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6ed9b1ba05ae21535488ba33c94d058d59849ab..01f3fb17a06c722a938a6874bcce4688a673ab0e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -723,20 +723,14 @@ target_link_libraries(SCHED_NR_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs
 
 # nFAPI
 #################################
-set(NFAPI_COMMON_SRC
-  ${NFAPI_DIR}/common/src/debug.c
-  )
-add_library(NFAPI_COMMON_LIB ${NFAPI_COMMON_SRC})
-
-include_directories(${NFAPI_DIR}/common/public_inc)
-
 set(NFAPI_SRC
-  ${NFAPI_DIR}/nfapi/src/nfapi.c
   ${NFAPI_DIR}/nfapi/src/nfapi_p4.c
   ${NFAPI_DIR}/nfapi/src/nfapi_p5.c
   ${NFAPI_DIR}/nfapi/src/nfapi_p7.c
 )
 add_library(NFAPI_LIB ${NFAPI_SRC})
+target_link_libraries(NFAPI_LIB PUBLIC nfapi_common)
+target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5)
 
 include_directories(${NFAPI_DIR}/nfapi/public_inc)
 include_directories(${NFAPI_DIR}/nfapi/inc)
@@ -761,7 +755,10 @@ set(NFAPI_VNF_SRC
 )
 add_library(NFAPI_VNF_LIB ${NFAPI_VNF_SRC})
 target_link_libraries(NFAPI_VNF_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
-
+target_link_libraries(NFAPI_VNF_LIB PRIVATE nr_fapi_p5)
+if(OAI_AERIAL)
+  target_compile_definitions(NFAPI_VNF_LIB PRIVATE ENABLE_AERIAL)
+endif()
 include_directories(${NFAPI_DIR}/vnf/public_inc)
 include_directories(${NFAPI_DIR}/vnf/inc)
 
@@ -1457,6 +1454,9 @@ add_library(e1_if
 target_link_libraries(e1_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs asn1_f1ap SECURITY ${OPENSSL_LIBRARIES} e1ap GTPV1U)
 
 target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc nr_common)
+if(OAI_AERIAL)
+    target_compile_definitions(L2_NR PRIVATE ENABLE_AERIAL)
+endif()
 if(E2_AGENT)
   target_link_libraries(L2_NR PUBLIC e2_agent e2_agent_arg e2_ran_func_du_cucp_cuup)
   target_compile_definitions(L2_NR PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
@@ -1968,7 +1968,7 @@ add_dependencies(lte-softmodem oai_iqplayer)
 target_link_libraries(lte-softmodem PRIVATE
   -Wl,--start-group
   lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
-  PHY_COMMON PHY PHY_RU  L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
+  PHY_COMMON PHY PHY_RU  L2 L2_LTE NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
   ${NAS_UE_LIB} ITTI SIMU SIMU_ETH shlib_loader
   -Wl,--end-group z dl)
 
@@ -2028,7 +2028,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE
   -Wl,--start-group
   lte_rrc nr_rrc s1ap x2ap m2ap m3ap
   SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
-  PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
+  PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
   ${NAS_UE_LIB} ITTI shlib_loader
   -Wl,--end-group z dl)
 
@@ -2061,13 +2061,11 @@ add_executable(nr-softmodem
   ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
   )
 
-include(${OPENAIR_DIR}/nfapi/CMakeLists.txt)
-
 target_link_libraries(nr-softmodem PRIVATE
   -Wl,--start-group
   UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
   ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
-  ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
+  ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
   x2ap f1ap m2ap m3ap e1ap shlib_loader
   -Wl,--end-group z dl)
 
@@ -2075,6 +2073,11 @@ target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt sctp)
 target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
 target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
 target_link_libraries(nr-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
+add_boolean_option(OAI_AERIAL OFF "Activate OAI's AERIAL driver" OFF)
+if (OAI_AERIAL)
+  target_compile_definitions(nr-softmodem PUBLIC ENABLE_AERIAL)
+  target_link_libraries(nr-softmodem PUBLIC aerial_lib)
+endif()
 if(E2_AGENT)
   target_compile_definitions(nr-softmodem PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
 endif()
@@ -2131,7 +2134,7 @@ add_executable(nr-uesoftmodem
 target_link_libraries(nr-uesoftmodem PRIVATE
   -Wl,--start-group
   nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
-  PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
+  PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_LIB NFAPI_PNF_LIB
   NFAPI_USER_LIB MISC_NFAPI_NR_LIB
   ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH shlib_loader
   -Wl,--end-group z dl)
@@ -2367,7 +2370,7 @@ if (${T_TRACER})
         params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
         oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
         SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
-        NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
+        NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
         MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
         PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
         L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
@@ -2488,6 +2491,7 @@ endif()
 
 add_subdirectory(common)
 add_subdirectory(doc)
+add_subdirectory(nfapi)
 add_subdirectory(openair1)
 add_subdirectory(openair2)
 add_subdirectory(openair3)
diff --git a/ci-scripts/docker/Dockerfile.unittest.ubuntu22 b/ci-scripts/docker/Dockerfile.unittest.ubuntu22
index 6098a1d1f6b59b46ac69fa415d2bb127ba035a5c..21805560d4bd369a90273d6443bbb31d0c7d34db 100644
--- a/ci-scripts/docker/Dockerfile.unittest.ubuntu22
+++ b/ci-scripts/docker/Dockerfile.unittest.ubuntu22
@@ -37,4 +37,4 @@ WORKDIR /oai-ran
 COPY . .
 
 WORKDIR /oai-ran/build
-RUN cmake -GNinja -DENABLE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug .. && ninja tests
+RUN cmake -GNinja -DENABLE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DSANITIZE_ADDRESS=True .. && ninja tests
diff --git a/common/utils/nr/CMakeLists.txt b/common/utils/nr/CMakeLists.txt
index 6b58544a6dbe15db3a0c55440a3cf9197473c0b8..979958d877069e557cdb878717904b7f0b3794f5 100644
--- a/common/utils/nr/CMakeLists.txt
+++ b/common/utils/nr/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_library(nr_common nr_common.c)
 target_include_directories(nr_common PUBLIC .)
+target_link_libraries(nr_common PRIVATE UTIL)
 if (ENABLE_TESTS)
   add_subdirectory(tests)
 endif()
diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c
index 8f0fcb4594bb9d90a0f0ba5d014e0cb2f0e0f72a..520dce1ace09e4120da48ade2aee5d21311e361d 100644
--- a/common/utils/nr/nr_common.c
+++ b/common/utils/nr/nr_common.c
@@ -356,8 +356,8 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_
 
   int band_size_khz = get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, nb_ul) * 1000;
   float limit = frame_type == TDD ? 0.04 : 0.03;
-  float rel_bw = (float) (2 * band_size_khz) / (float) (nr_bandtable[index].ul_max + nr_bandtable[index].ul_min);
-  return rel_bw <= limit;
+  float rel_bw = (float) (band_size_khz) / (float) (nr_bandtable[index].ul_max - nr_bandtable[index].ul_min);
+  return rel_bw > limit;
 }
 
 uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt
index 7f2d7a02e56daa9a85e2bd1a9fdb7ef4eca5d43b..959812d73a9bda9b4906037935ddaa07ccce855c 100644
--- a/common/utils/telnetsrv/CMakeLists.txt
+++ b/common/utils/telnetsrv/CMakeLists.txt
@@ -36,6 +36,7 @@ add_library(telnetsrv MODULE
 )
 target_link_libraries(telnetsrv PRIVATE history)
 target_link_libraries(telnetsrv PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
+target_link_libraries(telnetsrv PRIVATE UTIL)
 
 message(STATUS "Add enb specific telnet functions in libtelnetsrv_enb.so")
 add_library(telnetsrv_enb MODULE
diff --git a/common/utils/threadPool/test/test_thread-pool.c b/common/utils/threadPool/test/test_thread-pool.c
index 0d6defd5cbae3edb4622cf2c73329df82a67bb3f..1af3dc10204fcc222b9942f2b9b5310d8062fcca 100644
--- a/common/utils/threadPool/test/test_thread-pool.c
+++ b/common/utils/threadPool/test/test_thread-pool.c
@@ -46,7 +46,7 @@ void displayList(notifiedFIFO_t *nf)
 struct testData {
   int id;
   int sleepTime;
-  char txt[30];
+  char txt[50];
 };
 
 void processing(void *arg)
@@ -64,21 +64,27 @@ int main()
   logInit();
   notifiedFIFO_t myFifo;
   initNotifiedFIFO(&myFifo);
+  int num_elements_on_queue = 0;
   pushNotifiedFIFO(&myFifo, newNotifiedFIFO_elt(sizeof(struct testData), 1234, NULL, NULL));
+  num_elements_on_queue++;
 
   for (int i = 10; i > 1; i--) {
     pushNotifiedFIFO(&myFifo, newNotifiedFIFO_elt(sizeof(struct testData), 1000 + i, NULL, NULL));
+    num_elements_on_queue++;
   }
 
   displayList(&myFifo);
   notifiedFIFO_elt_t *tmp = pullNotifiedFIFO(&myFifo);
   printf("pulled: %lu\n", tmp->key);
   displayList(&myFifo);
+  delNotifiedFIFO_elt(tmp);
   tmp = pullNotifiedFIFO(&myFifo);
+  num_elements_on_queue--;
   printf("pulled: %lu\n", tmp->key);
   displayList(&myFifo);
   pushNotifiedFIFO(&myFifo, newNotifiedFIFO_elt(sizeof(struct testData), 12345678, NULL, NULL));
   displayList(&myFifo);
+  delNotifiedFIFO_elt(tmp);
 
   do {
     tmp = pollNotifiedFIFO(&myFifo);
@@ -86,9 +92,12 @@ int main()
     if (tmp) {
       printf("pulled: %lu\n", tmp->key);
       displayList(&myFifo);
+      delNotifiedFIFO_elt(tmp);
+      num_elements_on_queue--;
     } else
       printf("Empty list \n");
-  } while (tmp);
+  } while (num_elements_on_queue > 0);
+  AssertFatal(pollNotifiedFIFO(&myFifo) == NULL, "Unexpected extra element on queue\n");
 
   tpool_t pool;
   char params[] = "1,2,3,4,5";
@@ -129,5 +138,6 @@ int main()
          dur / 1000,
          cumulProcessTime / 1000,
          (dur - cumulProcessTime) / (1000 * nb_jobs));
+  abortTpool(&pool);
   return 0;
 }
diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h
index 1a78e201347e41de88ff8384f4cbef5817d71f57..b0e1b9e4e88e68e2c46b0c9cfc3bebbf4591193b 100644
--- a/common/utils/threadPool/thread-pool.h
+++ b/common/utils/threadPool/thread-pool.h
@@ -336,7 +336,9 @@ static inline int abortTpool(tpool_t *t) {
   thread = t->allthreads;
   while (thread != NULL) {
     pthread_cancel(thread->threadID);
-    thread = thread->next;
+    struct one_thread *next = thread->next;
+    free(thread);
+    thread = next;
   }
 
   return nbRemoved;
diff --git a/nfapi/CMakeLists.txt b/nfapi/CMakeLists.txt
index 7c75480aa64cf352ac825053d6283a67bfd05328..d6c5b0e92a39acf1489578a9c3e8d0e7b92594ff 100644
--- a/nfapi/CMakeLists.txt
+++ b/nfapi/CMakeLists.txt
@@ -1 +1,3 @@
-include(${OPENAIR_DIR}/nfapi/oai_integration/aerial/CMakeLists.txt)
\ No newline at end of file
+add_subdirectory(oai_integration/aerial)
+add_subdirectory(open-nFAPI)
+add_subdirectory(tests)
diff --git a/nfapi/oai_integration/aerial/CMakeLists.txt b/nfapi/oai_integration/aerial/CMakeLists.txt
index 2514edf6029d1fef6f5510a8b9ce1b8e2b02ba40..4c02ab01e95c904c78094c98d0df10b3b5b5a3dd 100644
--- a/nfapi/oai_integration/aerial/CMakeLists.txt
+++ b/nfapi/oai_integration/aerial/CMakeLists.txt
@@ -1,20 +1,16 @@
-add_boolean_option(OAI_AERIAL OFF "Activate OAI's AERIAL driver" OFF)
 if (OAI_AERIAL)
     message(STATUS "Building with support for Aerial")
-
-    target_sources(
-            nr-softmodem
-            PRIVATE
-            ${OPENAIR_DIR}/nfapi/oai_integration/aerial/fapi_nvIPC.c
-            ${OPENAIR_DIR}/nfapi/oai_integration/aerial/fapi_vnf_p7.c
-            ${OPENAIR_DIR}/nfapi/oai_integration/aerial/fapi_vnf_p5.c )
+    add_library(aerial_lib
+            fapi_nvIPC.c
+            fapi_vnf_p7.c
+            fapi_vnf_p5.c
+    )
 
     find_library(NVIPC_LIB nvipc REQUIRED)
     if (NOT NVIPC_LIB)
         message(FATAL_ERROR "-- nvipc library not found")
     else ()
         message(STATUS "  nvipc library found in ${NVIPC_LIB}")
-        #add_library(nvipc   STATIC  SHARED IMPORTED GLOBAL)
     endif ()
 
     find_library(NVLOG_LIB nvlog REQUIRED)
@@ -23,11 +19,10 @@ if (OAI_AERIAL)
     else ()
         message(STATUS "  nvlog library found in ${NVLOG_LIB}")
     endif ()
-
-    add_compile_definitions(ENABLE_L2_SLT_RSP)
-    add_compile_definitions(FAPI_BYTE_ORDERING_BIG_ENDIAN)
-    add_compile_definitions(ENABLE_AERIAL)
-    target_link_libraries(nr-softmodem PRIVATE  "${NVLOG_LIB}" "${NVIPC_LIB}")
-else()
+    target_compile_definitions(aerial_lib PUBLIC ENABLE_L2_SLT_RSP ENABLE_AERIAL)
+    target_link_libraries(aerial_lib PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
+    target_link_libraries(aerial_lib PRIVATE nr_fapi_p5)
+    target_link_libraries(aerial_lib PRIVATE "${NVLOG_LIB}" "${NVIPC_LIB}")
+else ()
     message(STATUS "No Support for Aerial")
-endif()
\ No newline at end of file
+endif ()
diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.c b/nfapi/oai_integration/aerial/fapi_vnf_p5.c
index 90e584d33d8cc86c5d56eb673a66d6d45c9ae2f8..20236a2a856e4e013d75fdd8e709c92d55fcbf8e 100644
--- a/nfapi/oai_integration/aerial/fapi_vnf_p5.c
+++ b/nfapi/oai_integration/aerial/fapi_vnf_p5.c
@@ -32,8 +32,9 @@
 #ifdef ENABLE_AERIAL
 #include "fapi_vnf_p5.h"
 #include "fapi_vnf_p7.h"
-#include "nfapi/open-nFAPI/nfapi/src/nfapi_p5.c"
 #include "nfapi/open-nFAPI/vnf/inc/vnf_p7.h"
+#include "nr_fapi.h"
+#include "nr_fapi_p5.h"
 
 extern RAN_CONTEXT_t RC;
 extern UL_RCC_IND_t UL_RCC_INFO;
@@ -621,61 +622,6 @@ int aerial_nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config)
   return 0;
 }
 
-int fapi_nr_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;
-
-  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;
-  }
-  uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen;
-  uint8_t *pPackedLengthField = &pWritePackedMessage[4];
-  uint8_t *pPacketBodyField = &pWritePackedMessage[8];
-  uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8];
-
-  pack_nr_p5_message_body(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config);
-
-  // PHY API message header
-  push8(1, &pWritePackedMessage, pPackMessageEnd); // Number of messages
-  push8(0, &pWritePackedMessage, pPackMessageEnd); // Opaque handle
-
-  // PHY API Message structure
-  push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd); // Message type ID
-
-  if(1==1) {
-    // check for a valid message length
-    packedMsgLen = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField);
-    packedMsgLen-=1;
-    if(pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_START_REQUEST){
-      //START.request doesn't have a body, length is 0
-      packedMsgLen = 0;
-    }else if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) {
-      NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message 0x%02x length error %d, buffer supplied %d\n",pMessageHeader->message_id, packedMsgLen, packedBufLen);
-      return -1;
-    } else {
-
-    }
-
-    // Update the message length in the header
-    if(!push32(packedMsgLen, &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;
-  }
-
-}
-
-
 int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req)
 {
   nfapi_vnf_p7_config_t *p7_config = aerial_vnf.p7_vnfs[0].config;
diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p5.h b/nfapi/oai_integration/aerial/fapi_vnf_p5.h
index 9d3fb6d1705ae33e271233682d7f8f9424e00abf..ba315709bfe608c02c17fe27d30207ca2769d717 100644
--- a/nfapi/oai_integration/aerial/fapi_vnf_p5.h
+++ b/nfapi/oai_integration/aerial/fapi_vnf_p5.h
@@ -65,7 +65,6 @@ uint8_t aerial_unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end,
 uint8_t aerial_unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
 int aerial_pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx);
 int aerial_nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config);
-int fapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
 
 int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req);
 int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req);
diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c
index eefa404e58923973b56bc9d25b2eacdf7be00884..42a12d3cb4c81c52fce96de93d7bc104dbd90b55 100644
--- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c
+++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c
@@ -31,7 +31,7 @@
  */
 #ifdef ENABLE_AERIAL
 #include "fapi_vnf_p7.h"
-#include "nfapi/open-nFAPI/nfapi/src/nfapi_p7.c"
+#include "nr_nfapi_p7.h"
 
 extern RAN_CONTEXT_t RC;
 extern UL_RCC_IND_t UL_RCC_INFO;
diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.h b/nfapi/oai_integration/aerial/fapi_vnf_p7.h
index a09ca94aa9c19753eff45f3f8b9747658a8158ec..7ea5e24569262541d1535388c43f9efee63d3512 100644
--- a/nfapi/oai_integration/aerial/fapi_vnf_p7.h
+++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.h
@@ -45,6 +45,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "nfapi_interface.h"
 #include "nfapi_nr_interface_scf.h"
 #include "nfapi_vnf_interface.h"
 #include "nfapi_vnf.h"
diff --git a/nfapi/open-nFAPI/CMakeLists.txt b/nfapi/open-nFAPI/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad4131c621f54eb7309eabed5160dd6da601283a
--- /dev/null
+++ b/nfapi/open-nFAPI/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(common)
+add_subdirectory(fapi)
diff --git a/nfapi/open-nFAPI/common/CMakeLists.txt b/nfapi/open-nFAPI/common/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..20263bc29c2d722d45eb831fd7a846d061e89a47
--- /dev/null
+++ b/nfapi/open-nFAPI/common/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(nfapi_common
+            src/debug.c
+            src/nfapi.c)
+target_include_directories(nfapi_common PUBLIC public_inc/)
+if (OAI_AERIAL)
+    target_compile_definitions(nfapi_common PRIVATE FAPI_BYTE_ORDERING_BIG_ENDIAN)
+endif()
diff --git a/nfapi/open-nFAPI/nfapi/inc/nfapi.h b/nfapi/open-nFAPI/common/public_inc/nfapi.h
similarity index 66%
rename from nfapi/open-nFAPI/nfapi/inc/nfapi.h
rename to nfapi/open-nFAPI/common/public_inc/nfapi.h
index dc2d3d3ec00cc13e08ea726eca3841d604741b4f..99c7d7ec7e2dcc68c43583986cf778fd30715c23 100644
--- a/nfapi/open-nFAPI/nfapi/inc/nfapi.h
+++ b/nfapi/open-nFAPI/common/public_inc/nfapi.h
@@ -77,8 +77,8 @@ uint8_t unpackarray(uint8_t **ppReadPackedMsg,
                     uint8_t *end,
                     unpack_array_elem_fn fn);
 
-uint32_t pack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end);
-uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end);
+uint32_t pack_dci_payload(uint8_t *payload, uint16_t payloadSizeBits, uint8_t **out, uint8_t *end);
+uint32_t unpack_dci_payload(uint8_t *payload, uint16_t payloadSizeBits, uint8_t **in, uint8_t *end);
 
 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);
@@ -86,6 +86,7 @@ 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);
 uint8_t pack_nr_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn);
+uint8_t pack_nr_generic_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
 
 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_tlv(nfapi_tl_t *tl,
@@ -94,6 +95,8 @@ int unpack_vendor_extension_tlv(nfapi_tl_t *tl,
                                 nfapi_p4_p5_codec_config_t *config,
                                 nfapi_tl_t **ve_tlv);
 
+uint8_t unpack_nr_generic_tlv_list(void *tlv_list, uint8_t tlv_count, uint8_t **ppReadPackedMsg, uint8_t *end);
+
 uint8_t get_tlv_padding(uint16_t tlv_length);
 
 typedef uint8_t (*unpack_tlv_fn)(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
@@ -136,6 +139,50 @@ int unpack_nr_p7_tlv_list(unpack_p7_tlv_t unpack_fns[],
                           nfapi_p7_codec_config_t *config,
                           nfapi_tl_t **ve);
 
+uint8_t pack_pnf_param_general_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_pnf_param_general_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_pnf_phy_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_pnf_phy_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_pnf_phy_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_pnf_phy_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_phy_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_phy_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_ipv4_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_ipv4_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_ipv6_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_ipv6_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+
+uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+
+uint8_t pack_uint32_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_uint32_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_uint16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_uint16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_int16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_int16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint8_t pack_uint8_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end);
+uint8_t unpack_uint8_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end);
+
+uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/nfapi/open-nFAPI/common/src/nfapi.c b/nfapi/open-nFAPI/common/src/nfapi.c
new file mode 100644
index 0000000000000000000000000000000000000000..97352b98f79487ede26e257f290d4512a1144b1b
--- /dev/null
+++ b/nfapi/open-nFAPI/common/src/nfapi.c
@@ -0,0 +1,1708 @@
+/*
+ * 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 <execinfo.h>
+
+#include <nfapi_interface.h>
+#include <nfapi_nr_interface_scf.h>
+#include <nfapi.h>
+#include <debug.h>
+
+// What to do when an error happens (e.g., a push or pull fails)
+static inline void on_error()
+{
+  // show the call stack
+  int fd = STDERR_FILENO;
+  static const char msg[] = "---stack trace---\n";
+  __attribute__((unused)) int r = write(fd, msg, sizeof(msg) - 1);
+  void *buffer[100];
+  int nptrs = backtrace(buffer, sizeof(buffer) / sizeof(buffer[0]));
+  backtrace_symbols_fd(buffer, nptrs, fd);
+
+  // abort();
+}
+
+// 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__);
+    on_error();
+    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__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end)
+{
+  uint8_t *pOut = *out;
+
+  if ((end - pOut) >= 2) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    pOut[1] = (in & 0xFF00) >> 8;
+    pOut[0] = (in & 0xFF);
+#else
+    pOut[0] = (in & 0xFF00) >> 8;
+    pOut[1] = (in & 0xFF);
+#endif
+    (*out) += 2;
+    return 2;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end)
+{
+  uint8_t *pOut = *out;
+
+  if ((end - pOut) >= 2) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    pOut[1] = (in & 0xFF00) >> 8;
+    pOut[0] = (in & 0xFF);
+#else
+    pOut[0] = (in & 0xFF00) >> 8;
+    pOut[1] = (in & 0xFF);
+#endif
+    (*out) += 2;
+    return 2;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end)
+{
+  uint8_t *pOut = *out;
+
+  if ((end - pOut) >= 4) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    pOut[3] = (in & 0xFF000000) >> 24;
+    pOut[2] = (in & 0xFF0000) >> 16;
+    pOut[1] = (in & 0xFF00) >> 8;
+    pOut[0] = (in & 0xFF);
+#else
+    pOut[0] = (in & 0xFF000000) >> 24;
+    pOut[1] = (in & 0xFF0000) >> 16;
+    pOut[2] = (in & 0xFF00) >> 8;
+    pOut[3] = (in & 0xFF);
+#endif
+    (*out) += 4;
+    return 4;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end)
+{
+  uint8_t *pOut = *out;
+
+  if ((end - pOut) >= 4) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    pOut[3] = (in & 0xFF000000) >> 24;
+    pOut[2] = (in & 0xFF0000) >> 16;
+    pOut[1] = (in & 0xFF00) >> 8;
+    pOut[0] = (in & 0xFF);
+#else
+    pOut[0] = (in & 0xFF000000) >> 24;
+    pOut[1] = (in & 0xFF0000) >> 16;
+    pOut[2] = (in & 0xFF00) >> 8;
+    pOut[3] = (in & 0xFF);
+#endif
+    (*out) += 4;
+    return 4;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    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__);
+    on_error();
+    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__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end)
+{
+  uint8_t *pIn = *in;
+
+  if ((end - pIn) >= 2) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    *out = ((pIn[1]) << 8) | pIn[0];
+#else
+    *out = ((pIn[0]) << 8) | pIn[1];
+#endif
+    (*in) += 2;
+    return 2;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end)
+{
+  uint8_t *pIn = *in;
+
+  if ((end - pIn) >= 2) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    *out = ((pIn[1]) << 8) | pIn[0];
+#else
+    *out = ((pIn[0]) << 8) | pIn[1];
+#endif
+    (*in) += 2;
+    return 2;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end)
+{
+  uint8_t *pIn = *in;
+
+  if ((end - pIn) >= 4) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    *out = ((uint32_t)pIn[3] << 24) | (pIn[2] << 16) | (pIn[1] << 8) | pIn[0];
+#else
+    *out = ((uint32_t)pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
+#endif
+    (*in) += 4;
+    return 4;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end)
+{
+  uint8_t *pIn = *in;
+
+  if ((end - pIn) >= 4) {
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+    *out = (pIn[3] << 24) | (pIn[2] << 16) | (pIn[1] << 8) | pIn[0];
+#else
+    *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
+#endif
+    (*in) += 4;
+    return 4;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    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);
+    on_error();
+    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__);
+    on_error();
+    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);
+    on_error();
+    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__);
+    on_error();
+    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);
+    on_error();
+    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__);
+    on_error();
+    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);
+    on_error();
+    return 0;
+  }
+
+  if ((end - (*out)) >= sizeof(uint16_t) * len) {
+    uint32_t idx;
+
+    for (idx = 0; idx < len; ++idx) {
+      if (!pushs16(in[idx], out, end))
+        return 0;
+    }
+
+    return sizeof(uint16_t) * len;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+uint32_t pullarray32(uint8_t **values_to_pull,
+                     uint32_t out[],
+                     uint32_t max_num_values_to_pull,
+                     uint32_t num_values_to_pull,
+                     uint8_t *out_end)
+{
+  if (num_values_to_pull == 0)
+
+    return 1;
+
+  if (num_values_to_pull > max_num_values_to_pull) {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, num_values_to_pull, max_num_values_to_pull);
+    on_error();
+    return 0;
+  }
+
+  if ((out_end - (*values_to_pull)) >= sizeof(uint32_t) * num_values_to_pull) {
+    uint32_t idx;
+
+    for (idx = 0; idx < num_values_to_pull; ++idx) {
+      if (!pull32(values_to_pull, &out[idx], out_end))
+        return 0;
+    }
+
+    return sizeof(uint32_t) * num_values_to_pull;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+
+uint32_t pullarrays32(uint8_t **in, int32_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);
+    on_error();
+    return 0;
+  }
+
+  if ((end - (*in)) >= sizeof(uint32_t) * len) {
+    uint32_t idx;
+
+    for (idx = 0; idx < len; ++idx) {
+      if (!pulls32(in, &out[idx], end))
+        return 0;
+    }
+
+    return sizeof(uint32_t) * len;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+uint32_t pusharray32(const uint32_t *values_to_push,
+                     uint32_t max_num_values_to_push,
+                     uint32_t num_values_to_push,
+                     uint8_t **out,
+                     uint8_t *out_end)
+{
+  if (num_values_to_push == 0)
+    return 1;
+
+  if (num_values_to_push > max_num_values_to_push) {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, num_values_to_push, max_num_values_to_push);
+    on_error();
+    return 0;
+  }
+
+  if ((out_end - (*out)) >= sizeof(uint32_t) * num_values_to_push) {
+    uint32_t idx;
+
+    for (idx = 0; idx < num_values_to_push; ++idx) {
+      if (!push32(values_to_push[idx], out, out_end))
+        return 0;
+    }
+
+    return sizeof(uint32_t) * num_values_to_push;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    return 0;
+  }
+}
+uint32_t pusharrays32(int32_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);
+    on_error();
+    return 0;
+  }
+
+  if ((end - (*out)) >= sizeof(uint32_t) * len) {
+    uint32_t idx;
+
+    for (idx = 0; idx < len; ++idx) {
+      if (!pushs32(in[idx], out, end))
+        return 0;
+    }
+
+    return sizeof(uint32_t) * len;
+  } else {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
+    on_error();
+    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);
+    on_error();
+    return 0;
+  }
+
+  if ((end - (*in)) >= 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__);
+    on_error();
+    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);
+    on_error();
+    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__);
+    on_error();
+    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);
+    on_error();
+    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);
+    on_error();
+    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_dci_payload(uint8_t *payload, uint16_t payloadSizeBits, uint8_t **out, uint8_t *end)
+{
+  uint8_t dci_byte_len = (payloadSizeBits + 7) / 8;
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+  // Helper vars for DCI Payload
+  uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN] = {0};
+  uint8_t payload_internal[DCI_PAYLOAD_BYTE_LEN] = {0}; // Used to not edit the "outside" pointer
+  uint8_t rotation_bits = 0;
+  // Align the dci payload bits to the left on the payload buffer
+  if (payloadSizeBits % 8 != 0) {
+    rotation_bits = 8 - (payloadSizeBits % 8);
+    // Bit shifting value ( << )
+    uint64_t t = 0;
+    memcpy(&t, payload, dci_byte_len);
+    t = t << rotation_bits;
+    memcpy(payload_internal, &t, dci_byte_len);
+  } else {
+    // No rotation needed
+    memcpy(payload_internal, payload, dci_byte_len);
+  }
+  // Invert the byte order of the DCI Payload
+  for (int j = 0; j < dci_byte_len; j++) {
+    dci_bytes_inverted[j] = payload_internal[(dci_byte_len - 1) - j];
+  }
+  return pusharray8(dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, out, end);
+#else
+  return pusharray8(payload, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, out, end);
+#endif
+}
+
+uint32_t unpack_dci_payload(uint8_t *payload, uint16_t payloadSizeBits, uint8_t **in, uint8_t *end)
+{
+  // Pull the inverted DCI and invert it back
+  //  Helper vars for DCI Payload
+  uint8_t dci_byte_len = (payloadSizeBits + 7) / 8;
+#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
+  uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN] = {0};
+  // Get DCI array inverted
+  uint32_t pullresult = pullarray8(in, dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, end);
+
+  // Reversing the byte order of the inverted DCI payload
+  for (uint16_t j = 0; j < dci_byte_len; j++) {
+    payload[j] = dci_bytes_inverted[(dci_byte_len - 1) - j];
+  }
+
+  uint64_t t = 0;
+  memcpy(&t, payload, dci_byte_len);
+  if (payloadSizeBits % 8 != 0) {
+    uint8_t rotation_bits = 8 - (payloadSizeBits % 8);
+    t = (t >> (uint64_t)rotation_bits);
+  }
+  memcpy(payload, &t, dci_byte_len);
+#else
+  uint32_t pullresult = pullarray8(in, payload, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, end);
+#endif
+  return pullresult;
+}
+
+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;
+}
+
+int 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) { // match the extracted tag value with all the tags in unpack_fn list
+        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 %ld\n",
+                      tl->tag,
+                      tl->length,
+                      (*ppReadPackedMsg - pStartOfValue));
+          on_error();
+        }
+      }
+    }
+
+    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);
+          on_error();
+
+          if (++numBadTags > MAX_BAD_TAG) {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+            on_error();
+            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);
+        on_error();
+
+        if (++numBadTags > MAX_BAD_TAG) {
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+          on_error();
+          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_nr_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) { // match the extracted tag value with all the tags in unpack_fn list
+        tagMatch = 1;
+
+        if (generic_tl.tag == NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG) {
+          // padding and sub tlvs handled already
+          nfapi_nr_cell_param_t *cellParamTable = (nfapi_nr_cell_param_t *)unpack_fns[idx].tlv;
+          cellParamTable->num_config_tlvs_to_report.tl.tag = generic_tl.tag;
+          cellParamTable->num_config_tlvs_to_report.tl.length = generic_tl.length;
+          int result = (*unpack_fns[idx].unpack_func)(unpack_fns[idx].tlv, ppReadPackedMsg, end);
+          if (result == 0) {
+            return 0;
+          }
+          continue;
+        }
+
+        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 %ld\n",
+                      tl->tag,
+                      tl->length,
+                      (*ppReadPackedMsg - pStartOfValue));
+          on_error();
+        }
+        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+        int padding = get_tlv_padding(tl->length);
+        if (padding != 0) {
+          (*ppReadPackedMsg) += padding;
+        }
+      }
+    }
+
+    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);
+          on_error();
+
+          if (++numBadTags > MAX_BAD_TAG) {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+            on_error();
+            return 0;
+          }
+
+          if ((end - *ppReadPackedMsg) >= generic_tl.length) {
+            // Advance past the unknown TLV
+            (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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);
+        on_error();
+
+        if (++numBadTags > MAX_BAD_TAG) {
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+          on_error();
+          return 0;
+        }
+
+        if ((end - *ppReadPackedMsg) >= generic_tl.length) {
+          // Advance past the unknown TLV
+          (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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 %ld\n",
+                      tl->tag,
+                      tl->length,
+                      (*ppReadPackedMsg - pStartOfValue));
+          on_error();
+        }
+      }
+    }
+
+    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);
+          on_error();
+
+          if (++numBadTags > MAX_BAD_TAG) {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+            on_error();
+            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);
+        on_error();
+
+        if (++numBadTags > MAX_BAD_TAG) {
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+          on_error();
+          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;
+}
+
+int unpack_nr_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 %ld\n",
+                      tl->tag,
+                      tl->length,
+                      (*ppReadPackedMsg - pStartOfValue));
+          on_error();
+        }
+        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+        int padding = get_tlv_padding(tl->length);
+        if (padding != 0) {
+          (*ppReadPackedMsg) += padding;
+        }
+      }
+    }
+
+    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);
+          on_error();
+
+          if (++numBadTags > MAX_BAD_TAG) {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+            on_error();
+            return -1;
+          }
+
+          if ((end - *ppReadPackedMsg) >= generic_tl.length) {
+            // Advance past the unknown TLV
+            (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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);
+        on_error();
+
+        if (++numBadTags > MAX_BAD_TAG) {
+          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+          on_error();
+          return -1;
+        }
+
+        if ((end - *ppReadPackedMsg) >= generic_tl.length) {
+          // Advance past the unknown TLV
+          (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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;
+}
+
+uint8_t pack_nr_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);
+    // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+    int padding = get_tlv_padding(tl->length);
+    NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x with padding of %d bytes\n", tl->tag, padding);
+    if (padding != 0) {
+      memset(*ppWritePackedMsg, 0, padding);
+      (*ppWritePackedMsg) += padding;
+    }
+  } 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;
+}
+
+uint8_t pack_nr_generic_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+  nfapi_nr_generic_tlv_scf_t *toPack = (nfapi_nr_generic_tlv_scf_t *)tlv;
+  // If the tag is defined
+  if (toPack->tl.tag == tag && toPack->tl.length != 0) {
+    // write the tlv header, length comes with value
+    if (pack_tl(&(toPack->tl), ppWritePackedMsg, end) == 0)
+      return 0;
+
+    // pack the tlv value
+    switch (toPack->tl.length) {
+      case UINT_8:
+        if (push8(toPack->value.u8, ppWritePackedMsg, end) == 0) {
+          return 0;
+        }
+        break;
+      case UINT_16:
+        if (push16(toPack->value.u16, ppWritePackedMsg, end) == 0) {
+          return 0;
+        }
+        break;
+      case UINT_32:
+        if (push32(toPack->value.u32, ppWritePackedMsg, end) == 0) {
+          return 0;
+        }
+        break;
+      case ARRAY_UINT_16:
+        if ((push16(toPack->value.array_u16[0], ppWritePackedMsg, end) && push16(toPack->value.array_u16[1], ppWritePackedMsg, end)
+             && push16(toPack->value.array_u16[2], ppWritePackedMsg, end)
+             && push16(toPack->value.array_u16[3], ppWritePackedMsg, end)
+             && push16(toPack->value.array_u16[4], ppWritePackedMsg, end))
+            == 0) {
+          return 0;
+        }
+        break;
+      default:
+        break;
+    }
+
+    // calculate the length of the value and rewrite the tl header
+    // in case of nfapi_nr_config_response_tlv_list_scf_t this is to come pre-calculated, possibly unnecessary
+    /*toPack->tl.length = (*ppWritePackedMsg) - pStartOfValue;
+    // rewrite the header with the correct length
+    pack_tl(&(toPack->tl), &pStartOfTlv, end);*/
+    // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+    int padding = get_tlv_padding(toPack->tl.length);
+    NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x with padding of %d bytes\n", toPack->tl.tag, padding);
+    if (padding != 0) {
+      memset(*ppWritePackedMsg, 0, padding);
+      (*ppWritePackedMsg) += padding;
+    }
+  } else {
+    if (toPack->tl.tag != 0) {
+      NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", toPack->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;
+}
+
+uint8_t unpack_nr_generic_tlv()
+{
+  return 1;
+}
+
+uint8_t unpack_nr_generic_tlv_list(void *tlv_list, uint8_t tlv_count, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+  nfapi_nr_generic_tlv_scf_t *toUnpack = (nfapi_nr_generic_tlv_scf_t *)tlv_list;
+  uint8_t numBadTags = 0;
+  for (int i = 0; i < tlv_count; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(toUnpack[i]);
+
+    // unpack each generic tlv
+    //  unpack the tl and process the values accordingly
+    if (unpack_tl(ppReadPackedMsg, &(element->tl), end) == 0)
+      return 0;
+
+    uint8_t *pStartOfValue = *ppReadPackedMsg;
+    // check for valid tag
+    if (element->tl.tag < NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG || element->tl.tag > NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG) {
+      numBadTags++;
+      if (numBadTags > MAX_BAD_TAG) {
+        NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
+        on_error();
+        return 0;
+      }
+    }
+    // if tag is valid, check length to determine which type to unpack
+    switch (element->tl.length) {
+      case UINT_8:
+        pull8(ppReadPackedMsg, &(element->value.u8), end);
+        break;
+      case UINT_16:
+        pull16(ppReadPackedMsg, &(element->value.u16), end);
+        break;
+      case UINT_32:
+        pull32(ppReadPackedMsg, &(element->value.u32), end);
+        break;
+      case ARRAY_UINT_16:
+        for (int j = 0; j < 5; ++j) {
+          pull16(ppReadPackedMsg, &(element->value.array_u16[j]), end);
+        }
+        break;
+      default:
+        printf("unknown length %d\n", element->tl.length);
+        break;
+    }
+
+    // check if the length was right;
+    if (element->tl.length != (*ppReadPackedMsg - pStartOfValue)) {
+      NFAPI_TRACE(NFAPI_TRACE_ERROR,
+                  "Warning tlv tag 0x%x length %d not equal to unpack %ld\n",
+                  element->tl.tag,
+                  element->tl.length,
+                  (*ppReadPackedMsg - pStartOfValue));
+      on_error();
+    }
+    // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+    int padding = get_tlv_padding(element->tl.length);
+    if (padding != 0) {
+      (*ppReadPackedMsg) += padding;
+    }
+  }
+  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";
+  }
+}
+
+uint8_t get_tlv_padding(uint16_t tlv_length)
+{
+  return (4 - (tlv_length % 4)) % 4;
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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;
+  return pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end)
+         && unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+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);
+}
+
+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));
+}
+
+uint8_t pack_uint32_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+  nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv;
+  return push32(value->value, ppWritePackedMsg, end);
+}
+
+uint8_t unpack_uint32_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+  nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv;
+  return pull32(ppReadPackedMsg, &value->value, end);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+// helper function for message length calculation -
+// takes the pointers to the start of message to end of message
+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 %p, %p\n", &msgHead, &msgEnd);
+    return 0;
+  }
+
+  return msgEnd - msgHead;
+}
diff --git a/nfapi/open-nFAPI/fapi/CMakeLists.txt b/nfapi/open-nFAPI/fapi/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bd93d054475c04a6d5ac9dd667933f5983520908
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(nr_fapi_p5
+        src/nr_fapi_p5.c
+        src/nr_fapi_p5_utils.c
+)
+target_include_directories(nr_fapi_p5 PUBLIC inc)
+target_link_libraries(nr_fapi_p5 PUBLIC nfapi_common)
diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h
new file mode 100644
index 0000000000000000000000000000000000000000..322c09b59c5d5175a673cd22d4aa9715454e06d3
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi.h
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+
+#ifndef OPENAIRINTERFACE_NR_FAPI_H
+#define OPENAIRINTERFACE_NR_FAPI_H
+
+#include "stdint.h"
+#include "string.h"
+#include "nfapi_interface.h"
+#include "nfapi_nr_interface.h"
+#include "nfapi_nr_interface_scf.h"
+#include "nfapi.h"
+#include "nfapi/oai_integration/vendor_ext.h"
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include "assertions.h"
+
+typedef struct {
+  uint8_t num_msg;
+  uint8_t opaque_handle;
+  uint16_t message_id;
+  uint32_t message_length;
+} fapi_message_header_t;
+
+int fapi_nr_p5_message_header_unpack(uint8_t **pMessageBuf,
+                                     uint32_t messageBufLen,
+                                     void *pUnpackedBuf,
+                                     uint32_t unpackedBufLen,
+                                     nfapi_p4_p5_codec_config_t *config);
+
+int fapi_nr_p5_message_pack(void *pMessageBuf,
+                            uint32_t messageBufLen,
+                            void *pPackedBuf,
+                            uint32_t packedBufLen,
+                            nfapi_p4_p5_codec_config_t *config);
+
+int fapi_nr_p5_message_unpack(void *pMessageBuf,
+                              uint32_t messageBufLen,
+                              void *pUnpackedBuf,
+                              uint32_t unpackedBufLen,
+                              nfapi_p4_p5_codec_config_t *config);
+
+int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen);
+#endif // OPENAIRINTERFACE_NR_FAPI_H
diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
new file mode 100644
index 0000000000000000000000000000000000000000..feade4015b125e9ff16890a726a95fa3e846f02e
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+
+#ifndef OPENAIRINTERFACE_NR_FAPI_P5_H
+#define OPENAIRINTERFACE_NR_FAPI_P5_H
+#include "stdint.h"
+#include "nfapi_interface.h"
+
+uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_stop_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_stop_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+uint8_t pack_nr_error_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config);
+uint8_t unpack_nr_error_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config);
+#endif // OPENAIRINTERFACE_NR_FAPI_P5_H
diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..36d327a850a8cc65d292780f9067e3e8958e7007
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+
+#ifndef OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H
+#define OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H
+#include "stdio.h"
+#include "stdint.h"
+#include "nr_fapi.h"
+#include "nfapi/oai_integration/vendor_ext.h"
+
+#define EQ_TLV(_tlv_a, _tlv_b)        \
+  do {                                \
+    EQ(_tlv_a.tl.tag, _tlv_b.tl.tag); \
+    EQ(_tlv_a.value, _tlv_b.value);   \
+  } while (0)
+
+#define EQ(_a, _b)      \
+  do {                  \
+    if ((_a) != (_b)) { \
+      return false;     \
+    }                   \
+  } while (0)
+
+#define COPY_TL(_dst_tl, _src_tl)    \
+  do {                               \
+    _dst_tl.tag = _src_tl.tag;       \
+    _dst_tl.length = _src_tl.length; \
+  } while (0)
+
+#define COPY_TLV(_dst, _src)   \
+  do {                         \
+    COPY_TL(_dst.tl, _src.tl); \
+    _dst.value = _src.value;   \
+  } while (0)
+
+void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src);
+
+bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req);
+bool eq_param_response(const nfapi_nr_param_response_scf_t *unpacked_req, const nfapi_nr_param_response_scf_t *req);
+bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const nfapi_nr_config_request_scf_t *req);
+bool eq_config_response(const nfapi_nr_config_response_scf_t *unpacked_req, const nfapi_nr_config_response_scf_t *req);
+bool eq_start_request(const nfapi_nr_start_request_scf_t *unpacked_req, const nfapi_nr_start_request_scf_t *req);
+bool eq_start_response(const nfapi_nr_start_response_scf_t *unpacked_req, const nfapi_nr_start_response_scf_t *req);
+bool eq_stop_request(const nfapi_nr_stop_request_scf_t *unpacked_req, const nfapi_nr_stop_request_scf_t *req);
+bool eq_stop_indication(const nfapi_nr_stop_indication_scf_t *unpacked_req, const nfapi_nr_stop_indication_scf_t *req);
+bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, const nfapi_nr_error_indication_scf_t *req);
+
+void free_param_request(nfapi_nr_param_request_scf_t *msg);
+void free_param_response(nfapi_nr_param_response_scf_t *msg);
+void free_config_request(nfapi_nr_config_request_scf_t *msg);
+void free_config_response(nfapi_nr_config_response_scf_t *msg);
+void free_start_request(nfapi_nr_start_request_scf_t *msg);
+void free_start_response(nfapi_nr_start_response_scf_t *msg);
+void free_stop_request(nfapi_nr_stop_request_scf_t *msg);
+void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg);
+void free_error_indication(nfapi_nr_error_indication_scf_t *msg);
+
+void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst);
+void copy_param_response(const nfapi_nr_param_response_scf_t *src, nfapi_nr_param_response_scf_t *dst);
+void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_config_request_scf_t *dst);
+void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst);
+void copy_start_request(const nfapi_nr_start_request_scf_t *src, nfapi_nr_start_request_scf_t *dst);
+void copy_start_response(const nfapi_nr_start_response_scf_t *src, nfapi_nr_start_response_scf_t *dst);
+void copy_stop_request(const nfapi_nr_stop_request_scf_t *src, nfapi_nr_stop_request_scf_t *dst);
+void copy_stop_indication(const nfapi_nr_stop_indication_scf_t *src, nfapi_nr_stop_indication_scf_t *dst);
+void copy_error_indication(const nfapi_nr_error_indication_scf_t *src, nfapi_nr_error_indication_scf_t *dst);
+
+#endif // OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H
diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
new file mode 100644
index 0000000000000000000000000000000000000000..063f9589eff06fe3557177472a6f373cde4822f8
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
@@ -0,0 +1,1707 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nr_fapi.h"
+#include "nr_fapi_p5.h"
+#include "nr_fapi_p5_utils.h"
+#include "debug.h"
+
+bool isFAPIMessageIDValid(uint16_t id)
+{
+  // SCF 222.10.04 Table 3-5 PHY API message types
+  return (id >= NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST && id <= 0xFF) || id == NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE
+         || id == NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC || id == NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC
+         || id == NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO;
+}
+
+int fapi_nr_p5_message_header_unpack(uint8_t **pMessageBuf,
+                                     uint32_t messageBufLen,
+                                     void *pUnpackedBuf,
+                                     uint32_t unpackedBufLen,
+                                     nfapi_p4_p5_codec_config_t *config)
+{
+  uint8_t **pReadPackedMessage = pMessageBuf;
+  nfapi_p4_p5_message_header_t *header = pUnpackedBuf;
+  fapi_message_header_t fapi_msg;
+
+  if(pMessageBuf == NULL || pUnpackedBuf == NULL || messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)){
+    return -1;
+  }
+  uint8_t *end = *pMessageBuf + messageBufLen;
+  // process the header
+  int result =
+      (pull8(pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(pReadPackedMessage, &fapi_msg.opaque_handle, end)
+       && pull16(pReadPackedMessage, &header->message_id, end) && pull32(pReadPackedMessage, &fapi_msg.message_length, end));
+  DevAssert(fapi_msg.message_length <= 0xFFFF);
+  header->message_length = fapi_msg.message_length;
+  return (result);
+}
+
+uint8_t fapi_nr_p5_message_body_pack(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_NR_PHY_MSG_TYPE_PARAM_REQUEST:
+      result = 0;
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
+      result = pack_nr_param_response(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
+      result = pack_nr_config_request(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
+      result = pack_nr_config_response(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
+      result = pack_nr_start_request(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
+      result = pack_nr_start_response(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
+      result = pack_nr_stop_request(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
+      result = pack_nr_stop_indication(header, ppWritePackedMsg, end, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
+      result = pack_nr_error_indication(header, ppWritePackedMsg, end, config);
+      break;
+
+    default: {
+      AssertFatal(header->message_id >= 0x00 && header->message_id <= 0xFF,
+                  "FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message",
+                  header->message_id);
+      break;
+    }
+  }
+  return result;
+}
+
+int fapi_nr_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;
+  AssertFatal(isFAPIMessageIDValid(pMessageHeader->message_id),
+              "FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message",
+              pMessageHeader->message_id);
+  uint32_t packedMsgLen;
+  uint32_t packedBodyLen;
+  uint16_t packedMsgLen16;
+  AssertFatal(pMessageBuf != NULL && pPackedBuf != NULL, "P5 Pack supplied pointers are null");
+
+  uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen;
+  uint8_t *pPackedLengthField = &pWritePackedMessage[4];
+  uint8_t *pPacketBodyField = &pWritePackedMessage[8];
+  uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8];
+
+  uint8_t res = fapi_nr_p5_message_body_pack(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config);
+  AssertFatal(res >= 0, "fapi_nr_p5_message_body_pack error packing message body %d\n", res);
+
+  // PHY API message header
+  push8(1, &pWritePackedMessage, pPackMessageEnd); // Number of messages
+  push8(0, &pWritePackedMessage, pPackMessageEnd); // Opaque handle
+
+  // PHY API Message structure
+  push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd); // Message type ID
+
+  // check for a valid message length
+  packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField);
+  packedBodyLen = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField);
+  packedMsgLen16 = (uint16_t)packedBodyLen;
+  if (pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST
+      || pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_START_REQUEST
+      || pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST
+      || pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION) {
+    // These messages don't have a body, length is 0
+    packedMsgLen16 = 0;
+  }
+  AssertFatal(packedMsgLen <= 0xFFFF && packedMsgLen <= packedBufLen,
+              "Packed message 0x%02x length error %d, buffer supplied %d\n",
+              pMessageHeader->message_id,
+              packedMsgLen,
+              packedBufLen);
+  // Update the message length in the header
+  if (!push32(packedMsgLen16, &pPackedLengthField, pPackMessageEnd))
+    return -1;
+
+  // return the packed length
+  return (int)(packedMsgLen);
+}
+
+int fapi_nr_p5_message_unpack(void *pMessageBuf,
+                              uint32_t messageBufLen,
+                              void *pUnpackedBuf,
+                              uint32_t unpackedBufLen,
+                              nfapi_p4_p5_codec_config_t *config)
+{
+  fapi_message_header_t *pMessageHeader = pUnpackedBuf;
+  uint8_t *pReadPackedMessage = pMessageBuf;
+
+  AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P5 unpack supplied pointers are null");
+  uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen;
+  AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t),
+              "P5 unpack supplied message buffer is too small %d, %d\n",
+              messageBufLen,
+              unpackedBufLen);
+  // clean the supplied buffer for - tag value blanking
+  (void)memset(pUnpackedBuf, 0, unpackedBufLen);
+  if (fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0)
+      < 0) {
+    // failed to read the header
+    return -1;
+  }
+
+  int result = -1;
+
+  if (check_nr_fapi_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_NR_PHY_MSG_TYPE_PARAM_REQUEST:
+      // PARAM request has no body;
+      result = 0;
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
+      result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
+      result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
+      result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
+      result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
+      result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
+      result = unpack_nr_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
+      result = unpack_nr_stop_indication(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
+      result = unpack_nr_error_indication(&pReadPackedMessage, end, pMessageHeader, config);
+      break;
+
+    default:
+      if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) {
+        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;
+}
+
+int check_nr_fapi_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen)
+{
+  int retLen = 0;
+  /**  NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST=  0x00,
+    NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE= 0x01,
+    NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST= 0x02,
+    NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE=0X03,
+    NFAPI_NR_PHY_MSG_TYPE_START_REQUEST=  0X04,
+    NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST=   0X05,
+    NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION=0X06,
+    NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION=0X07
+    */
+  // check for size of nFAPI struct without the nFAPI specific parameters
+  switch (msgId) {
+    case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST:
+      if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
+      if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t))
+        retLen = sizeof(nfapi_nr_param_request_scf_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
+      if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t) - sizeof(nfapi_nr_nfapi_t))
+        retLen = sizeof(nfapi_nr_config_request_scf_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
+      if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(nfapi_nr_config_response_scf_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
+      if (unpackedBufLen >= sizeof(nfapi_nr_start_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
+      if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
+      if (unpackedBufLen >= sizeof(nfapi_nr_stop_request_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
+      if (unpackedBufLen >= sizeof(nfapi_nr_stop_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
+      if (unpackedBufLen >= sizeof(nfapi_nr_error_indication_scf_t) - sizeof(nfapi_vendor_extension_tlv_t))
+        retLen = sizeof(fapi_message_header_t);
+
+      break;
+    default:
+      NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId);
+      break;
+  }
+
+  return retLen;
+}
+
+uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
+  return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
+  return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  printf("\nRUNNING pack_param_response\n");
+  nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
+  uint8_t retval = push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end);
+  retval &= pack_nr_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG,
+                        &(pNfapiMsg->cell_param.release_capability),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG,
+                           &(pNfapiMsg->cell_param.phy_state),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG,
+                           &(pNfapiMsg->cell_param.skip_blank_dl_config),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG,
+                           &(pNfapiMsg->cell_param.skip_blank_ul_config),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG,
+                           &(pNfapiMsg->cell_param.num_config_tlvs_to_report),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value);
+
+  for (int i = 0; i < pNfapiMsg->cell_param.num_config_tlvs_to_report.value; ++i) {
+    /*retval &= pack_nr_tlv(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag,
+                          &(pNfapiMsg->cell_param.config_tlvs_to_report_list[i]),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint8_tlv_value);*/
+    retval &= push16(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag, ppWritePackedMsg, end);
+    retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.length, ppWritePackedMsg, end);
+    retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].value, ppWritePackedMsg, end);
+    // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+    int padding = get_tlv_padding(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.length);
+    NFAPI_TRACE(NFAPI_TRACE_DEBUG,
+                "TLV 0x%x with padding of %d bytes\n",
+                pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag,
+                padding);
+    if (padding != 0) {
+      memset(*ppWritePackedMsg, 0, padding);
+      (*ppWritePackedMsg) += padding;
+    }
+  }
+
+  retval &= pack_nr_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG,
+                        &(pNfapiMsg->carrier_param.cyclic_prefix),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
+                           &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG,
+                           &(pNfapiMsg->carrier_param.supported_bandwidth_dl),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
+                           &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG,
+                           &(pNfapiMsg->carrier_param.supported_bandwidth_ul),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG,
+                           &(pNfapiMsg->pdcch_param.cce_mapping_type),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
+                           &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
+                           &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG,
+                           &(pNfapiMsg->pdcch_param.pdcch_mu_mimo),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG,
+                           &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG,
+                           &(pNfapiMsg->pdcch_param.max_pdcch_per_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG,
+                           &(pNfapiMsg->pucch_param.pucch_formats),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG,
+                           &(pNfapiMsg->pucch_param.max_pucchs_per_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_mapping_type),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_allocation_types),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_cbg),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG,
+                           &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
+                           &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG,
+                           &(pNfapiMsg->pdsch_param.supported_max_modulation_order_dl),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG,
+                           &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG,
+                           &(pNfapiMsg->pdsch_param.premption_support),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG,
+                           &(pNfapiMsg->pdsch_param.pdsch_non_slot_support),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG,
+                           &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG,
+                           &(pNfapiMsg->pusch_param.uci_only_pusch),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_frequency_hopping),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_dmrs_config_types),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_dmrs_max_len),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_cbg),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_mapping_type),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_allocation_types),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
+                           &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
+                           &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
+                           &(pNfapiMsg->pusch_param.supported_modulation_order_ul),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG,
+                           &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG,
+                           &(pNfapiMsg->pusch_param.dfts_ofdm_support),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
+                           &(pNfapiMsg->pusch_param.pusch_aggregation_factor),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG,
+                           &(pNfapiMsg->prach_param.prach_long_formats),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG,
+                           &(pNfapiMsg->prach_param.prach_short_formats),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG,
+                           &(pNfapiMsg->prach_param.prach_restricted_sets),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
+                           &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
+                           &(pNfapiMsg->measurement_param.rssi_measurement_support),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            &&
+            // config:
+            pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG,
+                        &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_ipv4_address_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG,
+                           &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_ipv6_address_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG,
+                           &(pNfapiMsg->nfapi_config.p7_vnf_port),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG,
+                           &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_ipv4_address_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG,
+                           &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_ipv6_address_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG,
+                           &(pNfapiMsg->nfapi_config.p7_pnf_port),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint16_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG,
+                           &(pNfapiMsg->nfapi_config.timing_window),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG,
+                           &(pNfapiMsg->nfapi_config.timing_info_mode),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG,
+                           &(pNfapiMsg->nfapi_config.timing_info_period),
+                           ppWritePackedMsg,
+                           end,
+                           &pack_uint8_tlv_value)
+            && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+  return retval;
+}
+
+static uint8_t unpack_config_tlvs_to_report(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
+{
+  uint8_t *pStartOfValue = *ppReadPackedMsg;
+  nfapi_nr_cell_param_t *cellParamTable = (nfapi_nr_cell_param_t *)tlv;
+  uint8_t retval = pull16(ppReadPackedMsg, &cellParamTable->num_config_tlvs_to_report.value, end);
+
+  // check if the length was right;
+  if (cellParamTable->num_config_tlvs_to_report.tl.length != (*ppReadPackedMsg - pStartOfValue)) {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR,
+                "Warning tlv tag 0x%x length %d not equal to unpack %ld\n",
+                cellParamTable->num_config_tlvs_to_report.tl.tag,
+                cellParamTable->num_config_tlvs_to_report.tl.length,
+                (*ppReadPackedMsg - pStartOfValue));
+  }
+  // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+  int padding = get_tlv_padding(cellParamTable->num_config_tlvs_to_report.tl.length);
+  if (padding != 0) {
+    (*ppReadPackedMsg) += padding;
+  }
+
+  // after this value, get the tlv list
+  cellParamTable->config_tlvs_to_report_list = calloc(cellParamTable->num_config_tlvs_to_report.value, sizeof(nfapi_uint8_tlv_t *));
+
+  for (int i = 0; i < cellParamTable->num_config_tlvs_to_report.value; ++i) {
+    pull16(ppReadPackedMsg, &cellParamTable->config_tlvs_to_report_list[i].tl.tag, end);
+    pull8(ppReadPackedMsg, (uint8_t *)&cellParamTable->config_tlvs_to_report_list[i].tl.length, end);
+    pull8(ppReadPackedMsg, &cellParamTable->config_tlvs_to_report_list[i].value, end);
+    // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+    padding = get_tlv_padding(cellParamTable->config_tlvs_to_report_list[i].tl.length);
+    if (padding != 0) {
+      (*ppReadPackedMsg) += padding;
+    }
+  }
+  return retval;
+}
+
+uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
+  unpack_tlv_t unpack_fns[] = {
+      {NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), &unpack_uint16_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param), &unpack_config_tlvs_to_report},
+
+      {NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
+       &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
+       &unpack_uint16_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
+       &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
+       &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
+       &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
+       &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
+       &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
+       &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG,
+       &(pNfapiMsg->pdsch_param.supported_max_modulation_order_dl),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
+       &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
+       &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
+       &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
+       &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
+       &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
+       &(pNfapiMsg->pusch_param.supported_modulation_order_ul),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
+       &(pNfapiMsg->pusch_param.pusch_aggregation_factor),
+       &unpack_uint8_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint16_tlv_value},
+      {NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value},
+      {NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
+       &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
+       &unpack_uint8_tlv_value},
+
+      {NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
+       &(pNfapiMsg->measurement_param.rssi_measurement_support),
+       &unpack_uint8_tlv_value},
+      // config
+      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value},
+      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value},
+      {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value},
+      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value},
+      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value},
+      {NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value},
+  };
+  // print ppReadPackedMsg
+  uint8_t *ptr = *ppReadPackedMsg;
+  printf("\n Read message unpack_param_response:   ");
+
+  while (ptr < end) {
+    printf(" 0x%02x", *ptr);
+    ptr++;
+  }
+
+  printf("\n");
+  return (pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end)
+          && unpack_nr_tlv_list(unpack_fns,
+                                sizeof(unpack_fns) / sizeof(unpack_tlv_t),
+                                ppReadPackedMsg,
+                                end,
+                                config,
+                                &pNfapiMsg->vendor_extension));
+}
+
+uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg;
+
+  nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
+  uint8_t numTLVs = 0;
+  *ppWritePackedMsg += 1; // Advance the buffer past the 'location' to push numTLVs
+  // START Carrier Configuration
+  uint8_t retval = pack_nr_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG,
+                               &(pNfapiMsg->carrier_config.dl_bandwidth),
+                               ppWritePackedMsg,
+                               end,
+                               &pack_uint16_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG,
+                        &(pNfapiMsg->carrier_config.dl_frequency),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint32_tlv_value);
+  numTLVs++;
+
+  retval &= push16(NFAPI_NR_CONFIG_DL_K0_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_k0[0].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_k0[1].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_k0[2].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_k0[3].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_k0[4].value, ppWritePackedMsg, end)
+            && push16(0, ppWritePackedMsg, end); // Padding
+  numTLVs++;
+
+  retval &= push16(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_grid_size[0].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_grid_size[1].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_grid_size[2].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_grid_size[3].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.dl_grid_size[4].value, ppWritePackedMsg, end)
+            && push16(0, ppWritePackedMsg, end); // Padding
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG,
+                        &(pNfapiMsg->carrier_config.num_tx_ant),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG,
+                        &(pNfapiMsg->carrier_config.uplink_bandwidth),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG,
+                        &(pNfapiMsg->carrier_config.uplink_frequency),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint32_tlv_value);
+  numTLVs++;
+
+  retval &= push16(NFAPI_NR_CONFIG_UL_K0_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_k0[0].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_k0[1].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_k0[2].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_k0[3].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_k0[4].value, ppWritePackedMsg, end)
+            && push16(0, ppWritePackedMsg, end); // Padding
+  numTLVs++;
+
+  retval &= push16(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_grid_size[0].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_grid_size[1].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_grid_size[2].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_grid_size[3].value, ppWritePackedMsg, end)
+            && push16(pNfapiMsg->carrier_config.ul_grid_size[4].value, ppWritePackedMsg, end)
+            && push16(0, ppWritePackedMsg, end); // Padding
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG,
+                        &(pNfapiMsg->carrier_config.num_rx_ant),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+#ifndef ENABLE_AERIAL
+  // TLV not supported by Aerial L1
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_FREQUENCY_SHIFT_7P5KHZ_TAG,
+                        &(pNfapiMsg->carrier_config.frequency_shift_7p5khz),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+#endif
+  // END Carrier Configuration
+
+  // START Cell Configuration
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG,
+                        &(pNfapiMsg->cell_config.phy_cell_id),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG,
+                        &(pNfapiMsg->cell_config.frame_duplex_type),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  // END Cell Configuration
+
+  // START SSB Configuration
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG,
+                        &(pNfapiMsg->ssb_config.ss_pbch_power),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint32_tlv_value);
+  numTLVs++;
+
+#ifndef ENABLE_AERIAL
+  // TLV not supported by Aerial L1
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG,
+                        &(pNfapiMsg->ssb_config.bch_payload),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+#endif
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG,
+                        &(pNfapiMsg->ssb_config.scs_common),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  // END SSB Configuration
+
+  // START PRACH Configuration
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG,
+                        &(pNfapiMsg->prach_config.prach_sequence_length),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG,
+                        &(pNfapiMsg->prach_config.prach_sub_c_spacing),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG,
+                        &(pNfapiMsg->prach_config.restricted_set_config),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG,
+                        &(pNfapiMsg->prach_config.num_prach_fd_occasions),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG,
+                        &(pNfapiMsg->prach_config.prach_ConfigurationIndex),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  for (int i = 0; i < pNfapiMsg->prach_config.num_prach_fd_occasions.value; i++) {
+    nfapi_nr_num_prach_fd_occasions_t prach_fd_occasion = pNfapiMsg->prach_config.num_prach_fd_occasions_list[i];
+
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG,
+                          &(prach_fd_occasion.prach_root_sequence_index),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint16_tlv_value);
+    numTLVs++;
+
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG,
+                          &(prach_fd_occasion.num_root_sequences),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint8_tlv_value);
+    numTLVs++;
+
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_K1_TAG, &(prach_fd_occasion.k1), ppWritePackedMsg, end, &pack_uint16_tlv_value);
+    numTLVs++;
+
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG,
+                          &(prach_fd_occasion.prach_zero_corr_conf),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint8_tlv_value);
+    numTLVs++;
+
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG,
+                          &(prach_fd_occasion.num_unused_root_sequences),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint16_tlv_value);
+    numTLVs++;
+    for (int k = 0; k < prach_fd_occasion.num_unused_root_sequences.value; k++) {
+      prach_fd_occasion.unused_root_sequences_list[k].tl.tag = NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG;
+      retval &= pack_nr_tlv(NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG,
+                            &(prach_fd_occasion.unused_root_sequences_list[k]),
+                            ppWritePackedMsg,
+                            end,
+                            &pack_uint16_tlv_value);
+      numTLVs++;
+    }
+  }
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG,
+                        &(pNfapiMsg->prach_config.ssb_per_rach),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band.tl.tag = NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG;
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
+                        &(pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  // END PRACH Configuration
+  // START SSB Table
+#ifndef ENABLE_AERIAL
+  // TLV not supported by Aerial L1
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG,
+                        &(pNfapiMsg->ssb_table.ssb_offset_point_a),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+#endif
+  retval &=
+      pack_nr_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG,
+                        &(pNfapiMsg->ssb_table.ssb_subcarrier_offset),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  /* was unused */
+  pNfapiMsg->ssb_table.MIB.tl.tag = NFAPI_NR_CONFIG_MIB_TAG;
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value);
+  numTLVs++;
+  // SCF222.10.02 Table 3-25 : If included there must be two instances of this TLV
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG,
+                        &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint32_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG,
+                        &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint32_tlv_value);
+  numTLVs++;
+#ifndef ENABLE_AERIAL
+  // TLV not supported by Aerial L1
+  for (int i = 0; i < 64; i++) {
+    // SCF222.10.02 Table 3-25 : If included there must be 64 instances of this TLV
+    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_BEAM_ID_TAG,
+                          &(pNfapiMsg->ssb_table.ssb_beam_id_list[i].beam_id),
+                          ppWritePackedMsg,
+                          end,
+                          &pack_uint8_tlv_value);
+    numTLVs++;
+  }
+
+  // END SSB Table
+  // START TDD Table
+  retval &=
+      pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value);
+  numTLVs++;
+  const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+  // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04
+  uint8_t cyclicprefix = 1;
+  bool normal_CP = cyclicprefix ? false : true;
+  // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
+  uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12;
+  for (int i = 0; i < slotsperframe[pNfapiMsg->ssb_config.scs_common.value]; i++) { // TODO check right number of slots
+    for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change?
+      retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG,
+                            &pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config,
+                            ppWritePackedMsg,
+                            end,
+                            &pack_uint8_tlv_value);
+      numTLVs++;
+    }
+  }
+
+  // END TDD Table
+#endif
+  // START Measurement Config
+  // SCF222.10.02 Table 3-27 : Contains only one TLV and is currently unused
+  pNfapiMsg->measurement_config.rssi_measurement.tl.tag = NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG;
+  pNfapiMsg->measurement_config.rssi_measurement.value = 1;
+  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG,
+                        &(pNfapiMsg->measurement_config.rssi_measurement),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  // END Measurement Config
+
+  // START Digital Beam Table (DBT) PDU
+  // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_dbt_pdu_t, currently unused
+  // END Digital Beam Table (DBT) PDU
+
+  // START Precoding Matrix (PM) PDU
+  // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL
+  // is 0xA011 END Precoding Matrix (PM) PDU
+#ifndef ENABLE_AERIAL
+  // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG,
+                        &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_ipv4_address_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG,
+                        &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_ipv6_address_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG,
+                        &(pNfapiMsg->nfapi_config.p7_vnf_port),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint16_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG,
+                        &(pNfapiMsg->nfapi_config.timing_window),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG,
+                        &(pNfapiMsg->nfapi_config.timing_info_mode),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+
+  retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG,
+                        &(pNfapiMsg->nfapi_config.timing_info_period),
+                        ppWritePackedMsg,
+                        end,
+                        &pack_uint8_tlv_value);
+  numTLVs++;
+  // END nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states
+
+  if (pNfapiMsg->vendor_extension != 0 && config != 0) {
+    retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+    NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing CONFIG.request vendor_extension_tlv %d\n", pNfapiMsg->vendor_extension->tag);
+    numTLVs++;
+  }
+#endif
+  pNfapiMsg->num_tlv = numTLVs;
+  retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
+  return retval;
+}
+
+uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  // Helper vars for indexed TLVs
+  int prach_root_seq_idx = 0;
+  int unused_root_seq_idx = 0;
+  int ssb_mask_idx = 0;
+  int config_beam_idx = 0;
+  int tdd_periodicity_idx = 0;
+  int symbol_per_slot_idx = 0;
+  nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
+  // unpack TLVs
+
+  unpack_tlv_t unpack_fns[] = {
+      {NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value},
+      {NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value},
+      {NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_FREQUENCY_SHIFT_7P5KHZ_TAG, &(pNfapiMsg->carrier_config.frequency_shift_7p5khz), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value},
+      {NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG, &(pNfapiMsg->ssb_config.bch_payload), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG, &(pNfapiMsg->prach_config.prach_ConfigurationIndex), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, NULL, &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, NULL, &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_K1_TAG, NULL, &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, NULL, &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG, NULL, &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG, NULL, &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
+       &(pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value},
+      {NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value},
+      {NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value},
+      {NFAPI_NR_CONFIG_BEAM_ID_TAG, &(pNfapiMsg->ssb_table.ssb_beam_id_list[0].beam_id), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SS_PBCH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
+       &(pNfapiMsg->ssb_table.ss_pbch_multiple_carriers_in_a_band),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_MULTIPLE_CELLS_SS_PBCH_IN_A_CARRIER_TAG,
+       &(pNfapiMsg->ssb_table.multiple_cells_ss_pbch_in_a_carrier),
+       &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_uint8_tlv_value},
+      {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value},
+      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value},
+      {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value},
+      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value},
+      {NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}};
+
+  pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end);
+
+  pNfapiMsg->vendor_extension = malloc(sizeof(&(pNfapiMsg->vendor_extension)));
+  nfapi_tl_t generic_tl;
+  uint8_t numBadTags = 0;
+  unsigned long 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 = 0;
+    for (idx = 0; idx < sizeof(unpack_fns) / sizeof(unpack_tlv_t); ++idx) {
+      if (unpack_fns[idx].tag == generic_tl.tag) { // match the extracted tag value with all the tags in unpack_fn list
+        pStartOfValue = *ppReadPackedMsg;
+        tagMatch = 1;
+        nfapi_tl_t *tl = (nfapi_tl_t *)(unpack_fns[idx].tlv);
+        if (tl) {
+          tl->tag = generic_tl.tag;
+          tl->length = generic_tl.length;
+        }
+        int result = 0;
+        switch (generic_tl.tag) {
+          case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG:
+            pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->prach_config.num_prach_fd_occasions, ppReadPackedMsg, end);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc(
+                pNfapiMsg->prach_config.num_prach_fd_occasions.value * sizeof(nfapi_nr_num_prach_fd_occasions_t));
+            prach_root_seq_idx = 0;
+            break;
+          case NFAPI_NR_CONFIG_SCS_COMMON_TAG:
+            pNfapiMsg->ssb_config.scs_common.tl.tag = generic_tl.tag;
+            pNfapiMsg->ssb_config.scs_common.tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->ssb_config.scs_common, ppReadPackedMsg, end);
+            const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+            // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04
+            uint8_t cyclicprefix = 1;
+            bool normal_CP = cyclicprefix ? false : true;
+            // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
+            uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12;
+
+            pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc(
+                slotsperframe[pNfapiMsg->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t));
+
+            for (int i = 0; i < slotsperframe[pNfapiMsg->ssb_config.scs_common.value]; i++) {
+              pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list =
+                  (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(number_of_symbols_per_slot
+                                                                  * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t));
+            }
+            break;
+          case NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG:
+            unpack_fns[idx].tlv =
+                &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index.tl.tag =
+                generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index.tl.length =
+                generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(
+                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index,
+                ppReadPackedMsg,
+                end);
+            break;
+          case NFAPI_NR_CONFIG_K1_TAG:
+            unpack_fns[idx].tlv = &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1.tl.tag = generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1.tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1,
+                                                    ppReadPackedMsg,
+                                                    end);
+            break;
+          case NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG:
+            unpack_fns[idx].tlv = &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf.tl.tag = generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf.tl.length =
+                generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(
+                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf,
+                ppReadPackedMsg,
+                end);
+            break;
+          case NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG:
+            unpack_fns[idx].tlv = &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences.tl.tag = generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences.tl.length =
+                generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(
+                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences,
+                ppReadPackedMsg,
+                end);
+            break;
+          case NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG:
+            unpack_fns[idx].tlv =
+                &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.tl.tag =
+                generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.tl.length =
+                generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(
+                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences,
+                ppReadPackedMsg,
+                end);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].unused_root_sequences_list =
+                (nfapi_uint8_tlv_t *)malloc(
+                    pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.value
+                    * sizeof(nfapi_uint8_tlv_t));
+            unused_root_seq_idx = 0;
+            break;
+          case NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG:
+            unpack_fns[idx].tlv = &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
+                                        .unused_root_sequences_list[unused_root_seq_idx]);
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
+                .unused_root_sequences_list[unused_root_seq_idx]
+                .tl.tag = generic_tl.tag;
+            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
+                .unused_root_sequences_list[unused_root_seq_idx]
+                .tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
+                                                         .unused_root_sequences_list[unused_root_seq_idx],
+                                                    ppReadPackedMsg,
+                                                    end);
+            unused_root_seq_idx++;
+            // last tlv of the list
+            if (unused_root_seq_idx
+                >= pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.value) {
+              prach_root_seq_idx++;
+              unused_root_seq_idx = 0;
+            }
+            break;
+          case NFAPI_NR_CONFIG_SSB_MASK_TAG:
+            pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask.tl.tag = generic_tl.tag;
+            pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask.tl.length = generic_tl.length;
+            result = unpack_uint32_tlv_value(&pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask, ppReadPackedMsg, end);
+            ssb_mask_idx++;
+            break;
+          case NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG:
+            for (int i = 0; i < 5; i++) {
+              pNfapiMsg->carrier_config.dl_grid_size[i].tl.tag = generic_tl.tag;
+              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.dl_grid_size[i], ppReadPackedMsg, end);
+            }
+            break;
+          case NFAPI_NR_CONFIG_DL_K0_TAG:
+            for (int i = 0; i < 5; i++) {
+              pNfapiMsg->carrier_config.dl_k0[i].tl.tag = generic_tl.tag;
+              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.dl_k0[i], ppReadPackedMsg, end);
+            }
+            break;
+          case NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG:
+            for (int i = 0; i < 5; i++) {
+              pNfapiMsg->carrier_config.ul_grid_size[i].tl.tag = generic_tl.tag;
+              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.ul_grid_size[i], ppReadPackedMsg, end);
+            }
+            break;
+          case NFAPI_NR_CONFIG_UL_K0_TAG:
+            for (int i = 0; i < 5; i++) {
+              pNfapiMsg->carrier_config.ul_k0[i].tl.tag = generic_tl.tag;
+              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.ul_k0[i], ppReadPackedMsg, end);
+            }
+            break;
+          case NFAPI_NR_CONFIG_BEAM_ID_TAG:
+            pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id.tl.tag = generic_tl.tag;
+            pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id.tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id,
+                                                    ppReadPackedMsg,
+                                                    end);
+            config_beam_idx++;
+            break;
+          case NFAPI_NR_CONFIG_SLOT_CONFIG_TAG:
+            unpack_fns[idx].tlv = &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
+                                        .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
+                                        .slot_config);
+            pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
+                .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
+                .slot_config.tl.tag = generic_tl.tag;
+            pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
+                .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
+                .slot_config.tl.length = generic_tl.length;
+            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
+                                                         .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
+                                                         .slot_config,
+                                                    ppReadPackedMsg,
+                                                    end);
+            symbol_per_slot_idx = (symbol_per_slot_idx + 1) % number_of_symbols_per_slot;
+            if (symbol_per_slot_idx == 0) {
+              tdd_periodicity_idx++;
+            }
+            break;
+          default:
+            result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end);
+            break;
+        }
+        // update tl pointer with updated value, if it was set in the switch (it was inside lists)
+        if (!tl) {
+          tl = (nfapi_tl_t *)(unpack_fns[idx].tlv);
+          tl->tag = generic_tl.tag;
+          tl->length = generic_tl.length;
+        }
+        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 %lu\n",
+                      tl->tag,
+                      tl->length,
+                      (*ppReadPackedMsg - pStartOfValue));
+
+        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
+        int padding = get_tlv_padding(tl->length);
+        NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x length %d with padding of %d bytes\n", tl->tag, tl->length, padding);
+        if (padding != 0)
+          (*ppReadPackedMsg) += padding;
+      }
+    }
+
+    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, &(pNfapiMsg->vendor_extension));
+        if (result == 0) {
+          // got to 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;
+            int padding = get_tlv_padding(generic_tl.length);
+            (*ppReadPackedMsg) += padding;
+          } 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;
+          int padding = get_tlv_padding(generic_tl.length);
+          (*ppReadPackedMsg) += padding;
+        } else {
+          // go to the end
+          return 0;
+        }
+      }
+    }
+  }
+  struct sockaddr_in vnf_p7_sockaddr;
+  memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), 4);
+
+  printf("[PNF] vnf p7 %s:%d\n", inet_ntoa(vnf_p7_sockaddr.sin_addr), pNfapiMsg->nfapi_config.p7_vnf_port.value);
+  return 1;
+}
+
+uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg;
+  uint8_t retval = push8(pNfapiMsg->error_code, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->num_invalid_tlvs, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_idle, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_running, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->num_missing_tlvs, ppWritePackedMsg, end);
+
+  // pack lists
+  for (int i = 0; i < pNfapiMsg->num_invalid_tlvs; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_list[i]);
+    pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
+  }
+  for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_idle; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_idle_list[i]);
+    pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
+  }
+  for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_running; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_running_list[i]);
+    pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
+  }
+  for (int i = 0; i < pNfapiMsg->num_missing_tlvs; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->missing_tlvs_list[i]);
+    pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
+  }
+
+  retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+  return retval;
+}
+
+uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_config_response_scf_t *nfapi_resp = (nfapi_nr_config_response_scf_t *)msg;
+  uint8_t retval = pull8(ppReadPackedMsg, &nfapi_resp->error_code, end)
+                   && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs, end)
+                   && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_idle, end)
+                   && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_running, end)
+                   && pull8(ppReadPackedMsg, &nfapi_resp->num_missing_tlvs, end);
+  // First unpack the invalid_tlvs_list
+  // allocate the memory
+  nfapi_resp->invalid_tlvs_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->invalid_tlvs_configured_in_idle_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->invalid_tlvs_configured_in_running_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->missing_tlvs_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+
+  // unpack the TLV lists
+  unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_list, nfapi_resp->num_invalid_tlvs, ppReadPackedMsg, end);
+  unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_idle_list,
+                             nfapi_resp->num_invalid_tlvs_configured_in_idle,
+                             ppReadPackedMsg,
+                             end);
+  unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_running_list,
+                             nfapi_resp->num_invalid_tlvs_configured_in_running,
+                             ppReadPackedMsg,
+                             end);
+  unpack_nr_generic_tlv_list(nfapi_resp->missing_tlvs_list, nfapi_resp->num_missing_tlvs, ppReadPackedMsg, end);
+  // TODO: Process and use the invalid TLVs fields
+  retval &= unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(nfapi_resp->vendor_extension));
+  return retval;
+}
+
+uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
+  return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
+  return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
+  return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end)
+          && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+}
+
+uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
+  return (pull8(ppReadPackedMsg, (uint8_t *)&pNfapiMsg->error_code, end)
+          && unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
+}
+
+uint8_t pack_nr_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_stop_request_scf_t *pNfapiMsg = (nfapi_nr_stop_request_scf_t *)msg;
+  return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+uint8_t unpack_nr_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_stop_request_scf_t *pNfapiMsg = (nfapi_nr_stop_request_scf_t *)msg;
+  return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+uint8_t pack_nr_stop_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_stop_indication_scf_t *pNfapiMsg = (nfapi_nr_stop_indication_scf_t *)msg;
+  return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+}
+
+uint8_t unpack_nr_stop_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_stop_indication_scf_t *pNfapiMsg = (nfapi_nr_stop_indication_scf_t *)msg;
+  return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+}
+
+uint8_t pack_nr_error_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg;
+  uint8_t retval = push16(pNfapiMsg->sfn, ppWritePackedMsg, end);
+  retval &= push16(pNfapiMsg->slot, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->message_id, ppWritePackedMsg, end);
+  retval &= push8(pNfapiMsg->error_code, ppWritePackedMsg, end);
+
+  retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+  return retval;
+}
+
+uint8_t unpack_nr_error_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+{
+  nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg;
+  uint8_t retval = pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end);
+  retval &= pull16(ppReadPackedMsg, &pNfapiMsg->slot, end);
+  retval &= pull8(ppReadPackedMsg, &pNfapiMsg->message_id, end);
+  retval &= pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end);
+  retval &= unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+  return retval;
+}
diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..abcbc3e9717a6578810fb8175f2085961076b137
--- /dev/null
+++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c
@@ -0,0 +1,971 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nr_fapi_p5_utils.h"
+
+void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_vendor_extension_tlv_t *src)
+{
+  nfapi_tl_t *dst_tlv = (nfapi_tl_t *)dst;
+  nfapi_tl_t *src_tlv = (nfapi_tl_t *)src;
+
+  switch (dst_tlv->tag) {
+    case VENDOR_EXT_TLV_2_TAG: {
+      vendor_ext_tlv_2 *dst_ve = (vendor_ext_tlv_2 *)dst_tlv;
+      vendor_ext_tlv_2 *src_ve = (vendor_ext_tlv_2 *)src_tlv;
+
+      dst_ve->dummy = src_ve->dummy;
+    } break;
+    case VENDOR_EXT_TLV_1_TAG: {
+      vendor_ext_tlv_1 *dst_ve = (vendor_ext_tlv_1 *)dst_tlv;
+      vendor_ext_tlv_1 *src_ve = (vendor_ext_tlv_1 *)src_tlv;
+
+      dst_ve->dummy = src_ve->dummy;
+    } break;
+  }
+}
+
+bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  return true;
+}
+
+bool eq_param_response(const nfapi_nr_param_response_scf_t *unpacked_req, const nfapi_nr_param_response_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  EQ(unpacked_req->num_tlv, req->num_tlv);
+  EQ(unpacked_req->error_code, req->error_code);
+
+  EQ_TLV(unpacked_req->cell_param.release_capability, req->cell_param.release_capability);
+
+  EQ_TLV(unpacked_req->cell_param.phy_state, req->cell_param.phy_state);
+
+  EQ_TLV(unpacked_req->cell_param.skip_blank_dl_config, req->cell_param.skip_blank_dl_config);
+
+  EQ_TLV(unpacked_req->cell_param.skip_blank_ul_config, req->cell_param.skip_blank_ul_config);
+
+  EQ_TLV(unpacked_req->cell_param.num_config_tlvs_to_report, req->cell_param.num_config_tlvs_to_report);
+
+  for (int i = 0; i < unpacked_req->cell_param.num_config_tlvs_to_report.value; ++i) {
+    EQ_TLV(unpacked_req->cell_param.config_tlvs_to_report_list[i], req->cell_param.config_tlvs_to_report_list[i]);
+  }
+
+  EQ_TLV(unpacked_req->carrier_param.cyclic_prefix, req->carrier_param.cyclic_prefix);
+
+  EQ_TLV(unpacked_req->carrier_param.supported_subcarrier_spacings_dl, req->carrier_param.supported_subcarrier_spacings_dl);
+
+  EQ_TLV(unpacked_req->carrier_param.supported_bandwidth_dl, req->carrier_param.supported_bandwidth_dl);
+
+  EQ_TLV(unpacked_req->carrier_param.supported_subcarrier_spacings_ul, req->carrier_param.supported_subcarrier_spacings_ul);
+
+  EQ_TLV(unpacked_req->carrier_param.supported_bandwidth_ul, req->carrier_param.supported_bandwidth_ul);
+
+  EQ_TLV(unpacked_req->pdcch_param.cce_mapping_type, req->pdcch_param.cce_mapping_type);
+
+  EQ_TLV(unpacked_req->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot,
+         req->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot);
+
+  EQ_TLV(unpacked_req->pdcch_param.coreset_precoder_granularity_coreset, req->pdcch_param.coreset_precoder_granularity_coreset);
+
+  EQ_TLV(unpacked_req->pdcch_param.pdcch_mu_mimo, req->pdcch_param.pdcch_mu_mimo);
+
+  EQ_TLV(unpacked_req->pdcch_param.pdcch_precoder_cycling, req->pdcch_param.pdcch_precoder_cycling);
+
+  EQ_TLV(unpacked_req->pdcch_param.max_pdcch_per_slot, req->pdcch_param.max_pdcch_per_slot);
+
+  EQ_TLV(unpacked_req->pucch_param.pucch_formats, req->pucch_param.pucch_formats);
+
+  EQ_TLV(unpacked_req->pucch_param.max_pucchs_per_slot, req->pucch_param.max_pucchs_per_slot);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_mapping_type, req->pdsch_param.pdsch_mapping_type);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_allocation_types, req->pdsch_param.pdsch_allocation_types);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_vrb_to_prb_mapping, req->pdsch_param.pdsch_vrb_to_prb_mapping);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_cbg, req->pdsch_param.pdsch_cbg);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_config_types, req->pdsch_param.pdsch_dmrs_config_types);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_max_length, req->pdsch_param.pdsch_dmrs_max_length);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_additional_pos, req->pdsch_param.pdsch_dmrs_additional_pos);
+
+  EQ_TLV(unpacked_req->pdsch_param.max_pdsch_tbs_per_slot, req->pdsch_param.max_pdsch_tbs_per_slot);
+
+  EQ_TLV(unpacked_req->pdsch_param.max_number_mimo_layers_pdsch, req->pdsch_param.max_number_mimo_layers_pdsch);
+
+  EQ_TLV(unpacked_req->pdsch_param.supported_max_modulation_order_dl, req->pdsch_param.supported_max_modulation_order_dl);
+
+  EQ_TLV(unpacked_req->pdsch_param.max_mu_mimo_users_dl, req->pdsch_param.max_mu_mimo_users_dl);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_data_in_dmrs_symbols, req->pdsch_param.pdsch_data_in_dmrs_symbols);
+
+  EQ_TLV(unpacked_req->pdsch_param.premption_support, req->pdsch_param.premption_support);
+
+  EQ_TLV(unpacked_req->pdsch_param.pdsch_non_slot_support, req->pdsch_param.pdsch_non_slot_support);
+
+  EQ_TLV(unpacked_req->pusch_param.uci_mux_ulsch_in_pusch, req->pusch_param.uci_mux_ulsch_in_pusch);
+
+  EQ_TLV(unpacked_req->pusch_param.uci_only_pusch, req->pusch_param.uci_only_pusch);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_frequency_hopping, req->pusch_param.pusch_frequency_hopping);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_config_types, req->pusch_param.pusch_dmrs_config_types);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_max_len, req->pusch_param.pusch_dmrs_max_len);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_additional_pos, req->pusch_param.pusch_dmrs_additional_pos);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_cbg, req->pusch_param.pusch_cbg);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_mapping_type, req->pusch_param.pusch_mapping_type);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_allocation_types, req->pusch_param.pusch_allocation_types);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_vrb_to_prb_mapping, req->pusch_param.pusch_vrb_to_prb_mapping);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_max_ptrs_ports, req->pusch_param.pusch_max_ptrs_ports);
+
+  EQ_TLV(unpacked_req->pusch_param.max_pduschs_tbs_per_slot, req->pusch_param.max_pduschs_tbs_per_slot);
+
+  EQ_TLV(unpacked_req->pusch_param.max_number_mimo_layers_non_cb_pusch, req->pusch_param.max_number_mimo_layers_non_cb_pusch);
+
+  EQ_TLV(unpacked_req->pusch_param.supported_modulation_order_ul, req->pusch_param.supported_modulation_order_ul);
+
+  EQ_TLV(unpacked_req->pusch_param.max_mu_mimo_users_ul, req->pusch_param.max_mu_mimo_users_ul);
+
+  EQ_TLV(unpacked_req->pusch_param.dfts_ofdm_support, req->pusch_param.dfts_ofdm_support);
+
+  EQ_TLV(unpacked_req->pusch_param.pusch_aggregation_factor, req->pusch_param.pusch_aggregation_factor);
+
+  EQ_TLV(unpacked_req->prach_param.prach_long_formats, req->prach_param.prach_long_formats);
+
+  EQ_TLV(unpacked_req->prach_param.prach_short_formats, req->prach_param.prach_short_formats);
+
+  EQ_TLV(unpacked_req->prach_param.prach_restricted_sets, req->prach_param.prach_restricted_sets);
+
+  EQ_TLV(unpacked_req->prach_param.max_prach_fd_occasions_in_a_slot, req->prach_param.max_prach_fd_occasions_in_a_slot);
+
+  EQ_TLV(unpacked_req->measurement_param.rssi_measurement_support, req->measurement_param.rssi_measurement_support);
+
+  return true;
+}
+
+bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const nfapi_nr_config_request_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  EQ(unpacked_req->num_tlv, req->num_tlv);
+
+  EQ_TLV(unpacked_req->carrier_config.dl_bandwidth, req->carrier_config.dl_bandwidth);
+
+  EQ_TLV(unpacked_req->carrier_config.dl_frequency, req->carrier_config.dl_frequency);
+
+  for (int i = 0; i < 5; ++i) {
+    EQ_TLV(unpacked_req->carrier_config.dl_k0[i], req->carrier_config.dl_k0[i]);
+
+    EQ_TLV(unpacked_req->carrier_config.dl_grid_size[i], req->carrier_config.dl_grid_size[i]);
+  }
+
+  EQ_TLV(unpacked_req->carrier_config.num_tx_ant, req->carrier_config.num_tx_ant);
+
+  EQ_TLV(unpacked_req->carrier_config.uplink_bandwidth, req->carrier_config.uplink_bandwidth);
+
+  EQ_TLV(unpacked_req->carrier_config.uplink_frequency, req->carrier_config.uplink_frequency);
+
+  for (int i = 0; i < 5; ++i) {
+    EQ_TLV(unpacked_req->carrier_config.ul_k0[i], req->carrier_config.ul_k0[i]);
+
+    EQ_TLV(unpacked_req->carrier_config.ul_grid_size[i], req->carrier_config.ul_grid_size[i]);
+  }
+
+  EQ_TLV(unpacked_req->carrier_config.num_rx_ant, req->carrier_config.num_rx_ant);
+
+  EQ_TLV(unpacked_req->carrier_config.frequency_shift_7p5khz, req->carrier_config.frequency_shift_7p5khz);
+
+  EQ_TLV(unpacked_req->cell_config.phy_cell_id, req->cell_config.phy_cell_id);
+
+  EQ_TLV(unpacked_req->cell_config.frame_duplex_type, req->cell_config.frame_duplex_type);
+
+  EQ_TLV(unpacked_req->ssb_config.ss_pbch_power, req->ssb_config.ss_pbch_power);
+
+  EQ_TLV(unpacked_req->ssb_config.bch_payload, req->ssb_config.bch_payload);
+
+  EQ_TLV(unpacked_req->ssb_config.scs_common, req->ssb_config.scs_common);
+
+  EQ_TLV(unpacked_req->prach_config.prach_sequence_length, req->prach_config.prach_sequence_length);
+
+  EQ_TLV(unpacked_req->prach_config.prach_sub_c_spacing, req->prach_config.prach_sub_c_spacing);
+
+  EQ_TLV(unpacked_req->prach_config.restricted_set_config, req->prach_config.restricted_set_config);
+
+  EQ_TLV(unpacked_req->prach_config.num_prach_fd_occasions, req->prach_config.num_prach_fd_occasions);
+
+  EQ_TLV(unpacked_req->prach_config.prach_ConfigurationIndex, req->prach_config.prach_ConfigurationIndex);
+
+  for (int i = 0; i < unpacked_req->prach_config.num_prach_fd_occasions.value; i++) {
+    nfapi_nr_num_prach_fd_occasions_t unpacked_prach_fd_occasion = unpacked_req->prach_config.num_prach_fd_occasions_list[i];
+    nfapi_nr_num_prach_fd_occasions_t req_prach_fd_occasion = req->prach_config.num_prach_fd_occasions_list[i];
+
+    EQ_TLV(unpacked_prach_fd_occasion.prach_root_sequence_index, req_prach_fd_occasion.prach_root_sequence_index);
+
+    EQ_TLV(unpacked_prach_fd_occasion.num_root_sequences, req_prach_fd_occasion.num_root_sequences);
+
+    EQ_TLV(unpacked_prach_fd_occasion.k1, req_prach_fd_occasion.k1);
+
+    EQ_TLV(unpacked_prach_fd_occasion.prach_zero_corr_conf, req_prach_fd_occasion.prach_zero_corr_conf);
+
+    EQ_TLV(unpacked_prach_fd_occasion.num_unused_root_sequences, req_prach_fd_occasion.num_unused_root_sequences);
+    for (int k = 0; k < unpacked_prach_fd_occasion.num_unused_root_sequences.value; k++) {
+      EQ_TLV(unpacked_prach_fd_occasion.unused_root_sequences_list[k], req_prach_fd_occasion.unused_root_sequences_list[k]);
+    }
+  }
+
+  EQ_TLV(unpacked_req->prach_config.ssb_per_rach, req->prach_config.ssb_per_rach);
+
+  EQ_TLV(unpacked_req->prach_config.prach_multiple_carriers_in_a_band, req->prach_config.prach_multiple_carriers_in_a_band);
+
+  EQ_TLV(unpacked_req->ssb_table.ssb_offset_point_a, req->ssb_table.ssb_offset_point_a);
+
+  EQ_TLV(unpacked_req->ssb_table.ssb_period, req->ssb_table.ssb_period);
+
+  EQ_TLV(unpacked_req->ssb_table.ssb_subcarrier_offset, req->ssb_table.ssb_subcarrier_offset);
+
+  EQ_TLV(unpacked_req->ssb_table.MIB, req->ssb_table.MIB);
+
+  EQ_TLV(unpacked_req->ssb_table.ssb_mask_list[0].ssb_mask, req->ssb_table.ssb_mask_list[0].ssb_mask);
+
+  EQ_TLV(unpacked_req->ssb_table.ssb_mask_list[1].ssb_mask, req->ssb_table.ssb_mask_list[1].ssb_mask);
+
+  for (int i = 0; i < 64; i++) {
+    EQ_TLV(unpacked_req->ssb_table.ssb_beam_id_list[i].beam_id, req->ssb_table.ssb_beam_id_list[i].beam_id);
+  }
+
+  EQ_TLV(unpacked_req->tdd_table.tdd_period, req->tdd_table.tdd_period);
+
+  const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+  // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04
+  uint8_t cyclicprefix = 1;
+  bool normal_CP = cyclicprefix ? false : true;
+  // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
+  uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12;
+
+  for (int i = 0; i < slotsperframe[unpacked_req->ssb_config.scs_common.value]; i++) {
+    for (int k = 0; k < number_of_symbols_per_slot; k++) {
+      EQ_TLV(unpacked_req->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config,
+             req->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config);
+    }
+  }
+
+  EQ_TLV(unpacked_req->measurement_config.rssi_measurement, req->measurement_config.rssi_measurement);
+
+  EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag);
+  for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) {
+    EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]);
+  }
+
+  EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv6.tl.tag, req->nfapi_config.p7_vnf_address_ipv6.tl.tag);
+  for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) {
+    EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv6.address[i], req->nfapi_config.p7_vnf_address_ipv6.address[i]);
+  }
+
+  EQ_TLV(unpacked_req->nfapi_config.p7_vnf_port, req->nfapi_config.p7_vnf_port);
+
+  EQ_TLV(unpacked_req->nfapi_config.timing_window, req->nfapi_config.timing_window);
+
+  EQ_TLV(unpacked_req->nfapi_config.timing_info_mode, req->nfapi_config.timing_info_mode);
+
+  EQ_TLV(unpacked_req->nfapi_config.timing_info_period, req->nfapi_config.timing_info_period);
+  return true;
+}
+
+static bool eq_config_response_tlv_lists(nfapi_nr_generic_tlv_scf_t *unpacked_list,
+                                         nfapi_nr_generic_tlv_scf_t *req_list,
+                                         uint8_t size)
+{
+  for (int i = 0; i < size; ++i) {
+    nfapi_nr_generic_tlv_scf_t *unpacked_element = &(unpacked_list[i]);
+    nfapi_nr_generic_tlv_scf_t *req_element = &(req_list[i]);
+
+    EQ(unpacked_element->tl.tag, req_element->tl.tag);
+    EQ(unpacked_element->tl.length, req_element->tl.length);
+    // check according to value type
+    switch (unpacked_element->tl.length) {
+      case UINT_8:
+        EQ(unpacked_element->value.u8, req_element->value.u8);
+        break;
+      case UINT_16:
+        EQ(unpacked_element->value.u16, req_element->value.u16);
+        break;
+      case UINT_32:
+        EQ(unpacked_element->value.u32, req_element->value.u32);
+        break;
+      case ARRAY_UINT_16:
+        for (int j = 0; j < 5; ++j) {
+          EQ(unpacked_element->value.array_u16[j], req_element->value.array_u16[j]);
+        }
+        break;
+      default:
+        printf("unknown length %d\n", unpacked_element->tl.length);
+        DevAssert(1 == 0);
+        break;
+    }
+  }
+  return true;
+}
+
+bool eq_config_response(const nfapi_nr_config_response_scf_t *unpacked_req, const nfapi_nr_config_response_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+
+  EQ(unpacked_req->error_code, req->error_code);
+  EQ(unpacked_req->num_invalid_tlvs, req->num_invalid_tlvs);
+  EQ(unpacked_req->num_invalid_tlvs_configured_in_idle, req->num_invalid_tlvs_configured_in_idle);
+  EQ(unpacked_req->num_invalid_tlvs_configured_in_running, req->num_invalid_tlvs_configured_in_running);
+  EQ(unpacked_req->num_missing_tlvs, req->num_missing_tlvs);
+  // compare the list elements
+  EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_list, req->invalid_tlvs_list, req->num_invalid_tlvs), true);
+  EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_idle_list,
+                                  req->invalid_tlvs_configured_in_idle_list,
+                                  req->num_invalid_tlvs_configured_in_idle),
+     true);
+  EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_running_list,
+                                  req->invalid_tlvs_configured_in_running_list,
+                                  req->num_invalid_tlvs_configured_in_running),
+     true);
+  EQ(eq_config_response_tlv_lists(unpacked_req->missing_tlvs_list, req->missing_tlvs_list, req->num_missing_tlvs), true);
+  return true;
+}
+
+bool eq_start_request(const nfapi_nr_start_request_scf_t *unpacked_req, const nfapi_nr_start_request_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  return true;
+}
+
+bool eq_start_response(const nfapi_nr_start_response_scf_t *unpacked_req, const nfapi_nr_start_response_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  EQ(unpacked_req->error_code, req->error_code);
+  return true;
+}
+
+bool eq_stop_request(const nfapi_nr_stop_request_scf_t *unpacked_req, const nfapi_nr_stop_request_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  return true;
+}
+
+bool eq_stop_indication(const nfapi_nr_stop_indication_scf_t *unpacked_req, const nfapi_nr_stop_indication_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  return true;
+}
+
+bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, const nfapi_nr_error_indication_scf_t *req)
+{
+  EQ(unpacked_req->header.message_id, req->header.message_id);
+  EQ(unpacked_req->header.message_length, req->header.message_length);
+  EQ(unpacked_req->sfn, req->sfn);
+  EQ(unpacked_req->slot, req->slot);
+  EQ(unpacked_req->message_id, req->message_id);
+  EQ(unpacked_req->error_code, req->error_code);
+  return true;
+}
+
+void free_param_request(nfapi_nr_param_request_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void free_param_response(nfapi_nr_param_response_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+
+  if (msg->cell_param.config_tlvs_to_report_list) {
+    free(msg->cell_param.config_tlvs_to_report_list);
+  }
+}
+
+void free_config_request(nfapi_nr_config_request_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+
+  if (msg->prach_config.num_prach_fd_occasions_list) {
+    for (int i = 0; i < msg->prach_config.num_prach_fd_occasions.value; i++) {
+      nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(msg->prach_config.num_prach_fd_occasions_list[i]);
+      if (prach_fd_occasion->unused_root_sequences_list) {
+        free(prach_fd_occasion->unused_root_sequences_list);
+      }
+    }
+    free(msg->prach_config.num_prach_fd_occasions_list);
+  }
+  const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+  if (msg->tdd_table.max_tdd_periodicity_list) {
+    for (int i = 0; i < slotsperframe[msg->ssb_config.scs_common.value]; i++) {
+      free(msg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list);
+    }
+    free(msg->tdd_table.max_tdd_periodicity_list);
+  }
+
+  if (msg->pmi_list.pmi_pdu) {
+    free(msg->pmi_list.pmi_pdu);
+  }
+}
+
+void free_config_response(nfapi_nr_config_response_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+
+  if (msg->invalid_tlvs_list) {
+    free(msg->invalid_tlvs_list);
+  }
+
+  if (msg->invalid_tlvs_configured_in_idle_list) {
+    free(msg->invalid_tlvs_configured_in_idle_list);
+  }
+
+  if (msg->invalid_tlvs_configured_in_running_list) {
+    free(msg->invalid_tlvs_configured_in_running_list);
+  }
+
+  if (msg->missing_tlvs_list) {
+    free(msg->missing_tlvs_list);
+  }
+}
+
+void free_start_request(nfapi_nr_start_request_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void free_start_response(nfapi_nr_start_response_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void free_stop_request(nfapi_nr_stop_request_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void free_error_indication(nfapi_nr_error_indication_scf_t *msg)
+{
+  if (msg->vendor_extension) {
+    free(msg->vendor_extension);
+  }
+}
+
+void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+}
+
+void copy_param_response(const nfapi_nr_param_response_scf_t *src, nfapi_nr_param_response_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+
+  dst->error_code = src->error_code;
+  dst->num_tlv = src->num_tlv;
+
+  COPY_TLV(dst->cell_param.release_capability, src->cell_param.release_capability);
+
+  COPY_TLV(dst->cell_param.phy_state, src->cell_param.phy_state);
+
+  COPY_TLV(dst->cell_param.skip_blank_dl_config, src->cell_param.skip_blank_dl_config);
+
+  COPY_TLV(dst->cell_param.skip_blank_ul_config, src->cell_param.skip_blank_ul_config);
+
+  COPY_TLV(dst->cell_param.num_config_tlvs_to_report, src->cell_param.num_config_tlvs_to_report);
+
+  if (src->cell_param.config_tlvs_to_report_list) {
+    dst->cell_param.config_tlvs_to_report_list =
+        calloc(src->cell_param.num_config_tlvs_to_report.value, sizeof(nfapi_uint8_tlv_t *));
+    for (int i = 0; i < src->cell_param.num_config_tlvs_to_report.value; ++i) {
+      COPY_TLV(dst->cell_param.config_tlvs_to_report_list[i], src->cell_param.config_tlvs_to_report_list[i]);
+    }
+  }
+
+  COPY_TLV(dst->carrier_param.cyclic_prefix, src->carrier_param.cyclic_prefix);
+
+  COPY_TLV(dst->carrier_param.supported_subcarrier_spacings_dl, src->carrier_param.supported_subcarrier_spacings_dl);
+
+  COPY_TLV(dst->carrier_param.supported_bandwidth_dl, src->carrier_param.supported_bandwidth_dl);
+
+  COPY_TLV(dst->carrier_param.supported_subcarrier_spacings_ul, src->carrier_param.supported_subcarrier_spacings_ul);
+
+  COPY_TLV(dst->carrier_param.supported_bandwidth_ul, src->carrier_param.supported_bandwidth_ul);
+
+  COPY_TLV(dst->pdcch_param.cce_mapping_type, src->pdcch_param.cce_mapping_type);
+
+  COPY_TLV(dst->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot,
+           src->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot);
+
+  COPY_TLV(dst->pdcch_param.coreset_precoder_granularity_coreset, src->pdcch_param.coreset_precoder_granularity_coreset);
+
+  COPY_TLV(dst->pdcch_param.pdcch_mu_mimo, src->pdcch_param.pdcch_mu_mimo);
+
+  COPY_TLV(dst->pdcch_param.pdcch_precoder_cycling, src->pdcch_param.pdcch_precoder_cycling);
+
+  COPY_TLV(dst->pdcch_param.max_pdcch_per_slot, src->pdcch_param.max_pdcch_per_slot);
+
+  COPY_TLV(dst->pucch_param.pucch_formats, src->pucch_param.pucch_formats);
+
+  COPY_TLV(dst->pucch_param.max_pucchs_per_slot, src->pucch_param.max_pucchs_per_slot);
+
+  COPY_TLV(dst->pdsch_param.pdsch_mapping_type, src->pdsch_param.pdsch_mapping_type);
+
+  COPY_TLV(dst->pdsch_param.pdsch_allocation_types, src->pdsch_param.pdsch_allocation_types);
+
+  COPY_TLV(dst->pdsch_param.pdsch_vrb_to_prb_mapping, src->pdsch_param.pdsch_vrb_to_prb_mapping);
+
+  COPY_TLV(dst->pdsch_param.pdsch_cbg, src->pdsch_param.pdsch_cbg);
+
+  COPY_TLV(dst->pdsch_param.pdsch_dmrs_config_types, src->pdsch_param.pdsch_dmrs_config_types);
+
+  COPY_TLV(dst->pdsch_param.pdsch_dmrs_max_length, src->pdsch_param.pdsch_dmrs_max_length);
+
+  COPY_TLV(dst->pdsch_param.pdsch_dmrs_additional_pos, src->pdsch_param.pdsch_dmrs_additional_pos);
+
+  COPY_TLV(dst->pdsch_param.max_pdsch_tbs_per_slot, src->pdsch_param.max_pdsch_tbs_per_slot);
+
+  COPY_TLV(dst->pdsch_param.max_number_mimo_layers_pdsch, src->pdsch_param.max_number_mimo_layers_pdsch);
+
+  COPY_TLV(dst->pdsch_param.supported_max_modulation_order_dl, src->pdsch_param.supported_max_modulation_order_dl);
+
+  COPY_TLV(dst->pdsch_param.max_mu_mimo_users_dl, src->pdsch_param.max_mu_mimo_users_dl);
+
+  COPY_TLV(dst->pdsch_param.pdsch_data_in_dmrs_symbols, src->pdsch_param.pdsch_data_in_dmrs_symbols);
+
+  COPY_TLV(dst->pdsch_param.premption_support, src->pdsch_param.premption_support);
+
+  COPY_TLV(dst->pdsch_param.pdsch_non_slot_support, src->pdsch_param.pdsch_non_slot_support);
+
+  COPY_TLV(dst->pusch_param.uci_mux_ulsch_in_pusch, src->pusch_param.uci_mux_ulsch_in_pusch);
+
+  COPY_TLV(dst->pusch_param.uci_only_pusch, src->pusch_param.uci_only_pusch);
+
+  COPY_TLV(dst->pusch_param.pusch_frequency_hopping, src->pusch_param.pusch_frequency_hopping);
+
+  COPY_TLV(dst->pusch_param.pusch_dmrs_config_types, src->pusch_param.pusch_dmrs_config_types);
+
+  COPY_TLV(dst->pusch_param.pusch_dmrs_max_len, src->pusch_param.pusch_dmrs_max_len);
+
+  COPY_TLV(dst->pusch_param.pusch_dmrs_additional_pos, src->pusch_param.pusch_dmrs_additional_pos);
+
+  COPY_TLV(dst->pusch_param.pusch_cbg, src->pusch_param.pusch_cbg);
+
+  COPY_TLV(dst->pusch_param.pusch_mapping_type, src->pusch_param.pusch_mapping_type);
+
+  COPY_TLV(dst->pusch_param.pusch_allocation_types, src->pusch_param.pusch_allocation_types);
+
+  COPY_TLV(dst->pusch_param.pusch_vrb_to_prb_mapping, src->pusch_param.pusch_vrb_to_prb_mapping);
+
+  COPY_TLV(dst->pusch_param.pusch_max_ptrs_ports, src->pusch_param.pusch_max_ptrs_ports);
+
+  COPY_TLV(dst->pusch_param.max_pduschs_tbs_per_slot, src->pusch_param.max_pduschs_tbs_per_slot);
+
+  COPY_TLV(dst->pusch_param.max_number_mimo_layers_non_cb_pusch, src->pusch_param.max_number_mimo_layers_non_cb_pusch);
+
+  COPY_TLV(dst->pusch_param.supported_modulation_order_ul, src->pusch_param.supported_modulation_order_ul);
+
+  COPY_TLV(dst->pusch_param.max_mu_mimo_users_ul, src->pusch_param.max_mu_mimo_users_ul);
+
+  COPY_TLV(dst->pusch_param.dfts_ofdm_support, src->pusch_param.dfts_ofdm_support);
+
+  COPY_TLV(dst->pusch_param.pusch_aggregation_factor, src->pusch_param.pusch_aggregation_factor);
+
+  COPY_TLV(dst->prach_param.prach_long_formats, src->prach_param.prach_long_formats);
+
+  COPY_TLV(dst->prach_param.prach_short_formats, src->prach_param.prach_short_formats);
+
+  COPY_TLV(dst->prach_param.prach_restricted_sets, src->prach_param.prach_restricted_sets);
+
+  COPY_TLV(dst->prach_param.max_prach_fd_occasions_in_a_slot, src->prach_param.max_prach_fd_occasions_in_a_slot);
+
+  COPY_TLV(dst->measurement_param.rssi_measurement_support, src->measurement_param.rssi_measurement_support);
+
+  COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl);
+  memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address,
+         src->nfapi_config.p7_vnf_address_ipv4.address,
+         sizeof(dst->nfapi_config.p7_vnf_address_ipv4.address));
+
+  COPY_TL(dst->nfapi_config.p7_vnf_address_ipv6.tl, src->nfapi_config.p7_vnf_address_ipv6.tl);
+  memcpy(dst->nfapi_config.p7_vnf_address_ipv6.address,
+         src->nfapi_config.p7_vnf_address_ipv6.address,
+         sizeof(dst->nfapi_config.p7_vnf_address_ipv6.address));
+
+  COPY_TLV(dst->nfapi_config.p7_vnf_port, src->nfapi_config.p7_vnf_port);
+
+  COPY_TL(dst->nfapi_config.p7_pnf_address_ipv4.tl, src->nfapi_config.p7_pnf_address_ipv4.tl);
+  memcpy(dst->nfapi_config.p7_pnf_address_ipv4.address,
+         src->nfapi_config.p7_pnf_address_ipv4.address,
+         sizeof(dst->nfapi_config.p7_pnf_address_ipv4.address));
+
+  COPY_TL(dst->nfapi_config.p7_pnf_address_ipv6.tl, src->nfapi_config.p7_pnf_address_ipv6.tl);
+  memcpy(dst->nfapi_config.p7_pnf_address_ipv6.address,
+         src->nfapi_config.p7_pnf_address_ipv6.address,
+         sizeof(dst->nfapi_config.p7_pnf_address_ipv6.address));
+
+  COPY_TLV(dst->nfapi_config.p7_pnf_port, src->nfapi_config.p7_pnf_port);
+
+  COPY_TLV(dst->nfapi_config.timing_window, src->nfapi_config.timing_window);
+
+  COPY_TLV(dst->nfapi_config.timing_info_mode, src->nfapi_config.timing_info_mode);
+
+  COPY_TLV(dst->nfapi_config.timing_info_period, src->nfapi_config.timing_info_period);
+
+  COPY_TLV(dst->nfapi_config.dl_tti_timing_offset, src->nfapi_config.dl_tti_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.ul_tti_timing_offset, src->nfapi_config.ul_tti_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset);
+}
+
+void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_config_request_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+
+  dst->num_tlv = src->num_tlv;
+
+  COPY_TLV(dst->carrier_config.dl_bandwidth, src->carrier_config.dl_bandwidth);
+
+  COPY_TLV(dst->carrier_config.dl_frequency, src->carrier_config.dl_frequency);
+
+  for (int i = 0; i < 5; ++i) {
+    COPY_TLV(dst->carrier_config.dl_k0[i], src->carrier_config.dl_k0[i]);
+
+    COPY_TLV(dst->carrier_config.dl_grid_size[i], src->carrier_config.dl_grid_size[i]);
+  }
+
+  COPY_TLV(dst->carrier_config.num_tx_ant, src->carrier_config.num_tx_ant);
+
+  COPY_TLV(dst->carrier_config.uplink_bandwidth, src->carrier_config.uplink_bandwidth);
+
+  COPY_TLV(dst->carrier_config.uplink_frequency, src->carrier_config.uplink_frequency);
+
+  COPY_TLV(dst->carrier_config.uplink_frequency, src->carrier_config.uplink_frequency);
+
+  for (int i = 0; i < 5; ++i) {
+    COPY_TLV(dst->carrier_config.ul_k0[i], src->carrier_config.ul_k0[i]);
+
+    COPY_TLV(dst->carrier_config.ul_grid_size[i], src->carrier_config.ul_grid_size[i]);
+  }
+
+  COPY_TLV(dst->carrier_config.num_rx_ant, src->carrier_config.num_rx_ant);
+
+  COPY_TLV(dst->carrier_config.frequency_shift_7p5khz, src->carrier_config.frequency_shift_7p5khz);
+
+  COPY_TLV(dst->cell_config.phy_cell_id, src->cell_config.phy_cell_id);
+
+  COPY_TLV(dst->cell_config.frame_duplex_type, src->cell_config.frame_duplex_type);
+
+  COPY_TLV(dst->ssb_config.ss_pbch_power, src->ssb_config.ss_pbch_power);
+
+  COPY_TLV(dst->ssb_config.bch_payload, src->ssb_config.bch_payload);
+
+  COPY_TLV(dst->ssb_config.scs_common, src->ssb_config.scs_common);
+
+  COPY_TLV(dst->prach_config.prach_sequence_length, src->prach_config.prach_sequence_length);
+
+  COPY_TLV(dst->prach_config.prach_sub_c_spacing, src->prach_config.prach_sub_c_spacing);
+
+  COPY_TLV(dst->prach_config.restricted_set_config, src->prach_config.restricted_set_config);
+
+  COPY_TLV(dst->prach_config.num_prach_fd_occasions, src->prach_config.num_prach_fd_occasions);
+
+  COPY_TLV(dst->prach_config.prach_ConfigurationIndex, src->prach_config.prach_ConfigurationIndex);
+
+  COPY_TLV(dst->prach_config.prach_ConfigurationIndex, src->prach_config.prach_ConfigurationIndex);
+
+  dst->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc(
+      dst->prach_config.num_prach_fd_occasions.value * sizeof(nfapi_nr_num_prach_fd_occasions_t));
+  for (int i = 0; i < dst->prach_config.num_prach_fd_occasions.value; i++) {
+    nfapi_nr_num_prach_fd_occasions_t *src_prach_fd_occasion = &(src->prach_config.num_prach_fd_occasions_list[i]);
+    nfapi_nr_num_prach_fd_occasions_t *dst_prach_fd_occasion = &(dst->prach_config.num_prach_fd_occasions_list[i]);
+
+    COPY_TLV(dst_prach_fd_occasion->prach_root_sequence_index, src_prach_fd_occasion->prach_root_sequence_index);
+
+    COPY_TLV(dst_prach_fd_occasion->num_root_sequences, src_prach_fd_occasion->num_root_sequences);
+
+    COPY_TLV(dst_prach_fd_occasion->k1, src_prach_fd_occasion->k1);
+
+    COPY_TLV(dst_prach_fd_occasion->prach_zero_corr_conf, src_prach_fd_occasion->prach_zero_corr_conf);
+
+    COPY_TLV(dst_prach_fd_occasion->num_unused_root_sequences, src_prach_fd_occasion->num_unused_root_sequences);
+
+    dst_prach_fd_occasion->unused_root_sequences_list =
+        (nfapi_uint8_tlv_t *)malloc(dst_prach_fd_occasion->num_unused_root_sequences.value * sizeof(nfapi_uint8_tlv_t));
+    for (int k = 0; k < dst_prach_fd_occasion->num_unused_root_sequences.value; k++) {
+      COPY_TLV(dst_prach_fd_occasion->unused_root_sequences_list[k], src_prach_fd_occasion->unused_root_sequences_list[k]);
+    }
+  }
+
+  COPY_TLV(dst->prach_config.ssb_per_rach, src->prach_config.ssb_per_rach);
+
+  COPY_TLV(dst->prach_config.prach_multiple_carriers_in_a_band, src->prach_config.prach_multiple_carriers_in_a_band);
+
+  COPY_TLV(dst->ssb_table.ssb_offset_point_a, src->ssb_table.ssb_offset_point_a);
+
+  COPY_TLV(dst->ssb_table.ssb_period, src->ssb_table.ssb_period);
+
+  COPY_TLV(dst->ssb_table.ssb_subcarrier_offset, src->ssb_table.ssb_subcarrier_offset);
+
+  COPY_TLV(dst->ssb_table.MIB, src->ssb_table.MIB);
+
+  COPY_TLV(dst->ssb_table.ssb_mask_list[0].ssb_mask, src->ssb_table.ssb_mask_list[0].ssb_mask);
+
+  COPY_TLV(dst->ssb_table.ssb_mask_list[1].ssb_mask, src->ssb_table.ssb_mask_list[1].ssb_mask);
+
+  for (int i = 0; i < 64; i++) {
+    COPY_TLV(dst->ssb_table.ssb_beam_id_list[i].beam_id, src->ssb_table.ssb_beam_id_list[i].beam_id);
+  }
+
+  COPY_TLV(dst->tdd_table.tdd_period, src->tdd_table.tdd_period);
+
+  const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+  // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04
+  uint8_t cyclicprefix = 1;
+  bool normal_CP = cyclicprefix ? false : true;
+  // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
+  uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12;
+  dst->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc(slotsperframe[dst->ssb_config.scs_common.value]
+                                                                                     * sizeof(nfapi_nr_max_tdd_periodicity_t));
+
+  for (int i = 0; i < slotsperframe[dst->ssb_config.scs_common.value]; i++) {
+    dst->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list =
+        (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(number_of_symbols_per_slot * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t));
+  }
+  for (int i = 0; i < slotsperframe[dst->ssb_config.scs_common.value]; i++) { // TODO check right number of slots
+    for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change?
+      COPY_TLV(dst->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config,
+               src->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config);
+    }
+  }
+
+  COPY_TLV(dst->measurement_config.rssi_measurement, src->measurement_config.rssi_measurement);
+
+  COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl);
+  memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address,
+         src->nfapi_config.p7_vnf_address_ipv4.address,
+         sizeof(dst->nfapi_config.p7_vnf_address_ipv4.address));
+
+  COPY_TL(dst->nfapi_config.p7_vnf_address_ipv6.tl, src->nfapi_config.p7_vnf_address_ipv6.tl);
+  memcpy(dst->nfapi_config.p7_vnf_address_ipv6.address,
+         src->nfapi_config.p7_vnf_address_ipv6.address,
+         sizeof(dst->nfapi_config.p7_vnf_address_ipv6.address));
+
+  COPY_TLV(dst->nfapi_config.p7_vnf_port, src->nfapi_config.p7_vnf_port);
+
+  COPY_TL(dst->nfapi_config.p7_pnf_address_ipv4.tl, src->nfapi_config.p7_pnf_address_ipv4.tl);
+  memcpy(dst->nfapi_config.p7_pnf_address_ipv4.address,
+         src->nfapi_config.p7_pnf_address_ipv4.address,
+         sizeof(dst->nfapi_config.p7_pnf_address_ipv4.address));
+
+  COPY_TL(dst->nfapi_config.p7_pnf_address_ipv6.tl, src->nfapi_config.p7_pnf_address_ipv6.tl);
+  memcpy(dst->nfapi_config.p7_pnf_address_ipv6.address,
+         src->nfapi_config.p7_pnf_address_ipv6.address,
+         sizeof(dst->nfapi_config.p7_pnf_address_ipv6.address));
+
+  COPY_TLV(dst->nfapi_config.p7_pnf_port, src->nfapi_config.p7_pnf_port);
+
+  COPY_TLV(dst->nfapi_config.timing_window, src->nfapi_config.timing_window);
+
+  COPY_TLV(dst->nfapi_config.timing_info_mode, src->nfapi_config.timing_info_mode);
+
+  COPY_TLV(dst->nfapi_config.timing_info_period, src->nfapi_config.timing_info_period);
+
+  COPY_TLV(dst->nfapi_config.dl_tti_timing_offset, src->nfapi_config.dl_tti_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.ul_tti_timing_offset, src->nfapi_config.ul_tti_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset);
+
+  COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset);
+}
+
+void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+
+  dst->error_code = src->error_code;
+  dst->num_invalid_tlvs = src->num_invalid_tlvs;
+  dst->num_invalid_tlvs_configured_in_idle = src->num_invalid_tlvs_configured_in_idle;
+  dst->num_invalid_tlvs_configured_in_running = src->num_invalid_tlvs_configured_in_running;
+  dst->num_missing_tlvs = src->num_missing_tlvs;
+
+  dst->invalid_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+  dst->invalid_tlvs_configured_in_idle_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t));
+  dst->invalid_tlvs_configured_in_running_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t));
+  dst->missing_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+
+  for (int i = 0; i < dst->num_invalid_tlvs; ++i) {
+    COPY_TLV(dst->invalid_tlvs_list[i], src->invalid_tlvs_list[i]);
+  }
+
+  for (int i = 0; i < dst->num_invalid_tlvs_configured_in_idle; ++i) {
+    COPY_TLV(dst->invalid_tlvs_configured_in_idle_list[i], src->invalid_tlvs_configured_in_idle_list[i]);
+  }
+
+  for (int i = 0; i < dst->num_invalid_tlvs_configured_in_running; ++i) {
+    COPY_TLV(dst->invalid_tlvs_configured_in_running_list[i], src->invalid_tlvs_configured_in_running_list[i]);
+  }
+
+  for (int i = 0; i < dst->num_missing_tlvs; ++i) {
+    COPY_TLV(dst->missing_tlvs_list[i], src->missing_tlvs_list[i]);
+  }
+}
+
+void copy_start_request(const nfapi_nr_start_request_scf_t *src, nfapi_nr_start_request_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+}
+
+void copy_start_response(const nfapi_nr_start_response_scf_t *src, nfapi_nr_start_response_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+  dst->error_code = src->error_code;
+}
+
+void copy_stop_request(const nfapi_nr_stop_request_scf_t *src, nfapi_nr_stop_request_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+}
+
+void copy_stop_indication(const nfapi_nr_stop_indication_scf_t *src, nfapi_nr_stop_indication_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+}
+
+void copy_error_indication(const nfapi_nr_error_indication_scf_t *src, nfapi_nr_error_indication_scf_t *dst)
+{
+  dst->header.message_id = src->header.message_id;
+  dst->header.message_length = src->header.message_length;
+  if (src->vendor_extension) {
+    dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t));
+    dst->vendor_extension->tag = src->vendor_extension->tag;
+    dst->vendor_extension->length = src->vendor_extension->length;
+    copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension);
+  }
+
+  dst->sfn = src->sfn;
+  dst->slot = src->slot;
+  dst->message_id = src->message_id;
+  dst->error_code = src->error_code;
+}
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index d9d63a9704baf041c1e54f3856373eca5d12912b..a98595fdd5bd09e0486d2c9c0358d88de5f56383 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -359,6 +359,7 @@ typedef struct
   nfapi_nr_ue_ul_beamforming_t beamforming;
   //OAI specific
   int8_t absolute_delta_PUSCH;
+  int16_t tx_power;
   fapi_nr_tx_request_body_t tx_request_body;
 } nfapi_nr_ue_pusch_pdu_t;
 
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
index 7ce7da2290701c056ba6a4d1249067e9a27089b5..3312fa832eb3d4b56a132b0d14c7f1f28f479920 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
@@ -3981,6 +3981,20 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn
 int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
 int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
 
+/*! \brief Packs a NFAPI P5 message body
+ *  \param header A pointer to the header of the P5 message
+ *  \param ppWritePackedMsg A pointer to the buffer where to pack the P5 message
+ *  \param end Pointer to the end of the packing buffer
+ *  \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
+ */
+uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t* header,
+                                uint8_t** ppWritePackedMsg,
+                                uint8_t* end,
+                                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
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
index a2995aa6490d2d991d01a3da0bcad320f0fa71f5..08b7843ce4b23edc20d75018808db9b3c241486a 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -44,36 +44,36 @@ typedef struct {
 //PHY API message types
 
 typedef enum {
-  NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST=  0x00,
-  NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE= 0x01,
-  NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST= 0x02,
-  NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE=0X03,
-  NFAPI_NR_PHY_MSG_TYPE_START_REQUEST=  0X04,
-  NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST=   0X05,
-  NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION=0X06,
-  NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION=0X07,
-  NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE=0X010D,
-  NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE=0X010F,
-  //RESERVED 0X08 ~ 0X7F
-  NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST= 0X80,
-  NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST= 0X81,
-  NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION=0X82,
-  NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST= 0X83,
-  NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST=0X84, // CHANGED TO 0X84
-  NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION=0X85,
-  NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION= 0X86,
-  NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION= 0X87,
-  NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION= 0X88,
-  NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89,
-  //RESERVED 0X8a ~ 0xff
+  NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST = 0x00,
+  NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE = 0x01,
+  NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST = 0x02,
+  NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE = 0X03,
+  NFAPI_NR_PHY_MSG_TYPE_START_REQUEST = 0X04,
+  NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST = 0X05,
+  NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION = 0X06,
+  NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION = 0X07,
+  NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE = 0X0108, // SCF 222.10.04 Section 3.2 Start.Response - 0x108, as of nFAPIv2
+  NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE = 0X010F,
+  // RESERVED 0X08 ~ 0X7F
+  NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST = 0X80,
+  NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST = 0X81,
+  NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION = 0X82,
+  NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST = 0X83,
+  NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST = 0X84, // CHANGED TO 0X84
+  NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION = 0X85,
+  NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION = 0X86,
+  NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION = 0X87,
+  NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION = 0X88,
+  NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION = 0X89,
+  // RESERVED 0X8a ~ 0xff
   NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST = 0x0100,
   NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST= 0x0102,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE= 0x0103,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST= 0x0104,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE= 0x0105,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST= 0x0106,
-  NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE= 0x0107,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST = 0x0102,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE = 0x0103,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST = 0x0104,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE = 0x0105,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST = 0x0106,
+  NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE = 0x0107,
 
   NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC = 0x0180,
   NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC,
@@ -129,7 +129,7 @@ typedef enum {
 #define  NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG 0x0017
 #define  NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG 0x0018
 #define  NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG 0x0019
-#define  NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG 0x001A
+#define NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG 0x001A
 #define  NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG 0x001B
 #define  NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG 0x001C
 #define  NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG 0x001D
@@ -577,6 +577,23 @@ typedef struct {
   nfapi_nr_pm_list_t            pmi_list;
 } nfapi_nr_config_request_scf_t;
 
+typedef enum {
+  UINT_8 = sizeof(uint8_t),
+  UINT_16 = sizeof(uint16_t),
+  UINT_32 = sizeof(uint32_t),
+  ARRAY_UINT_16 = 5 * sizeof(uint16_t),
+  UNKNOWN = 0xffff
+} nfapi_nr_config_response_tlv_value_type_t;
+
+typedef struct {
+  nfapi_tl_t tl;
+  union {
+    uint8_t u8;
+    uint16_t u16;
+    uint32_t u32;
+    uint16_t array_u16[5]; // 4 TLVs defined as array ( dlK0, dlGridSize, ulK0, ulGridSize )
+  } value;
+} nfapi_nr_generic_tlv_scf_t;
 
 /* CONFIG.RESPONSE */
 typedef struct {
@@ -586,8 +603,11 @@ typedef struct {
   uint8_t num_invalid_tlvs_configured_in_idle;
   uint8_t num_invalid_tlvs_configured_in_running;
   uint8_t num_missing_tlvs;
-  // TODO: add list of invalid/unsupported TLVs (see Table 3.18)
-   nfapi_vendor_extension_tlv_t  vendor_extension;
+  nfapi_nr_generic_tlv_scf_t* invalid_tlvs_list;
+  nfapi_nr_generic_tlv_scf_t* invalid_tlvs_configured_in_idle_list;
+  nfapi_nr_generic_tlv_scf_t* invalid_tlvs_configured_in_running_list;
+  nfapi_nr_generic_tlv_scf_t* missing_tlvs_list;
+  nfapi_vendor_extension_tlv_t vendor_extension;
 } nfapi_nr_config_response_scf_t;
 
 //------------------------------//
@@ -609,13 +629,21 @@ typedef struct {
 typedef struct {
   nfapi_p4_p5_message_header_t header;
   nfapi_vendor_extension_tlv_t vendor_extension;
-} nfapi_nr_stop_request_t;
+} nfapi_nr_stop_request_scf_t;
 
+typedef struct {
+  nfapi_p4_p5_message_header_t header;
+  nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nr_stop_indication_scf_t;
 
 typedef struct {
   nfapi_p4_p5_message_header_t header;
+  uint16_t sfn;
+  uint16_t slot;
+  uint8_t message_id; // Which message received on the PNF has an error
+  uint8_t error_code;
   nfapi_vendor_extension_tlv_t vendor_extension;
-} nfapi_nr_stop_indication_t;
+} nfapi_nr_error_indication_scf_t;
 
 typedef enum {
   NFAPI_NR_STOP_MSG_INVALID_STATE
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h b/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a6fe08701a539890ed9c885e8eab83c77bf1825
--- /dev/null
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/open-nFAPI/nfapi/public_inc/nr_nfapi_p7.h
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+
+#ifndef OPENAIRINTERFACE_NR_NFAPI_P7_H
+#define OPENAIRINTERFACE_NR_NFAPI_P7_H
+#include "nfapi_interface.h"
+#include "nfapi_nr_interface_scf.h"
+
+uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg,
+                                  uint8_t *end,
+                                  nfapi_nr_slot_indication_scf_t *msg,
+                                  nfapi_p7_codec_config_t *config);
+
+void *nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t *config);
+
+uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg,
+                                 uint8_t *end,
+                                 nfapi_nr_srs_indication_t *pNfapiMsg,
+                                 nfapi_p7_codec_config_t *config);
+
+uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config);
+
+uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg,
+                                 uint8_t *end,
+                                 nfapi_nr_crc_indication_t *msg,
+                                 nfapi_p7_codec_config_t *config);
+
+uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config);
+
+uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg,
+                                  uint8_t *end,
+                                  nfapi_nr_rach_indication_t *msg,
+                                  nfapi_p7_codec_config_t *config);
+
+#endif // OPENAIRINTERFACE_NR_NFAPI_P7_H
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c
deleted file mode 100644
index b4b078cbed24a72cbcf5e7689f51191a26638877..0000000000000000000000000000000000000000
--- a/nfapi/open-nFAPI/nfapi/src/nfapi.c
+++ /dev/null
@@ -1,1178 +0,0 @@
-/*
- * 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 <execinfo.h>
-
-#include <nfapi_interface.h>
-#include <nfapi_nr_interface_scf.h>
-#include <nfapi.h>
-#include <debug.h>
-
-// What to do when an error happens (e.g., a push or pull fails)
-static inline void on_error()
-{
-    // show the call stack
-    int fd = STDERR_FILENO;
-    static const char msg[] = "---stack trace---\n";
-    __attribute__((unused)) int r =
-        write(fd, msg, sizeof(msg) - 1);
-    void *buffer[100];
-    int nptrs = backtrace(buffer, sizeof(buffer) / sizeof(buffer[0]));
-    backtrace_symbols_fd(buffer, nptrs, fd);
-
-    //abort();
-}
-
-// 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__);
-    on_error();
-    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__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end) {
-  uint8_t *pOut = *out;
-
-  if((end - pOut) >= 2) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    pOut[1] = (in & 0xFF00) >> 8;
-    pOut[0] = (in & 0xFF);
-#else
-    pOut[0] = (in & 0xFF00) >> 8;
-    pOut[1] = (in & 0xFF);
-#endif
-    (*out)+=2;
-    return 2;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end) {
-  uint8_t *pOut = *out;
-
-  if((end - pOut) >= 2) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    pOut[1] = (in & 0xFF00) >> 8;
-    pOut[0] = (in & 0xFF);
-#else
-    pOut[0] = (in & 0xFF00) >> 8;
-    pOut[1] = (in & 0xFF);
-#endif
-    (*out)+=2;
-    return 2;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end) {
-  uint8_t *pOut = *out;
-
-  if((end - pOut) >= 4) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    pOut[3] = (in & 0xFF000000) >> 24;
-    pOut[2] = (in & 0xFF0000) >> 16;
-    pOut[1] = (in & 0xFF00) >> 8;
-    pOut[0] = (in & 0xFF);
-#else
-    pOut[0] = (in & 0xFF000000) >> 24;
-    pOut[1] = (in & 0xFF0000) >> 16;
-    pOut[2] = (in & 0xFF00) >> 8;
-    pOut[3] = (in & 0xFF);
-#endif
-    (*out)+=4;
-    return 4;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end) {
-  uint8_t *pOut = *out;
-
-  if((end - pOut) >= 4) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    pOut[3] = (in & 0xFF000000) >> 24;
-    pOut[2] = (in & 0xFF0000) >> 16;
-    pOut[1] = (in & 0xFF00) >> 8;
-    pOut[0] = (in & 0xFF);
-#else
-    pOut[0] = (in & 0xFF000000) >> 24;
-    pOut[1] = (in & 0xFF0000) >> 16;
-    pOut[2] = (in & 0xFF00) >> 8;
-    pOut[3] = (in & 0xFF);
-#endif
-    (*out)+=4;
-    return 4;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    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__);
-    on_error();
-    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__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end) {
-  uint8_t *pIn = *in;
-
-  if((end - pIn) >=2 ) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    *out = ((pIn[1]) << 8) | pIn[0];
-#else
-    *out = ((pIn[0]) << 8) | pIn[1];
-#endif
-    (*in)+=2;
-    return 2;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end) {
-  uint8_t *pIn = *in;
-
-  if((end - pIn) >=2 ) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    *out = ((pIn[1]) << 8) | pIn[0];
-#else
-    *out = ((pIn[0]) << 8) | pIn[1];
-#endif
-    (*in)+=2;
-    return 2;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end) {
-  uint8_t *pIn = *in;
-
-  if((end - pIn) >= 4) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    *out = ((uint32_t)pIn[3] << 24) | (pIn[2] << 16) | (pIn[1] << 8) | pIn[0];
-#else
-    *out = ((uint32_t)pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
-#endif
-    (*in) += 4;
-    return 4;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n",  __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end) {
-  uint8_t *pIn = *in;
-
-  if((end - pIn) >=4 ) {
-#ifdef FAPI_BYTE_ORDERING_BIG_ENDIAN
-    *out = (pIn[3] << 24) | (pIn[2] << 16) | (pIn[1] << 8) | pIn[0];
-#else
-    *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
-#endif
-    (*in)+=4;
-    return 4;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    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);
-    on_error();
-    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__);
-    on_error();
-    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);
-    on_error();
-    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__);
-    on_error();
-    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);
-    on_error();
-    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__);
-    on_error();
-    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);
-    on_error();
-    return 0;
-  }
-
-  if((end - (*out)) >= sizeof(uint16_t) * len) {
-    uint32_t idx;
-
-    for(idx = 0; idx < len; ++idx) {
-      if (!pushs16(in[idx], out, end))
-        return 0;
-    }
-
-    return sizeof(uint16_t) * len;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-uint32_t pullarray32(uint8_t **values_to_pull,
-                     uint32_t out[],
-                     uint32_t max_num_values_to_pull,
-                     uint32_t num_values_to_pull,
-                     uint8_t *out_end) {
-  if (num_values_to_pull == 0)
-
-    return 1;
-
-  if (num_values_to_pull > max_num_values_to_pull) {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n",
-                __FUNCTION__, num_values_to_pull, max_num_values_to_pull);
-    on_error();
-    return 0;
-  }
-
-  if ((out_end - (*values_to_pull)) >= sizeof(uint32_t) * num_values_to_pull) {
-    uint32_t idx;
-
-    for (idx = 0; idx < num_values_to_pull; ++idx) {
-      if (!pull32(values_to_pull, &out[idx], out_end))
-        return 0;
-    }
-
-    return sizeof(uint32_t) * num_values_to_pull;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-
-uint32_t pullarrays32(uint8_t **in, int32_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);
-    on_error();
-    return 0;
-  }
-
-  if((end - (*in)) >= sizeof(uint32_t) * len) {
-    uint32_t idx;
-
-    for(idx = 0; idx < len; ++idx) {
-      if(!pulls32(in, &out[idx], end))
-        return 0;
-    }
-
-    return sizeof(uint32_t) * len;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-uint32_t pusharray32(const uint32_t *values_to_push,
-                     uint32_t max_num_values_to_push,
-                     uint32_t num_values_to_push,
-                     uint8_t **out,
-                     uint8_t *out_end) {
-  if (num_values_to_push == 0)
-    return 1;
-
-  if (num_values_to_push > max_num_values_to_push) {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n",
-                __FUNCTION__, num_values_to_push, max_num_values_to_push);
-    on_error();
-    return 0;
-  }
-
-  if ((out_end - (*out)) >= sizeof(uint32_t) * num_values_to_push) {
-    uint32_t idx;
-
-    for (idx = 0; idx < num_values_to_push; ++idx) {
-      if (!push32(values_to_push[idx], out, out_end))
-        return 0;
-    }
-
-    return sizeof(uint32_t) * num_values_to_push;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    return 0;
-  }
-}
-uint32_t pusharrays32(int32_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);
-    on_error();
-    return 0;
-  }
-
-  if((end - (*out)) >= sizeof(uint32_t) * len) {
-    uint32_t idx;
-
-    for(idx = 0; idx < len; ++idx) {
-      if (!pushs32(in[idx], out, end))
-        return 0;
-    }
-
-    return sizeof(uint32_t) * len;
-  } else {
-    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__);
-    on_error();
-    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);
-    on_error();
-    return 0;
-  }
-
-  if((end - (*in)) >= 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__);
-    on_error();
-    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);
-    on_error();
-    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__);
-    on_error();
-    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);
-    on_error();
-    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);
-    on_error();
-    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_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **out, uint8_t *end)
-{
-  // Helper vars for DCI Payload
-  uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN];
-  uint8_t dci_byte_len = (payloadSizeBits + 7) / 8;
-  // Align the dci payload bits to the left on the payload buffer
-  uint64_t *dci_pdu = (uint64_t *)payload;
-  if (payloadSizeBits % 8 != 0) {
-    uint8_t rotation_bits = 8 - (payloadSizeBits % 8);
-    *dci_pdu = (*dci_pdu << rotation_bits);
-  }
-  // Invert the byte order of the DCI Payload
-  for (int j = 0; j < dci_byte_len; j++) {
-    dci_bytes_inverted[j] = payload[(dci_byte_len - 1) - j];
-  }
-  return pusharray8(dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, out, end);
-}
-
-uint32_t unpack_dci_payload(uint8_t payload[], uint16_t payloadSizeBits, uint8_t **in, uint8_t *end)
-{
-  // Pull the inverted DCI and invert it back
-  //  Helper vars for DCI Payload
-  uint8_t dci_bytes_inverted[DCI_PAYLOAD_BYTE_LEN];
-  uint8_t dci_byte_len = (payloadSizeBits + 7) / 8;
-  // Get DCI array inverted
-  uint32_t pullresult = pullarray8(in, dci_bytes_inverted, DCI_PAYLOAD_BYTE_LEN, dci_byte_len, end);
-  uint64_t *dci_pdu = (uint64_t *)payload;
-  // Reversing the byte order of the inverted DCI payload
-  for (uint16_t j = 0; j < dci_byte_len; j++) {
-    payload[j] = dci_bytes_inverted[(dci_byte_len - 1) - j];
-  }
-  if (payloadSizeBits % 8 != 0) {
-    uint8_t rotation_bits = 8 - (payloadSizeBits % 8);
-    *dci_pdu = (*dci_pdu >> rotation_bits);
-  }
-  return pullresult;
-}
-
-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;
-}
-
-int 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) { // match the extracted tag value with all the tags in unpack_fn list
-        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 %ld\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue));
-          on_error();
-        }
-      }
-    }
-
-    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);
-          on_error();
-
-          if (++numBadTags > MAX_BAD_TAG) {
-            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-            on_error();
-            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);
-        on_error();
-
-        if (++numBadTags > MAX_BAD_TAG) {
-          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-          on_error();
-          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_nr_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) { // match the extracted tag value with all the tags in unpack_fn list
-        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 %ld\n",
-                      tl->tag,
-                      tl->length,
-                      (*ppReadPackedMsg - pStartOfValue));
-          on_error();
-        }
-        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
-        int padding = get_tlv_padding(tl->length);
-        if (padding != 0) {
-          (*ppReadPackedMsg) += padding;
-        }
-      }
-    }
-
-    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);
-          on_error();
-
-          if (++numBadTags > MAX_BAD_TAG) {
-            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-            on_error();
-            return 0;
-          }
-
-          if ((end - *ppReadPackedMsg) >= generic_tl.length) {
-            // Advance past the unknown TLV
-            (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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);
-        on_error();
-
-        if (++numBadTags > MAX_BAD_TAG) {
-          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-          on_error();
-          return 0;
-        }
-
-        if ((end - *ppReadPackedMsg) >= generic_tl.length) {
-          // Advance past the unknown TLV
-          (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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 %ld\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue));
-          on_error();
-        }
-      }
-    }
-
-    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);
-          on_error();
-
-          if (++numBadTags > MAX_BAD_TAG) {
-            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-            on_error();
-            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);
-        on_error();
-
-        if (++numBadTags > MAX_BAD_TAG) {
-          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-          on_error();
-          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;
-}
-
-int unpack_nr_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 %ld\n",
-                      tl->tag,
-                      tl->length,
-                      (*ppReadPackedMsg - pStartOfValue));
-          on_error();
-        }
-        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
-        int padding = get_tlv_padding(tl->length);
-        if (padding != 0) {
-          (*ppReadPackedMsg) += padding;
-        }
-      }
-    }
-
-    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);
-          on_error();
-
-          if (++numBadTags > MAX_BAD_TAG) {
-            NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-            on_error();
-            return -1;
-          }
-
-          if ((end - *ppReadPackedMsg) >= generic_tl.length) {
-            // Advance past the unknown TLV
-            (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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);
-        on_error();
-
-        if (++numBadTags > MAX_BAD_TAG) {
-          NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
-          on_error();
-          return -1;
-        }
-
-        if ((end - *ppReadPackedMsg) >= generic_tl.length) {
-          // Advance past the unknown TLV
-          (*ppReadPackedMsg) += generic_tl.length + get_tlv_padding(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;
-}
-
-uint8_t pack_nr_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);
-    // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
-    int padding = get_tlv_padding(tl->length);
-    NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x with padding of %d bytes\n", tl->tag, padding);
-    if (padding != 0) {
-      memset(*ppWritePackedMsg, 0, padding);
-      (*ppWritePackedMsg) += padding;
-    }
-  } 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";
-  }
-}
-
-uint8_t get_tlv_padding(uint16_t tlv_length)
-{
-  return (4 - (tlv_length % 4)) % 4;
-}
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
index ec16d8e39cbb5415e015debeaec7e351e97c5424..9615d3b934dfa891bb11cef94893a421f7a6b84e 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c
@@ -27,15 +27,6 @@
 #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 %lu, %lu\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);
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
index d1ac9fcdcbba12bb452584fbceb8d4a188cb79ab..a5a7810f405421d140c435cf3198ea171c31b69a 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
@@ -37,7 +37,8 @@
 #include "nfapi_nr_interface_scf.h"
 #include "nfapi/oai_integration/vendor_ext.h"
 #include <debug.h>
-
+#include "nr_fapi_p5.h"
+#include "nr_fapi.h"
 
 // Pack routines
 //TODO: Add pacl/unpack fns for uint32 and uint64
@@ -51,53 +52,6 @@ static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uin
   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;
@@ -241,21 +195,6 @@ static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, ui
           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_nr_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
 {
   nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg;
@@ -335,78 +274,17 @@ static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uin
            pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) {
-  nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
-  return (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_uint32_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
-  nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv;
-  return push32(value->value, ppWritePackedMsg, end);
-}
-
-static uint8_t unpack_uint32_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) {
-  nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv;
-  return pull32(ppReadPackedMsg, &value->value, end);
-}
-
-
-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) &&
@@ -418,11 +296,13 @@ static uint8_t pack_nmm_frequency_bands_value(void *tlv, uint8_t **ppWritePacked
   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_embms_mbsfn_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
   nfapi_embms_mbsfn_config_t *value = (nfapi_embms_mbsfn_config_t *)tlv;
   return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) &&
@@ -781,326 +661,6 @@ static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_
       && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
-{
-  printf("\nRUNNING pack_param_response\n");
-  nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
-  return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG,
-                         &(pNfapiMsg->cell_param.release_capability),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG,
-                         &(pNfapiMsg->cell_param.phy_state),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG,
-                         &(pNfapiMsg->cell_param.skip_blank_dl_config),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG,
-                         &(pNfapiMsg->cell_param.skip_blank_ul_config),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG,
-                         &(pNfapiMsg->cell_param.num_config_tlvs_to_report),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG,
-                         &(pNfapiMsg->carrier_param.cyclic_prefix),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
-                         &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG,
-                         &(pNfapiMsg->carrier_param.supported_bandwidth_dl),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
-                         &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG,
-                         &(pNfapiMsg->carrier_param.supported_bandwidth_ul),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG,
-                         &(pNfapiMsg->pdcch_param.cce_mapping_type),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
-                         &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
-                         &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG,
-                         &(pNfapiMsg->pdcch_param.pdcch_mu_mimo),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG,
-                         &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG,
-                         &(pNfapiMsg->pdcch_param.max_pdcch_per_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG,
-                         &(pNfapiMsg->pucch_param.pucch_formats),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG,
-                         &(pNfapiMsg->pucch_param.max_pucchs_per_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_mapping_type),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_allocation_types),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_cbg),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG,
-                         &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
-                         &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG,
-                         &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG,
-                         &(pNfapiMsg->pdsch_param.premption_support),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG,
-                         &(pNfapiMsg->pdsch_param.pdsch_non_slot_support),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG,
-                         &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG,
-                         &(pNfapiMsg->pusch_param.uci_only_pusch),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_frequency_hopping),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_dmrs_config_types),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_dmrs_max_len),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_cbg),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_mapping_type),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_allocation_types),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
-                         &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
-                         &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
-                         &(pNfapiMsg->pusch_param.supported_modulation_order_ul),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG,
-                         &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG,
-                         &(pNfapiMsg->pusch_param.dfts_ofdm_support),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
-                         &(pNfapiMsg->pusch_param.pusch_aggregation_factor),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG,
-                         &(pNfapiMsg->prach_param.prach_long_formats),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG,
-                         &(pNfapiMsg->prach_param.prach_short_formats),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG,
-                         &(pNfapiMsg->prach_param.prach_restricted_sets),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
-                         &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
-                         &(pNfapiMsg->measurement_param.rssi_measurement_support),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          &&
-          // config:
-          pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG,
-                      &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4),
-                      ppWritePackedMsg,
-                      end,
-                      &pack_ipv4_address_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG,
-                         &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_ipv6_address_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG,
-                         &(pNfapiMsg->nfapi_config.p7_vnf_port),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG,
-                         &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_ipv4_address_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG,
-                         &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_ipv6_address_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG,
-                         &(pNfapiMsg->nfapi_config.p7_pnf_port),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint16_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG,
-                         &(pNfapiMsg->nfapi_config.timing_window),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG,
-                         &(pNfapiMsg->nfapi_config.timing_info_mode),
-                         ppWritePackedMsg,
-                         end,
-                         &pack_uint8_tlv_value)
-          && pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG,
-                         &(pNfapiMsg->nfapi_config.timing_info_period),
-                         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;
@@ -1586,443 +1146,29 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_
                   &pack_uint8_tlv_value));
 }
 
-static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
-{
-  uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg;
-
-  nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
-  uint8_t numTLVs = 0;
-  *ppWritePackedMsg += 1; // Advance the buffer past the 'location' to push numTLVs
-  // START Carrier Configuration
-  uint8_t retval = pack_nr_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG,
-                               &(pNfapiMsg->carrier_config.dl_bandwidth),
-                               ppWritePackedMsg,
-                               end,
-                               &pack_uint16_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG,
-                        &(pNfapiMsg->carrier_config.dl_frequency),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint32_tlv_value);
-  numTLVs++;
-
-  retval &= push16(NFAPI_NR_CONFIG_DL_K0_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_k0[0].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_k0[1].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_k0[2].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_k0[3].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_k0[4].value, ppWritePackedMsg, end)
-            && push16(0, ppWritePackedMsg, end); // Padding
-  numTLVs++;
-
-  retval &= push16(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_grid_size[0].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_grid_size[1].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_grid_size[2].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_grid_size[3].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.dl_grid_size[4].value, ppWritePackedMsg, end)
-            && push16(0, ppWritePackedMsg, end); // Padding
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG,
-                        &(pNfapiMsg->carrier_config.num_tx_ant),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint16_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG,
-                        &(pNfapiMsg->carrier_config.uplink_bandwidth),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint16_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG,
-                        &(pNfapiMsg->carrier_config.uplink_frequency),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint32_tlv_value);
-  numTLVs++;
-
-  retval &= push16(NFAPI_NR_CONFIG_UL_K0_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_k0[0].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_k0[1].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_k0[2].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_k0[3].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_k0[4].value, ppWritePackedMsg, end)
-            && push16(0, ppWritePackedMsg, end); // Padding
-  numTLVs++;
-
-  retval &= push16(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, ppWritePackedMsg, end) && push16(5 * sizeof(uint16_t), ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_grid_size[0].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_grid_size[1].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_grid_size[2].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_grid_size[3].value, ppWritePackedMsg, end)
-            && push16(pNfapiMsg->carrier_config.ul_grid_size[4].value, ppWritePackedMsg, end)
-            && push16(0, ppWritePackedMsg, end); // Padding
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG,
-                        &(pNfapiMsg->carrier_config.num_rx_ant),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint16_tlv_value);
-  numTLVs++;
-
-  if (NFAPI_MODE != NFAPI_MODE_AERIAL) {
-    // TLV not supported by Aerial L1
-    pack_nr_tlv(NFAPI_NR_CONFIG_FREQUENCY_SHIFT_7P5KHZ_TAG,
-                &(pNfapiMsg->carrier_config.frequency_shift_7p5khz),
-                ppWritePackedMsg,
-                end,
-                &pack_uint8_tlv_value);
-    numTLVs++;
-  }
-  // END Carrier Configuration
-
-  // START Cell Configuration
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG,
-                        &(pNfapiMsg->cell_config.phy_cell_id),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint16_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG,
-                        &(pNfapiMsg->cell_config.frame_duplex_type),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-  // END Cell Configuration
-
-  // START SSB Configuration
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG,
-                        &(pNfapiMsg->ssb_config.ss_pbch_power),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint32_tlv_value);
-  numTLVs++;
-  if (NFAPI_MODE != NFAPI_MODE_AERIAL) {
-    // TLV not supported by Aerial L1
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG,
-                          &(pNfapiMsg->ssb_config.bch_payload),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-  }
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG,
-                        &(pNfapiMsg->ssb_config.scs_common),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-  // END SSB Configuration
-
-  // START PRACH Configuration
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG,
-                        &(pNfapiMsg->prach_config.prach_sequence_length),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG,
-                        &(pNfapiMsg->prach_config.prach_sub_c_spacing),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG,
-                        &(pNfapiMsg->prach_config.restricted_set_config),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG,
-                        &(pNfapiMsg->prach_config.num_prach_fd_occasions),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG,
-                        &(pNfapiMsg->prach_config.prach_ConfigurationIndex),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-
-  for (int i = 0; i < pNfapiMsg->prach_config.num_prach_fd_occasions.value; i++) {
-    nfapi_nr_num_prach_fd_occasions_t prach_fd_occasion = pNfapiMsg->prach_config.num_prach_fd_occasions_list[i];
-
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG,
-                          &(prach_fd_occasion.prach_root_sequence_index),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint16_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG,
-                          &(prach_fd_occasion.num_root_sequences),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_K1_TAG, &(prach_fd_occasion.k1), ppWritePackedMsg, end, &pack_uint16_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG,
-                          &(prach_fd_occasion.prach_zero_corr_conf),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG,
-                          &(prach_fd_occasion.num_unused_root_sequences),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint16_tlv_value);
-    numTLVs++;
-    for (int k = 0; k < prach_fd_occasion.num_unused_root_sequences.value; k++) {
-      prach_fd_occasion.unused_root_sequences_list[k].tl.tag = NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG;
-      prach_fd_occasion.unused_root_sequences_list[k].value = 0;
-      pack_nr_tlv(NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG,
-                  &(prach_fd_occasion.unused_root_sequences_list[k]),
-                  ppWritePackedMsg,
-                  end,
-                  &pack_uint16_tlv_value);
-      numTLVs++;
-    }
-  }
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG,
-                        &(pNfapiMsg->prach_config.ssb_per_rach),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-  pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band.tl.tag = NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG;
-  pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band.value = 0;
-  pack_nr_tlv(NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
-              &(pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band),
-              ppWritePackedMsg,
-              end,
-              &pack_uint8_tlv_value);
-  numTLVs++;
-  // END PRACH Configuration
-  // START SSB Table
-  if (NFAPI_MODE != NFAPI_MODE_AERIAL) {
-    // TLV not supported by Aerial L1
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG,
-                          &(pNfapiMsg->ssb_table.ssb_offset_point_a),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint16_tlv_value);
-    numTLVs++;
-  }
-  retval &=
-      pack_nr_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG,
-                        &(pNfapiMsg->ssb_table.ssb_subcarrier_offset),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint8_tlv_value);
-  numTLVs++;
-  /* was unused */
-  pNfapiMsg->ssb_table.MIB.tl.tag = NFAPI_NR_CONFIG_MIB_TAG;
-  pack_nr_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value);
-  numTLVs++;
-  // SCF222.10.02 Table 3-25 : If included there must be two instances of this TLV
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG,
-                        &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint32_tlv_value);
-  numTLVs++;
-
-  retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG,
-                        &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask),
-                        ppWritePackedMsg,
-                        end,
-                        &pack_uint32_tlv_value);
-  numTLVs++;
-  if (NFAPI_MODE != NFAPI_MODE_AERIAL) {
-    // TLV not supported by Aerial L1
-    for (int i = 0; i < 64; i++) {
-      // SCF222.10.02 Table 3-25 : If included there must be 64 instances of this TLV
-      retval &= pack_nr_tlv(NFAPI_NR_CONFIG_BEAM_ID_TAG,
-                            &(pNfapiMsg->ssb_table.ssb_beam_id_list[i].beam_id),
-                            ppWritePackedMsg,
-                            end,
-                            &pack_uint8_tlv_value);
-      numTLVs++;
-    }
-
-    // END SSB Table
-    // START TDD Table
-    retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG,
-                          &(pNfapiMsg->tdd_table.tdd_period),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-    // END TDD Table
-    for (int i = 0; i < 40; i++) {
-      for (int k = 0; k < 14; k++) {
-        pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG,
-                    &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config),
-                    ppWritePackedMsg,
-                    end,
-                    &pack_uint8_tlv_value);
-        numTLVs++;
-      }
-    }
-  }
-  // START Measurement Config
-  // SCF222.10.02 Table 3-27 : Contains only one TLV and is currently unused
-  pNfapiMsg->measurement_config.rssi_measurement.tl.tag = NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG;
-  pNfapiMsg->measurement_config.rssi_measurement.value = 1;
-  pack_nr_tlv(NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG,
-              &(pNfapiMsg->measurement_config.rssi_measurement),
-              ppWritePackedMsg,
-              end,
-              &pack_uint8_tlv_value);
-  numTLVs++;
-  // END Measurement Config
-
-  // START Digital Beam Table (DBT) PDU
-  // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_dbt_pdu_t, currently unused
-  // END Digital Beam Table (DBT) PDU
-
-  // START Precoding Matrix (PM) PDU
-  // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL
-  // is 0xA011 END Precoding Matrix (PM) PDU
-  if(NFAPI_MODE != NFAPI_MODE_AERIAL){
-    // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG,
-                          &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_ipv4_address_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG,
-                          &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_ipv6_address_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG,
-                          &(pNfapiMsg->nfapi_config.p7_vnf_port),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint16_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG,
-                          &(pNfapiMsg->nfapi_config.timing_window),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG,
-                          &(pNfapiMsg->nfapi_config.timing_info_mode),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-
-    retval &= pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG,
-                          &(pNfapiMsg->nfapi_config.timing_info_period),
-                          ppWritePackedMsg,
-                          end,
-                          &pack_uint8_tlv_value);
-    numTLVs++;
-    // END nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states
-
-    if (pNfapiMsg->vendor_extension != 0 && config != 0) {
-      retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
-      NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Packing CONFIG.request vendor_extension_tlv %d\n", pNfapiMsg->vendor_extension->tag);
-      numTLVs++;
-    }
-  }
-  pNfapiMsg->num_tlv = numTLVs;
-  retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
-  return retval;
-}
-
-static uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg;
-  return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && push8(pNfapiMsg->num_invalid_tlvs, ppWritePackedMsg, end)
-          && push8(pNfapiMsg->num_invalid_tlvs_configured_in_idle, ppWritePackedMsg, end)
-          && push8(pNfapiMsg->num_invalid_tlvs_configured_in_running, ppWritePackedMsg, end)
-          && push8(pNfapiMsg->num_missing_tlvs, ppWritePackedMsg, end)
-          && 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_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) {
-  nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
-  return 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_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) {
-  nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
-  return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) &&
-           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) {
+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) &&
@@ -2039,7 +1185,11 @@ static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg,
           pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_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 pack_nr_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
@@ -2109,9 +1259,8 @@ static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uin
       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) {
+      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);
@@ -2119,14 +1268,12 @@ static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uin
       } else {
         NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id);
       }
-    }
-    break;
+    } break;
   }
 
   return result;
 }
 
-
 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;
 
@@ -2222,19 +1369,6 @@ static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_
   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 %p, %p\n", &msgHead, &msgEnd);
-    return 0;
-  }
-
-  return (msgEnd - msgHead);
-}
-
 // Main pack function - public
 
 int nfapi_nr_p5_message_pack(void *pMessageBuf,
@@ -2332,8 +1466,6 @@ int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPack
   }
 }
 
-
-
 // Unpack routines
 
 static uint8_t unpack_nr_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
@@ -2347,53 +1479,6 @@ static uint8_t  unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end
   return unpack_tlv_list(NULL, 0, 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) &&
@@ -2406,6 +1491,7 @@ static uint8_t unpack_pnf_rf_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t
           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) &&
@@ -2422,13 +1508,13 @@ static uint8_t unpack_pnf_phy_rel10_info(void *elem, uint8_t **ppReadPackedMsg,
           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) &&
@@ -2536,20 +1622,6 @@ static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *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_nr_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
 {
   nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg;
@@ -2598,7 +1670,6 @@ static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end,
   return unpack_tlv_list(NULL, 0, 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;
   return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) &&
@@ -2628,12 +1699,6 @@ static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, voi
   return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
 }
 
-static uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
-  return unpack_nr_tlv_list(NULL, 0, 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;
@@ -2776,134 +1841,6 @@ static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, vo
                              &pNfapiMsg->vendor_extension));
 }
 
-static uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
-  unpack_tlv_t unpack_fns[] = {
-      {NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), &unpack_uint16_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG,
-       &(pNfapiMsg->cell_param.num_config_tlvs_to_report),
-       &unpack_uint16_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
-       &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
-       &unpack_uint16_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
-       &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
-       &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
-       &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
-       &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
-       &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
-       &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
-       &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
-       &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
-       &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
-       &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
-       &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
-       &(pNfapiMsg->pusch_param.supported_modulation_order_ul),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
-       &(pNfapiMsg->pusch_param.pusch_aggregation_factor),
-       &unpack_uint8_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value},
-      {NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
-       &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
-       &unpack_uint8_tlv_value},
-
-      {NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
-       &(pNfapiMsg->measurement_param.rssi_measurement_support),
-       &unpack_uint8_tlv_value},
-      // config
-      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value},
-      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value},
-      {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value},
-      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value},
-      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value},
-      {NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value},
-  };
-  // print ppReadPackedMsg
-  uint8_t *ptr = *ppReadPackedMsg;
-  printf("\n Read message unpack_param_response: ");
-
-  while (ptr < end) {
-    printf(" %02x ", *ptr);
-    ptr++;
-  }
-
-  printf("\n");
-  return (pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end)
-          && unpack_nr_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;
@@ -3121,324 +2058,11 @@ static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo
                              &pNfapiMsg->vendor_extension));
 }
 
-static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
+static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
 {
-  // Helper vars for indexed TLVs
-  int prach_root_seq_idx = 0;
-  int unused_root_seq_idx = 0;
-  int ssb_mask_idx = 0;
-  int config_beam_idx = 0;
-  int tdd_periodicity_idx = 0;
-  int symbol_per_slot_idx = 0;
-  nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
-  // Memory allocations
-  pNfapiMsg->tdd_table.max_tdd_periodicity_list =
-      (nfapi_nr_max_tdd_periodicity_t *)malloc(40 * sizeof(nfapi_nr_max_tdd_periodicity_t));
-
-  for (int i = 0; i < 40; i++) {
-    pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list =
-        (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(14 * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t));
-  }
-  pNfapiMsg->prach_config.num_prach_fd_occasions_list =
-      (nfapi_nr_num_prach_fd_occasions_t *)malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t));
-  // unpack TLVs
-
-  unpack_tlv_t unpack_fns[] = {
-      {NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value},
-      {NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value},
-      {NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_FREQUENCY_SHIFT_7P5KHZ_TAG, &(pNfapiMsg->carrier_config.frequency_shift_7p5khz), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value},
-      {NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG, &(pNfapiMsg->ssb_config.bch_payload), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG, &(pNfapiMsg->prach_config.prach_ConfigurationIndex), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG,
-       &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index),
-       &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG,
-       &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG,
-       &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG,
-       &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_unused_root_sequences),
-       &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG,
-       &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].unused_root_sequences_list[0]),
-       &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
-       &(pNfapiMsg->prach_config.prach_multiple_carriers_in_a_band),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value},
-      {NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value},
-      {NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value},
-      {NFAPI_NR_CONFIG_BEAM_ID_TAG, &(pNfapiMsg->ssb_table.ssb_beam_id_list[0].beam_id), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SS_PBCH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
-       &(pNfapiMsg->ssb_table.ss_pbch_multiple_carriers_in_a_band),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_MULTIPLE_CELLS_SS_PBCH_IN_A_CARRIER_TAG,
-       &(pNfapiMsg->ssb_table.multiple_cells_ss_pbch_in_a_carrier),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_SLOT_CONFIG_TAG,
-       &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config),
-       &unpack_uint8_tlv_value},
-      {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value},
-      {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value},
-      {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value},
-      {NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value},
-      {NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}};
-
-  pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end);
-
-  pNfapiMsg->vendor_extension = malloc(sizeof(&(pNfapiMsg->vendor_extension)));
-  nfapi_tl_t generic_tl;
-  uint8_t numBadTags = 0;
-  unsigned long 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 = 0;
-    for (idx = 0; idx < sizeof(unpack_fns) / sizeof(unpack_tlv_t); ++idx) {
-      if (unpack_fns[idx].tag == generic_tl.tag) { // match the extracted tag value with all the tags in unpack_fn list
-        pStartOfValue = *ppReadPackedMsg;
-        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 = 0;
-        switch (generic_tl.tag) {
-          case NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index.tl.tag =
-                generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index.tl.length =
-                generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(
-                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_root_sequence_index,
-                ppReadPackedMsg,
-                end);
-            prach_root_seq_idx++;
-            break;
-          case NFAPI_NR_CONFIG_K1_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1.tl.tag = generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1.tl.length = generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].k1,
-                                                    ppReadPackedMsg,
-                                                    end);
-            break;
-          case NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf.tl.tag = generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf.tl.length =
-                generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(
-                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].prach_zero_corr_conf,
-                ppReadPackedMsg,
-                end);
-            break;
-          case NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences.tl.tag = generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences.tl.length =
-                generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(
-                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_root_sequences,
-                ppReadPackedMsg,
-                end);
-            break;
-          case NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.tl.tag =
-                generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences.tl.length =
-                generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(
-                &pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx].num_unused_root_sequences,
-                ppReadPackedMsg,
-                end);
-            break;
-          case NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG:
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
-                .unused_root_sequences_list[unused_root_seq_idx]
-                .tl.tag = generic_tl.tag;
-            pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
-                .unused_root_sequences_list[unused_root_seq_idx]
-                .tl.length = generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->prach_config.num_prach_fd_occasions_list[prach_root_seq_idx]
-                                                         .unused_root_sequences_list[unused_root_seq_idx],
-                                                    ppReadPackedMsg,
-                                                    end);
-            unused_root_seq_idx++;
-            break;
-          case NFAPI_NR_CONFIG_SSB_MASK_TAG:
-            pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask.tl.tag = generic_tl.tag;
-            pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask.tl.length = generic_tl.length;
-            result = unpack_uint32_tlv_value(&pNfapiMsg->ssb_table.ssb_mask_list[ssb_mask_idx].ssb_mask, ppReadPackedMsg, end);
-            ssb_mask_idx++;
-            break;
-          case NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG:
-            for (int i = 0; i < 5; i++) {
-              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.dl_grid_size[i], ppReadPackedMsg, end);
-            }
-            break;
-          case NFAPI_NR_CONFIG_DL_K0_TAG:
-            for (int i = 0; i < 5; i++) {
-              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.dl_k0[i], ppReadPackedMsg, end);
-            }
-            break;
-          case NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG:
-            for (int i = 0; i < 5; i++) {
-              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.ul_grid_size[i], ppReadPackedMsg, end);
-            }
-            break;
-          case NFAPI_NR_CONFIG_UL_K0_TAG:
-            for (int i = 0; i < 5; i++) {
-              result = unpack_uint16_tlv_value(&pNfapiMsg->carrier_config.ul_k0[i], ppReadPackedMsg, end);
-            }
-            break;
-          case NFAPI_NR_CONFIG_BEAM_ID_TAG:
-            pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id.tl.tag = generic_tl.tag;
-            pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id.tl.length = generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->ssb_table.ssb_beam_id_list[config_beam_idx].beam_id,
-                                                    ppReadPackedMsg,
-                                                    end);
-            config_beam_idx++;
-            break;
-          case NFAPI_NR_CONFIG_SLOT_CONFIG_TAG:
-            pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
-                .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
-                .slot_config.tl.tag = generic_tl.tag;
-            pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
-                .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
-                .slot_config.tl.length = generic_tl.length;
-            result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->tdd_table.max_tdd_periodicity_list[tdd_periodicity_idx]
-                                                         .max_num_of_symbol_per_slot_list[symbol_per_slot_idx]
-                                                         .slot_config,
-                                                    ppReadPackedMsg,
-                                                    end);
-            symbol_per_slot_idx = (symbol_per_slot_idx + 1) % 14;
-            if (symbol_per_slot_idx == 0) {
-              tdd_periodicity_idx++;
-            }
-            break;
-          default:
-            result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end);
-            break;
-        }
-
-        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 %lu\n",
-                      tl->tag,
-                      tl->length,
-                      (*ppReadPackedMsg - pStartOfValue));
-
-        // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
-        int padding = get_tlv_padding(tl->length);
-        NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x length %d with padding of %d bytes\n", tl->tag, tl->length, padding);
-        if (padding != 0)
-          (*ppReadPackedMsg) += padding;
-      }
-    }
-
-    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, &(pNfapiMsg->vendor_extension));
-        if (result == 0) {
-          // got to 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;
-            int padding = get_tlv_padding(generic_tl.length);
-            (*ppReadPackedMsg) += padding;
-          } 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;
-          int padding = get_tlv_padding(generic_tl.length);
-          (*ppReadPackedMsg) += padding;
-        } else {
-          // go to the end
-          return 0;
-        }
-      }
-    }
-  }
-  struct sockaddr_in vnf_p7_sockaddr;
-  memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), 4);
-
-  printf("[PNF] vnf p7 %s:%d\n", inet_ntoa(vnf_p7_sockaddr.sin_addr), pNfapiMsg->nfapi_config.p7_vnf_port.value);
-  return 1;
-}
-
-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;
-  return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
-           unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
-}
-
-static uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg;
-  uint8_t invalid_unsupported_TLVs, invalidTLVsIdle, InvalidTLVsRunning, missingTLVS;
-  uint8_t retVal = (pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && pull8(ppReadPackedMsg, &invalid_unsupported_TLVs, end)
-                    && pull8(ppReadPackedMsg, &invalidTLVsIdle, end) && pull8(ppReadPackedMsg, &InvalidTLVsRunning, end)
-                    && pull8(ppReadPackedMsg, &missingTLVS, end)
-                    && unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
-  // TODO: Process and use the invalid TLVs fields
-  return retVal;
-}
-
-static uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
-  return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
+  return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end)
+          && unpack_tlv_list(NULL, 0, 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) {
@@ -3452,40 +2076,17 @@ static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, vo
            unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
 }
 
-static uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
-{
-  nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
-  return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end)
-          && unpack_nr_tlv_list(NULL, 0, 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;
   return unpack_tlv_list(NULL, 0, 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;
-  return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) &&
-           unpack_tlv_list(NULL, 0, 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[] = {
@@ -3550,47 +2151,16 @@ static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpack
         retLen = sizeof(nfapi_nr_pnf_stop_response_t);
 
       break;
-
     case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST:
-      if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t))
-        retLen = sizeof(nfapi_nr_param_request_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
-      if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t))
-        retLen = sizeof(nfapi_nr_param_response_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
-      if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t))
-        retLen = sizeof(nfapi_nr_config_request_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
-      if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t))
-        retLen = sizeof(nfapi_nr_config_response_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
-      if (unpackedBufLen >= sizeof( nfapi_nr_start_request_scf_t))
-        retLen = sizeof( nfapi_nr_start_request_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
-      if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t))
-        retLen = sizeof(nfapi_nr_start_response_scf_t);
-
-      break;
-
     case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
-      if (unpackedBufLen >= sizeof(nfapi_stop_request_t))
-        retLen = sizeof(nfapi_stop_request_t);
-
+    case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
+    case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
+      retLen = check_nr_fapi_unpack_length(msgId, unpackedBufLen);
       break;
 
     case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE:
@@ -3607,7 +2177,6 @@ static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpack
   return retLen;
 }
 
-
 static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) {
   int retLen = 0;
 
@@ -3728,7 +2297,6 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen
   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) {
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
index 45d5f15ffe5298bd0882fb7822e754db9603cb39..b856e6b6484545f8c0e237d011c1879d9a8c7881 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
@@ -38,6 +38,7 @@
 #include <nfapi.h>
 #include <debug.h>
 #include "nfapi_nr_interface_scf.h"
+#include "nr_nfapi_p7.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);
@@ -829,7 +830,7 @@ static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePac
   return 1;
 }
 
-static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
   nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg;
 
@@ -1658,7 +1659,7 @@ static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePac
   return 1;
 }
 
-static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
   nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg;
   pNfapiMsg->n_ulcch = 0;
@@ -1987,25 +1988,22 @@ static uint8_t pack_ul_dci_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg,
   return push16(value->PDUSize, &pPackedLengthField, end);
 }
 
-static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg;
 
-  if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->Slot, ppWritePackedMsg, end) &&
-        push8(pNfapiMsg->numPdus, ppWritePackedMsg, end)
-       ))
+  if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end)
+        && push8(pNfapiMsg->numPdus, ppWritePackedMsg, end)))
     return 0;
 
-  for(int i=0; i<pNfapiMsg->numPdus; i++) {
-    if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end))
+  for (int i = 0; i < pNfapiMsg->numPdus; i++) {
+    if (!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end))
       return 0;
   }
 
   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) &&
@@ -2159,10 +2157,15 @@ static uint8_t pack_release_request_body_value(void *tlv, uint8_t **ppWritePacke
   return 1;
 }
 
-static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t *)msg;
   int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end);
-  int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value);
+  int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG,
+                   &pNfapiMsg->ue_release_request_body,
+                   ppWritePackedMsg,
+                   end,
+                   &pack_release_request_body_value);
   int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
   return x && y && z;
 }
@@ -2179,7 +2182,8 @@ static uint8_t pack_nr_ue_release_request(void *msg, uint8_t **ppWritePackedMsg,
          && pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
 }
 
-static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t *)msg;
   int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end);
   int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
@@ -3087,11 +3091,11 @@ static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint
            pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t *)msg;
-  return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) &&
-           pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) &&
-           pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+  return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end)
+          && 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) {
@@ -3101,12 +3105,12 @@ static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t
            pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_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));
+  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_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
@@ -3136,40 +3140,37 @@ static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *
           pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
-static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) {
+uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
   nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t *)msg;
-  return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) &&
-          push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) &&
-          pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) &&
-          pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
+  return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && push32(pNfapiMsg->last_slot, ppWritePackedMsg, end)
+          && push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end)
+          && push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end)
+          && push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end)
+          && push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end)
+          && pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end)
+          && pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
 }
 
 //NR UPLINK indication function packing
 
 //SLOT INDICATION
 
-static uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
-	nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg;
+  nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg;
 
-	if (!(push16((uint16_t)pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16((uint16_t)pNfapiMsg->slot , ppWritePackedMsg, end)
-		))
-			return 0;
+  if (!(push16((uint16_t)pNfapiMsg->sfn, ppWritePackedMsg, end) && push16((uint16_t)pNfapiMsg->slot, ppWritePackedMsg, end)))
+    return 0;
 
-return 1;
+  return 1;
 }
 
 //RX DATA INDICATION
@@ -3193,20 +3194,16 @@ static uint8_t pack_nr_rx_data_indication_body(nfapi_nr_rx_data_pdu_t *value, ui
   return 1;
 }
 
-
-static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
-  nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg;
+  nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t *)msg;
 
-  if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
-  ))
+  if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end)
+        && push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)))
     return 0;
 
-  for (int i = 0; i < pNfapiMsg->number_of_pdus; i++)
-  {
-    if(!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end))
+  for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) {
+    if (!pack_nr_rx_data_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end))
       return 0;
   }
 
@@ -3238,19 +3235,16 @@ static uint8_t pack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppWr
   return 1;
 }
 
-static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
-  nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg;
+  nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg;
 
-  if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end)
-  ))
+  if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end)
+        && push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end)))
     return 0;
 
-  for (int i = 0; i < pNfapiMsg->number_crcs; i++)
-  {
-    if(!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end))
+  for (int i = 0; i < pNfapiMsg->number_crcs; i++) {
+    if (!pack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppWritePackedMsg, end))
       return 0;
   }
 
@@ -3366,19 +3360,17 @@ static uint8_t pack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *value,
   return 1;
 }
 
-static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) {
-
-  nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg;
+uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
+{
+  nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t *)msg;
 
-  if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-        push16(pNfapiMsg->control_length , ppWritePackedMsg, end) &&
-        push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) {
+  if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end)
+        && push16(pNfapiMsg->control_length, ppWritePackedMsg, end) && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end))) {
     return 0;
   }
 
-  for(int i=0; i<pNfapiMsg->number_of_pdus;i++) {
-    if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg, end)) {
+  for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) {
+    if (!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end)) {
       return 0;
     }
   }
@@ -3412,26 +3404,22 @@ static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMs
 	return 1;
 }
 
-static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
-	nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg;
+  nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg;
 
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
-		))
-			return 0;
+  if (!(push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end)
+        && push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)))
+    return 0;
 
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)
-	{
-		if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end))
-		return 0;
-	}
+  for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) {
+    if (!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]), ppWritePackedMsg, end))
+      return 0;
+  }
 
-return 1;
+  return 1;
 }
 
-
 //UCI INDICATION
 
 static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
@@ -3637,28 +3625,25 @@ static uint8_t pack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppWr
   return 1;
 }
 
-static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config)
 {
-  nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg;
+  nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg;
 
-  if (!push16(pNfapiMsg->sfn , ppWritePackedMsg, end))
+  if (!push16(pNfapiMsg->sfn, ppWritePackedMsg, end))
     return 0;
-  if (!push16(pNfapiMsg->slot , ppWritePackedMsg, end))
+  if (!push16(pNfapiMsg->slot, ppWritePackedMsg, end))
     return 0;
   if (!push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end))
     return 0;
 
-  for (int i = 0; i < pNfapiMsg->num_ucis; i++)
-  {
+  for (int i = 0; i < pNfapiMsg->num_ucis; i++) {
     if (!pack_nr_uci_indication_body(&pNfapiMsg->uci_list[i], ppWritePackedMsg, end))
       return 0;
-
   }
 
   return 1;
 }
 
-
 // Main pack function - public
 
 int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config)
@@ -6061,16 +6046,17 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
 
 //SLOT INDICATION
 
-static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_slot_indication_scf_t *msg, nfapi_p7_codec_config_t* config)
+uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg,
+                                  uint8_t *end,
+                                  nfapi_nr_slot_indication_scf_t *msg,
+                                  nfapi_p7_codec_config_t *config)
 {
-	nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg;
+  nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t *)msg;
 
-	if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->slot , end)
-		))
-			return 0;
+  if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)))
+    return 0;
 
-return 1;
+  return 1;
 }
 
 //RX DATA INDICATION
@@ -6121,7 +6107,7 @@ static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *
 
 //NR CRC INDICATION
 
-static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end)
+uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **ppReadPackedMsg, uint8_t *end)
 {
   if (!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end)
         && pull8(ppReadPackedMsg, &value->harq_id, end) && pull8(ppReadPackedMsg, &value->tb_crc_status, end)
@@ -6147,24 +6133,23 @@ static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t *value, uint8_t **pp
   return 1;
 }
 
-static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config)
+uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg,
+                                 uint8_t *end,
+                                 nfapi_nr_crc_indication_t *msg,
+                                 nfapi_p7_codec_config_t *config)
 {
-  nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg;
+  nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *)msg;
 
-  if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-        pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) &&
-        pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end)
-  ))
+  if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)
+        && pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end)))
     return 0;
 
-  if (pNfapiMsg->number_crcs > 0)
-  {
+  if (pNfapiMsg->number_crcs > 0) {
     pNfapiMsg->crc_list = nfapi_p7_allocate(sizeof(*pNfapiMsg->crc_list) * pNfapiMsg->number_crcs, config);
   }
 
-  for (int i = 0; i < pNfapiMsg->number_crcs; i++)
-  {
-    if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end))
+  for (int i = 0; i < pNfapiMsg->number_crcs; i++) {
+    if (!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list[i], ppReadPackedMsg, end))
       return 0;
   }
 
@@ -6276,16 +6261,17 @@ static uint8_t unpack_nr_srs_indication_body(nfapi_nr_srs_indication_pdu_t *valu
   return 1;
 }
 
-static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_srs_indication_t *pNfapiMsg, nfapi_p7_codec_config_t* config) {
-
-  if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn, end) &&
-        pull16(ppReadPackedMsg,&pNfapiMsg->slot, end) &&
-        pull16(ppReadPackedMsg,&pNfapiMsg->control_length, end) &&
-        pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end))) {
+uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg,
+                                 uint8_t *end,
+                                 nfapi_nr_srs_indication_t *pNfapiMsg,
+                                 nfapi_p7_codec_config_t *config)
+{
+  if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)
+        && pull16(ppReadPackedMsg, &pNfapiMsg->control_length, end) && pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end))) {
     return 0;
   }
 
-  for(int i=0; i<pNfapiMsg->number_of_pdus; i++) {
+  for (int i = 0; i < pNfapiMsg->number_of_pdus; i++) {
     if (!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list[i], ppReadPackedMsg, end)) {
       return 0;
     }
@@ -6318,10 +6304,10 @@ static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t *v
   return 1;
 }
 
-static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg,
-                                         uint8_t *end,
-                                         nfapi_nr_rach_indication_t *msg,
-                                         nfapi_p7_codec_config_t *config)
+uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg,
+                                  uint8_t *end,
+                                  nfapi_nr_rach_indication_t *msg,
+                                  nfapi_p7_codec_config_t *config)
 {
   nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t *)msg;
 
@@ -6609,7 +6595,7 @@ static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t *value,
   return 1;
 }
 
-static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config)
+uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config)
 {
   nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t *)msg;
 
diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
index ca8bc8d9a46525247fadd7d402af22d157849efb..14782bdcf4ae856abf49ad1b0fa335f00c0fe71a 100644
--- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
+++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
@@ -214,21 +214,21 @@ typedef struct nfapi_pnf_config
 	 *  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);
-	int (*nr_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_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
+  int (*nr_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_stop_request_scf_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
diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c
index f16fd776d29c75ee45edcf4bba49216c05fad059..9ee06b1ca8190717be596a9817ec33eece93635a 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf.c
@@ -937,75 +937,58 @@ void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
 	}
 }
 
-void pnf_nr_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
+void pnf_nr_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_nr_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_nr_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->nr_stop_req)
-						{
-							(config->nr_stop_req)(config, phy, &req);
-						}
-					}
-					else
-					{
-						nfapi_stop_response_t resp;
-						memset(&resp, 0, sizeof(resp));
-						resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_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_NR_PHY_MSG_TYPE_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_NR_PHY_MSG_TYPE_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);
+  // ensure it's valid
+  if (pRecvMsg == NULL || pnf == NULL) {
+    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+  } else {
+    nfapi_nr_stop_request_scf_t req;
+
+    NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n");
+
+    nfapi_pnf_config_t* config = &(pnf->_public);
+
+    // unpack the message
+    if (nfapi_nr_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->nr_stop_req) {
+              (config->nr_stop_req)(config, phy, &req);
+            }
+          } else {
+            nfapi_stop_response_t resp;
+            memset(&resp, 0, sizeof(resp));
+            resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_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_NR_PHY_MSG_TYPE_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_NR_PHY_MSG_TYPE_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)
diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c
index 6a769acd772f6d02912db304c1a23d6e6968db9e..631ce2b7e9fb36542418d40ea8f1de675696ac94 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf.c
@@ -30,6 +30,7 @@
 #ifdef ENABLE_AERIAL
 #include "nfapi/oai_integration/aerial/fapi_nvIPC.h"
 #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h"
+#include "nr_fapi.h"
 #endif
 #include "nfapi/oai_integration/vendor_ext.h"
 
diff --git a/nfapi/tests/CMakeLists.txt b/nfapi/tests/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4af1e68aa14be202d4f8d04b02352107c81c7159
--- /dev/null
+++ b/nfapi/tests/CMakeLists.txt
@@ -0,0 +1,4 @@
+if (ENABLE_TESTS)
+    add_subdirectory(p5)
+    add_subdirectory(p7)
+endif ()
diff --git a/nfapi/tests/nr_fapi_test.h b/nfapi/tests/nr_fapi_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c4c67a542b7b613cb96320188dfcd8b45600c10
--- /dev/null
+++ b/nfapi/tests/nr_fapi_test.h
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_test.h
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+
+#ifndef OPENAIRINTERFACE_NR_FAPI_TEST_H
+#define OPENAIRINTERFACE_NR_FAPI_TEST_H
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifndef _STANDALONE_TESTING_
+#include "common/utils/LOG/log.h"
+#endif
+#include "nfapi_nr_interface.h"
+#include "nfapi_nr_interface_scf.h"
+
+#define FILL_TLV(TlV, TaG, VaL) \
+  do {                          \
+    TlV.tl.tag = TaG;           \
+    TlV.value = VaL;            \
+  } while (0)
+
+uint8_t rand8()
+{
+  return (rand() & 0xff);
+}
+uint16_t rand16()
+{
+  return rand8() << 8 | rand8();
+}
+uint32_t rand24()
+{
+  return rand16() << 8 | rand8();
+}
+uint32_t rand32()
+{
+  return rand24() << 8 | rand8();
+}
+uint64_t rand64()
+{
+  return (uint64_t)rand32() << 32 | rand32();
+}
+
+uint8_t rand8_range(uint8_t lower, uint8_t upper)
+{
+  return (rand() % (upper - lower + 1)) + lower;
+}
+
+uint16_t rand16_range(uint16_t lower, uint16_t upper)
+{
+  return (rand() % (upper - lower + 1)) + lower;
+}
+
+int main(int n, char *v[]);
+
+static inline void fapi_test_init_seeded(time_t seed)
+{
+  srand(seed);
+  printf("srand seed is %ld\n", seed);
+  logInit();
+  set_glog(OAILOG_DISABLE);
+}
+
+static inline void fapi_test_init()
+{
+  fapi_test_init_seeded(time(NULL));
+}
+#endif // OPENAIRINTERFACE_NR_FAPI_TEST_H
diff --git a/nfapi/tests/p5/CMakeLists.txt b/nfapi/tests/p5/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5bcc3a218fae38e291cc8a121840eca7c3434e20
--- /dev/null
+++ b/nfapi/tests/p5/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(Test_Labels fapi p5)
+set(_fapi_p5_messages "param_request;param_response;config_request;config_response;start_request;start_response;stop_request;stop_indication;error_indication")
+
+foreach (fapi_p5_message IN LISTS _fapi_p5_messages)
+    add_executable(nr_fapi_${fapi_p5_message}_test nr_fapi_${fapi_p5_message}_test.c)
+    target_link_libraries(nr_fapi_${fapi_p5_message}_test PUBLIC nr_fapi_p5)
+    target_link_libraries(nr_fapi_${fapi_p5_message}_test PRIVATE pthread UTIL ${T_LIB} minimal_lib)
+    add_dependencies(tests nr_fapi_${fapi_p5_message}_test)
+
+    add_test(nr_fapi_${fapi_p5_message}_test nr_fapi_${fapi_p5_message}_test)
+    set_tests_properties(nr_fapi_${fapi_p5_message}_test PROPERTIES LABELS "${Test_Labels}")
+endforeach ()
diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e098722b235ee879a5b5278999045c187749cd9
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_config_request_test.c
@@ -0,0 +1,296 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_config_request_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void fill_config_request_tlv(nfapi_nr_config_request_scf_t *nfapi_resp)
+{
+  FILL_TLV(nfapi_resp->carrier_config.dl_bandwidth, NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.dl_frequency, NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, rand32());
+  nfapi_resp->num_tlv++;
+
+  for (int i = 0; i < 5; ++i) {
+    FILL_TLV(nfapi_resp->carrier_config.dl_k0[i], NFAPI_NR_CONFIG_DL_K0_TAG, rand16());
+  }
+  // these 5 are 1 tlv
+  nfapi_resp->num_tlv++;
+  for (int i = 0; i < 5; ++i) {
+    FILL_TLV(nfapi_resp->carrier_config.dl_grid_size[i], NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, rand16());
+  }
+  // these 5 are 1 tlv
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.num_tx_ant, NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.uplink_bandwidth, NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.uplink_frequency, NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  for (int i = 0; i < 5; ++i) {
+    FILL_TLV(nfapi_resp->carrier_config.ul_k0[i], NFAPI_NR_CONFIG_UL_K0_TAG, rand16());
+  }
+  // these 5 are 1 tlv
+  nfapi_resp->num_tlv++;
+  for (int i = 0; i < 5; ++i) {
+    FILL_TLV(nfapi_resp->carrier_config.ul_grid_size[i], NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, rand16());
+  }
+  // these 5 are 1 tlv
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.num_rx_ant, NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_config.frequency_shift_7p5khz, NFAPI_NR_CONFIG_FREQUENCY_SHIFT_7P5KHZ_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_config.phy_cell_id, NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_config.frame_duplex_type, NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_config.ss_pbch_power, NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, (int32_t)rand32());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_config.bch_payload, NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  // NOTE: MUST be between 0 & 4 ( inclusive ) , since this value is used as index to obtain slots per frame
+  FILL_TLV(nfapi_resp->ssb_config.scs_common, NFAPI_NR_CONFIG_SCS_COMMON_TAG, rand8_range(0, 4));
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_config.prach_sequence_length, NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_config.prach_sub_c_spacing, NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_config.restricted_set_config, NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, rand8());
+  nfapi_resp->num_tlv++;
+  /*Number of RACH frequency domain
+    occasions. Corresponds to the
+    parameter 𝑀𝑀 in [38.211, sec 6.3.3.2]
+    which equals the higher layer
+    parameter msg1FDM
+    Value: 1,2,4,8*/
+  const uint8_t num_prach_fd_ocasions[] = {1, 2, 4, 8};
+  FILL_TLV(nfapi_resp->prach_config.num_prach_fd_occasions,
+           NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG,
+           num_prach_fd_ocasions[rand8_range(0, sizeof(num_prach_fd_ocasions) - 1)]);
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_config.prach_ConfigurationIndex, NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  nfapi_resp->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc(
+      nfapi_resp->prach_config.num_prach_fd_occasions.value * sizeof(nfapi_nr_num_prach_fd_occasions_t));
+  for (int i = 0; i < nfapi_resp->prach_config.num_prach_fd_occasions.value; i++) {
+    nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(nfapi_resp->prach_config.num_prach_fd_occasions_list[i]);
+
+    FILL_TLV(prach_fd_occasion->prach_root_sequence_index, NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, rand16());
+    nfapi_resp->num_tlv++;
+
+    FILL_TLV(prach_fd_occasion->num_root_sequences, NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, rand8());
+    nfapi_resp->num_tlv++;
+
+    FILL_TLV(prach_fd_occasion->k1, NFAPI_NR_CONFIG_K1_TAG, rand8());
+    nfapi_resp->num_tlv++;
+
+    FILL_TLV(prach_fd_occasion->prach_zero_corr_conf, NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, rand8());
+    nfapi_resp->num_tlv++;
+
+    // This doesn't make sense to be more than the total num_root_sequences
+    /* SCF 222.10.02 : Number of unused sequences available
+       for noise estimation per FD occasion. At
+       least one unused root sequence is
+       required per FD occasion.  */
+    if (prach_fd_occasion->num_root_sequences.value != 0) {
+      FILL_TLV(prach_fd_occasion->num_unused_root_sequences,
+               NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG,
+               rand8_range(1, prach_fd_occasion->num_root_sequences.value));
+    } else {
+      FILL_TLV(prach_fd_occasion->num_unused_root_sequences, NFAPI_NR_CONFIG_NUM_UNUSED_ROOT_SEQUENCES_TAG, 1);
+    }
+    nfapi_resp->num_tlv++;
+
+    prach_fd_occasion->unused_root_sequences_list =
+        (nfapi_uint8_tlv_t *)malloc(prach_fd_occasion->num_unused_root_sequences.value * sizeof(nfapi_uint8_tlv_t));
+    for (int k = 0; k < prach_fd_occasion->num_unused_root_sequences.value; k++) {
+      FILL_TLV(prach_fd_occasion->unused_root_sequences_list[k], NFAPI_NR_CONFIG_UNUSED_ROOT_SEQUENCES_TAG, rand16());
+      nfapi_resp->num_tlv++;
+    }
+  }
+
+  FILL_TLV(nfapi_resp->prach_config.ssb_per_rach, NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_config.prach_multiple_carriers_in_a_band,
+           NFAPI_NR_CONFIG_PRACH_MULTIPLE_CARRIERS_IN_A_BAND_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.ssb_offset_point_a, NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.ssb_period, NFAPI_NR_CONFIG_SSB_PERIOD_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.ssb_subcarrier_offset, NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.MIB, NFAPI_NR_CONFIG_MIB_TAG, rand32());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.ssb_mask_list[0].ssb_mask, NFAPI_NR_CONFIG_SSB_MASK_TAG, rand32());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->ssb_table.ssb_mask_list[1].ssb_mask, NFAPI_NR_CONFIG_SSB_MASK_TAG, rand32());
+  nfapi_resp->num_tlv++;
+
+  for (int i = 0; i < 64; i++) {
+    FILL_TLV(nfapi_resp->ssb_table.ssb_beam_id_list[i].beam_id, NFAPI_NR_CONFIG_BEAM_ID_TAG, rand8());
+    nfapi_resp->num_tlv++;
+  }
+
+  FILL_TLV(nfapi_resp->tdd_table.tdd_period, NFAPI_NR_CONFIG_TDD_PERIOD_TAG, rand8());
+  nfapi_resp->num_tlv++;
+  const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
+  // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04
+  uint8_t cyclicprefix = 1;
+  bool normal_CP = cyclicprefix ? false : true;
+  // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
+  uint8_t number_of_symbols_per_slot = normal_CP ? 14 : 12;
+
+  nfapi_resp->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc(
+      slotsperframe[nfapi_resp->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t));
+
+  for (int i = 0; i < slotsperframe[nfapi_resp->ssb_config.scs_common.value]; i++) {
+    nfapi_resp->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list =
+        (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(number_of_symbols_per_slot * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t));
+  }
+
+  for (int i = 0; i < slotsperframe[nfapi_resp->ssb_config.scs_common.value]; i++) { // TODO check right number of slots
+    for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change?
+      FILL_TLV(nfapi_resp->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config,
+               NFAPI_NR_CONFIG_SLOT_CONFIG_TAG,
+               rand8());
+      nfapi_resp->num_tlv++;
+    }
+  }
+
+  FILL_TLV(nfapi_resp->measurement_config.rssi_measurement, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
+  for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) {
+    nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8();
+  }
+  nfapi_resp->num_tlv++;
+
+  nfapi_resp->nfapi_config.p7_vnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG;
+  for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) {
+    nfapi_resp->nfapi_config.p7_vnf_address_ipv6.address[i] = rand8();
+  }
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->nfapi_config.p7_vnf_port, NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->nfapi_config.timing_window, NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->nfapi_config.timing_info_mode, NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->nfapi_config.timing_info_period, NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, rand8());
+  nfapi_resp->num_tlv++;
+}
+
+void test_pack_unpack(nfapi_nr_config_request_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // PARAM.request message body length is 0
+  DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_config_request_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_config_request(&unpacked_req, req));
+  free_config_request(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_config_request_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_config_request_scf_t copy = {0};
+  copy_config_request(msg, &copy);
+  DevAssert(eq_config_request(msg, &copy));
+  free_config_request(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+  nfapi_nr_config_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST};
+  // Fill CONFIG.request TVLs
+  fill_config_request_tlv(&req);
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_config_request(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_config_response_test.c b/nfapi/tests/p5/nr_fapi_config_response_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae97b93c2ce9cada3be15e3c73ca76f2b848c3c7
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_config_response_test.c
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_config_response_test.c
+ * \brief Defines a unitary test for the FAPI CONFIG.response message ( 0x03 )
+ *        The test consists of filling a message with randomized data, filling each lists as well with random TLVs
+ *        After the message is created, is is packed into a byte buffer
+ *        After packing, the header is unpacked to mimic SCTP PEEK and the values unpacked checked against the original message
+ *        After the header is checked, the whole message is unpacked.
+ *        The test ends by checking all of the unpacked message contents against the original message
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void fill_config_response_tlv_list(nfapi_nr_generic_tlv_scf_t *list, uint8_t size)
+{
+  uint8_t const TLVtypes[] = {UINT_8, UINT_16, UINT_32, ARRAY_UINT_16};
+  for (int i = 0; i < size; ++i) {
+    nfapi_nr_generic_tlv_scf_t *element = &(list[i]);
+    element->tl.tag = rand16_range(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG);
+    element->tl.length = TLVtypes[rand8_range(0, sizeof(TLVtypes) - 1)];
+    switch (element->tl.length) {
+      case UINT_8:
+        element->value.u8 = rand8();
+        break;
+      case UINT_16:
+        element->value.u16 = rand16();
+        break;
+      case UINT_32:
+        element->value.u32 = rand32();
+        break;
+      case ARRAY_UINT_16:
+        for (int j = 0; j < 5; ++j) {
+          element->value.array_u16[j] = rand16();
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+void fill_config_response_tlv(nfapi_nr_config_response_scf_t *nfapi_resp)
+{
+  nfapi_resp->error_code = rand8();
+  nfapi_resp->num_invalid_tlvs = rand8();
+  nfapi_resp->num_invalid_tlvs_configured_in_idle = rand8();
+  nfapi_resp->num_invalid_tlvs_configured_in_running = rand8();
+  nfapi_resp->num_missing_tlvs = rand8();
+  // Lists
+  nfapi_resp->invalid_tlvs_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->invalid_tlvs_configured_in_idle_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->invalid_tlvs_configured_in_running_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t));
+  nfapi_resp->missing_tlvs_list =
+      (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
+
+  fill_config_response_tlv_list(nfapi_resp->invalid_tlvs_list, nfapi_resp->num_invalid_tlvs);
+  fill_config_response_tlv_list(nfapi_resp->invalid_tlvs_configured_in_idle_list, nfapi_resp->num_invalid_tlvs_configured_in_idle);
+  fill_config_response_tlv_list(nfapi_resp->invalid_tlvs_configured_in_running_list,
+                                nfapi_resp->num_invalid_tlvs_configured_in_running);
+  fill_config_response_tlv_list(nfapi_resp->missing_tlvs_list, nfapi_resp->num_missing_tlvs);
+}
+
+void test_pack_unpack(nfapi_nr_config_response_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_config_response_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), 0);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_config_response(&unpacked_req, req));
+  free_config_response(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_config_response_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_config_response_scf_t copy = {0};
+  copy_config_response(msg, &copy);
+  DevAssert(eq_config_response(msg, &copy));
+  free_config_response(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_config_response_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE};
+  // Fill Config response TVLs
+  fill_config_response_tlv(&req);
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_config_response(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_error_indication_test.c b/nfapi/tests/p5/nr_fapi_error_indication_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..97431ca9c3f4289307eeab484bce270c38baa5b8
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_error_indication_test.c
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_error_indication_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_error_indication_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  DevAssert(pack_result >= 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_error_indication_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_error_indication(&unpacked_req, req));
+  free_error_indication(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_error_indication_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_error_indication_scf_t copy = {0};
+  copy_error_indication(msg, &copy);
+  DevAssert(eq_error_indication(msg, &copy));
+  free_error_indication(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_error_indication_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION};
+  // Fill the message with randomized data
+  req.sfn = rand16_range(0, 1023);
+  req.slot = rand16_range(0, 159);
+  req.message_id = rand8_range(0x00, 0xFF);
+  req.error_code = rand8_range(0x00, 0x08);
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_error_indication(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_param_request_test.c b/nfapi/tests/p5/nr_fapi_param_request_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..5356160ca4128371bf517c92efedb5f7dcf09d73
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_param_request_test.c
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_param_request_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_param_request_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // PARAM.request message body length is 0
+  DevAssert(pack_result == 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_param_request_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_param_request(&unpacked_req, req));
+  free_param_request(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_param_request_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_param_request_scf_t copy = {0};
+  copy_param_request(msg, &copy);
+  DevAssert(eq_param_request(msg, &copy));
+  free_param_request(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_param_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST};
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_param_request(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_param_response_test.c b/nfapi/tests/p5/nr_fapi_param_response_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..75ca6d5e31ef0878f009038511da7caaed27062c
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_param_response_test.c
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_param_response_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void fill_param_response_tlv(nfapi_nr_param_response_scf_t *nfapi_resp)
+{
+  nfapi_resp->error_code = rand8_range(NFAPI_MSG_OK, NFAPI_MSG_INVALID_STATE);
+
+  FILL_TLV(nfapi_resp->cell_param.release_capability, NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_param.phy_state, NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_param.skip_blank_dl_config, NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_param.skip_blank_ul_config, NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->cell_param.num_config_tlvs_to_report,
+           NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG,
+           rand16_range(0, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG - NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG));
+  nfapi_resp->num_tlv++;
+
+  nfapi_resp->cell_param.config_tlvs_to_report_list =
+      calloc(nfapi_resp->cell_param.num_config_tlvs_to_report.value, sizeof(nfapi_uint8_tlv_t *));
+  for (int i = 0; i < nfapi_resp->cell_param.num_config_tlvs_to_report.value; ++i) {
+    FILL_TLV(nfapi_resp->cell_param.config_tlvs_to_report_list[i],
+             rand16_range(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG),
+             rand8_range(0, 5));
+    nfapi_resp->cell_param.config_tlvs_to_report_list[i].tl.length = 1;
+  }
+
+  FILL_TLV(nfapi_resp->carrier_param.cyclic_prefix, NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_param.supported_subcarrier_spacings_dl,
+           NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
+           rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_param.supported_bandwidth_dl, NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_param.supported_subcarrier_spacings_ul,
+           NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->carrier_param.supported_bandwidth_ul, NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.cce_mapping_type, NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot,
+           NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.coreset_precoder_granularity_coreset,
+           NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.pdcch_mu_mimo, NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.pdcch_precoder_cycling, NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdcch_param.max_pdcch_per_slot, NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pucch_param.pucch_formats, NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pucch_param.max_pucchs_per_slot, NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_mapping_type, NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_allocation_types, NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_vrb_to_prb_mapping, NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_cbg, NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_dmrs_config_types, NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_dmrs_max_length, NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_dmrs_additional_pos, NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.max_pdsch_tbs_per_slot, NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.max_number_mimo_layers_pdsch, NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.supported_max_modulation_order_dl,
+           NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.max_mu_mimo_users_dl, NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_data_in_dmrs_symbols, NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.premption_support, NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pdsch_param.pdsch_non_slot_support, NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.uci_mux_ulsch_in_pusch, NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.uci_only_pusch, NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_frequency_hopping, NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_dmrs_config_types, NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_dmrs_max_len, NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_dmrs_additional_pos, NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_cbg, NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_mapping_type, NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_allocation_types, NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_vrb_to_prb_mapping, NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_max_ptrs_ports, NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.max_pduschs_tbs_per_slot, NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.max_number_mimo_layers_non_cb_pusch,
+           NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.supported_modulation_order_ul, NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.max_mu_mimo_users_ul, NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.dfts_ofdm_support, NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->pusch_param.pusch_aggregation_factor, NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_param.prach_long_formats, NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_param.prach_short_formats, NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, rand16());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_param.prach_restricted_sets, NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->prach_param.max_prach_fd_occasions_in_a_slot,
+           NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
+           rand8());
+  nfapi_resp->num_tlv++;
+
+  FILL_TLV(nfapi_resp->measurement_param.rssi_measurement_support, NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, rand8());
+  nfapi_resp->num_tlv++;
+}
+
+void test_pack_unpack(nfapi_nr_param_response_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // PARAM.response message body length is AT LEAST 10 (NFAPI_HEADER_LENGTH + 1 byte error_code + 1 byte num_tlv)
+  DevAssert(pack_result >= NFAPI_HEADER_LENGTH + 1 + 1);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  nfapi_p4_p5_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpaking and compare with initial message
+  nfapi_nr_param_response_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_param_response(&unpacked_req, req));
+  free_param_response(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_param_response_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_param_response_scf_t copy = {0};
+  copy_param_response(msg, &copy);
+  DevAssert(eq_param_response(msg, &copy));
+  free_param_response(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+  nfapi_nr_param_response_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE};
+  // Fill Param response TVLs
+  fill_param_response_tlv(&req);
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_param_response(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_start_request_test.c b/nfapi/tests/p5/nr_fapi_start_request_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..9384488c46c40ccb188994079c58a2cf4b855e77
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_start_request_test.c
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_start_request_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_start_request_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // START.request message body length is 0
+  DevAssert(pack_result == 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_start_request_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_start_request(&unpacked_req, req));
+  free_start_request(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_start_request_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_start_request_scf_t copy = {0};
+  copy_start_request(msg, &copy);
+  DevAssert(eq_start_request(msg, &copy));
+  free_start_request(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_start_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_REQUEST};
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_start_request(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_start_response_test.c b/nfapi/tests/p5/nr_fapi_start_response_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..32ef894981d9fc6ff477413cbec8dd5f8e64e43b
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_start_response_test.c
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_start_response_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_start_response_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // START.response message body length is 1
+  DevAssert(pack_result == 1 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_start_response_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_start_response(&unpacked_req, req));
+  free_start_response(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_start_response_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_start_response_scf_t copy = {0};
+  copy_start_response(msg, &copy);
+  DevAssert(eq_start_response(msg, &copy));
+  free_start_response(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_start_response_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE};
+  // Fill the message with randomized data
+  req.error_code = rand8_range(0x00, 0x01);
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_start_response(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_stop_indication_test.c b/nfapi/tests/p5/nr_fapi_stop_indication_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee3946c8e40c6ffb0f14a6d4a48eecdf81d69269
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_stop_indication_test.c
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_stop_indication_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_stop_indication_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // STOP.indication message body length is 0
+  DevAssert(pack_result == 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_stop_indication_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_stop_indication(&unpacked_req, req));
+  free_stop_indication(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_stop_indication_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_stop_indication_scf_t copy = {0};
+  copy_stop_indication(msg, &copy);
+  DevAssert(eq_stop_indication(msg, &copy));
+  free_stop_indication(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_stop_indication_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION};
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_stop_indication(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p5/nr_fapi_stop_request_test.c b/nfapi/tests/p5/nr_fapi_stop_request_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..74311cf94e33efc84473d01838709e2ce549282c
--- /dev/null
+++ b/nfapi/tests/p5/nr_fapi_stop_request_test.c
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_stop_request_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5_utils.h"
+
+void test_pack_unpack(nfapi_nr_stop_request_scf_t *req)
+{
+  uint8_t msg_buf[65535];
+  uint16_t msg_len = sizeof(*req);
+  // first test the packing procedure
+  int pack_result = fapi_nr_p5_message_pack(req, msg_len, msg_buf, sizeof(msg_buf), NULL);
+  // STOP.request message body length is 0
+  DevAssert(pack_result == 0 + NFAPI_HEADER_LENGTH);
+  // update req message_length value with value calculated in message_pack procedure
+  req->header.message_length = pack_result - NFAPI_HEADER_LENGTH;
+  // test the unpacking of the header
+  // copy first NFAPI_HEADER_LENGTH bytes into a new buffer, to simulate SCTP PEEK
+  fapi_message_header_t header;
+  uint32_t header_buffer_size = NFAPI_HEADER_LENGTH;
+  uint8_t header_buffer[header_buffer_size];
+  for (int idx = 0; idx < header_buffer_size; idx++) {
+    header_buffer[idx] = msg_buf[idx];
+  }
+  uint8_t *pReadPackedMessage = header_buffer;
+  int unpack_header_result = fapi_nr_p5_message_header_unpack(&pReadPackedMessage, NFAPI_HEADER_LENGTH, &header, sizeof(header), 0);
+  DevAssert(unpack_header_result >= 0);
+  DevAssert(header.message_id == req->header.message_id);
+  DevAssert(header.message_length == req->header.message_length);
+  // test the unpacking and compare with initial message
+  nfapi_nr_stop_request_scf_t unpacked_req = {0};
+  int unpack_result =
+      fapi_nr_p5_message_unpack(msg_buf, header.message_length + NFAPI_HEADER_LENGTH, &unpacked_req, sizeof(unpacked_req), NULL);
+  DevAssert(unpack_result >= 0);
+  DevAssert(eq_stop_request(&unpacked_req, req));
+  free_stop_request(&unpacked_req);
+}
+
+void test_copy(const nfapi_nr_stop_request_scf_t *msg)
+{
+  // Test copy function
+  nfapi_nr_stop_request_scf_t copy = {0};
+  copy_stop_request(msg, &copy);
+  DevAssert(eq_stop_request(msg, &copy));
+  free_stop_request(&copy);
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+
+  nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST};
+  // Perform tests
+  test_pack_unpack(&req);
+  test_copy(&req);
+  // All tests successful!
+  free_stop_request(&req);
+  return 0;
+}
diff --git a/nfapi/tests/p7/CMakeLists.txt b/nfapi/tests/p7/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7cf1958693a8ad0b9faa480e34eb22a46f653e24
--- /dev/null
+++ b/nfapi/tests/p7/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(Test_Labels fapi p7)
+set(_fapi_p7_messages "dci_inversion")
+foreach (fapi_p7_message IN LISTS _fapi_p7_messages)
+    add_executable(nr_fapi_${fapi_p7_message}_test nr_fapi_${fapi_p7_message}_test.c)
+    target_link_libraries(nr_fapi_${fapi_p7_message}_test PUBLIC nr_fapi_p5)
+    target_link_libraries(nr_fapi_${fapi_p7_message}_test PRIVATE pthread UTIL ${T_LIB} minimal_lib)
+    add_dependencies(tests nr_fapi_${fapi_p7_message}_test)
+
+    add_test(nr_fapi_${fapi_p7_message}_test nr_fapi_${fapi_p7_message}_test)
+    set_tests_properties(nr_fapi_${fapi_p7_message}_test PROPERTIES LABELS "${Test_Labels}")
+endforeach ()
+# Add the dci label for the dci payload test
+set(dci_labels dci ${Test_Labels})
+set_tests_properties(nr_fapi_dci_inversion_test PROPERTIES LABELS "dci ${Test_Labels}")
+# Add the FAPI_BYTE_ORDERING_BIG_ENDIAN preprocessor define in order to test the invert/uninvert dci payload functions
+target_compile_definitions(nfapi_common PRIVATE FAPI_BYTE_ORDERING_BIG_ENDIAN)
diff --git a/nfapi/tests/p7/nr_fapi_dci_inversion_test.c b/nfapi/tests/p7/nr_fapi_dci_inversion_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..22e883b0cd91b5246c169b4e35cd6be1bc046acb
--- /dev/null
+++ b/nfapi/tests/p7/nr_fapi_dci_inversion_test.c
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+ *
+ * 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.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+/*! \file nfapi/tests/p5/nr_fapi_param_request_test.c
+ * \brief
+ * \author Ruben S. Silva
+ * \date 2024
+ * \version 0.1
+ * \company OpenAirInterface Software Alliance
+ * \email: contact@openairinterface.org, rsilva@allbesmart.pt
+ * \note
+ * \warning
+ */
+#include "nfapi/tests/nr_fapi_test.h"
+#include "nr_fapi_p5.h"
+#include "nr_fapi.h"
+void printbits(uint64_t n, uint8_t numBytesToPrint)
+{
+  uint64_t i;
+  uint8_t counter = 0;
+  if (numBytesToPrint == 0) {
+    i = 1UL << (sizeof(n) * 8 - 1);
+  } else {
+    i = 1UL << (numBytesToPrint * 8 - 1);
+  }
+  while (i > 0) {
+    if (n & i)
+      printf("1");
+    else
+      printf("0");
+    i >>= 1;
+    counter++;
+    if (counter % 8 == 0) {
+      printf(" ");
+    }
+  }
+}
+
+/*! \brief Drops unwanted bits from a byte array, leaving only a specified number of payload bits
+ *
+ *  \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN)
+ *  \param payload[] A uint8_t array containing the payload bytes with random data
+ *  \details This function creates a bitmask of payloadSizeBits width to truncate the data in payload[] to only have the specified
+ *  number of payload bits\n
+ *  For example, a payload of 39 bits needs 5 bytes, but on the last byte, the last bit is unused, this function makes sure that
+ *  last bit is set to 0, allowing the payload to be then packed and unpacked and successfully compared with the original payload
+ */
+void truncate_unwanted_bits(uint8_t payloadSizeBits, uint8_t payload[])
+{
+  uint8_t payloadSizeBytes = (payloadSizeBits + 7) / 8;
+  printf("Original Value:\t");
+  uint64_t t = 0;
+  memcpy(&t, payload, payloadSizeBytes);
+  printbits(t, payloadSizeBytes);
+  printf("\n");
+  uint64_t bitmask = 1;
+  for (int i = 0; i < payloadSizeBits - 1; i++) {
+    bitmask = bitmask << 1 | 1;
+  }
+  printf("Calculated Bitmask:\t");
+  printbits(bitmask, payloadSizeBytes);
+  printf("\n");
+  t = t & bitmask;
+  printf("Truncated Value:\t");
+  printbits(t, payloadSizeBytes);
+  printf("\n");
+  memcpy(payload, &t, payloadSizeBytes);
+}
+
+/*! \brief Generates a random payload payloadSizeBits long into payload[]
+ *
+ *  \param payloadSizeBits How many bits the payload is to have, from 1 to 64 (8 * DCI_PAYLOAD_BYTE_LEN)
+ *  \param payload[] A uint8_t array to contain the generated payload
+ *  \details This function fills a uint8_t array with payloadSizeBits of random data, by first filling however many bytes are needed
+ *  to contain payloadSizeBits with random data, and then truncating the excess bits
+ */
+void generate_payload(uint8_t payloadSizeBits, uint8_t payload[])
+{
+  for (int i = 0; i < (payloadSizeBits + 7) / 8; ++i) {
+    payload[i] = rand8();
+  }
+  truncate_unwanted_bits(payloadSizeBits, payload);
+}
+
+void test_pack_payload(uint8_t payloadSizeBits, uint8_t payload[])
+{
+  uint8_t msg_buf[8192] = {0};
+  uint8_t payloadSizeBytes = (payloadSizeBits + 7) / 8;
+  uint8_t *pWritePackedMessage = msg_buf;
+  uint8_t *pPackMessageEnd = msg_buf + sizeof(msg_buf);
+
+  pack_dci_payload(payload, payloadSizeBits, &pWritePackedMessage, pPackMessageEnd);
+
+  uint8_t unpack_buf[payloadSizeBytes];
+  pWritePackedMessage = msg_buf;
+  unpack_dci_payload(unpack_buf, payloadSizeBits, &pWritePackedMessage, pPackMessageEnd);
+
+  printf("\nOriginal:\t");
+  for (int j = payloadSizeBytes - 1; j >= 0; j--) {
+    printbits(payload[j], 1);
+    printf(" ");
+  }
+  printf("\n");
+
+  printf("Unpacked:\t");
+  for (int j = payloadSizeBytes - 1; j >= 0; j--) {
+    printbits(unpack_buf[j], 1);
+    printf(" ");
+  }
+  printf("\n");
+
+  DevAssert(memcmp(payload, unpack_buf, payloadSizeBytes) == 0);
+  // All tests successful!
+}
+
+int main(int n, char *v[])
+{
+  fapi_test_init();
+  uint8_t upper = 8 * DCI_PAYLOAD_BYTE_LEN;
+  uint8_t lower = 1;
+  uint8_t payloadSizeBits = (rand() % (upper - lower + 1)) + lower; // from 1 bit to DCI_PAYLOAD_BYTE_LEN, in bits
+  printf("payloadSizeBits:%d\n", payloadSizeBits);
+  uint8_t payload[(payloadSizeBits + 7) / 8];
+
+  generate_payload(payloadSizeBits, payload);
+  test_pack_payload(payloadSizeBits, payload);
+  return 0;
+}
diff --git a/openair1/PHY/nr_phy_common/CMakeLists.txt b/openair1/PHY/nr_phy_common/CMakeLists.txt
index 79dc8dd7f3543aa937a180d8f9f0242508a073a3..3ba2666b0829892358dcf75cc98f00cc2123d680 100644
--- a/openair1/PHY/nr_phy_common/CMakeLists.txt
+++ b/openair1/PHY/nr_phy_common/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_library(nr_phy_common src/nr_phy_common.c)
+target_link_libraries(nr_phy_common PRIVATE UTIL)
 target_include_directories(nr_phy_common PUBLIC inc/)
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
index c8d8232382dec0ea2bc9f020255f24a5de50c820..6973f06103247b3a1375160500467c0163355a57 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
@@ -571,6 +571,7 @@ typedef struct NR_UE_UL_BWP {
   uint8_t mcs_table;
   nr_dci_format_t dci_format;
   int max_fb_time;
+  long *p0_NominalWithGrant;
 } NR_UE_UL_BWP_t;
 
 // non-BWP serving cell configuration
@@ -614,6 +615,7 @@ typedef struct NR_tda_info {
   int startSymbolIndex;
   int nrOfSymbols;
   long k2;
+  bool valid_tda;
 } NR_tda_info_t;
 
 #endif /*__LAYER2_MAC_H__ */
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index d612a6dcc67aaaa09a4bfd71a62109331a36884f..1f043728a1e7059f3764aeb113695e0d78a0f7a0 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -467,7 +467,11 @@ NR_tda_info_t get_ul_tda_info(const NR_UE_UL_BWP_t *ul_bwp,
   AssertFatal(scs >= 0 &&  scs < 5, "Subcarrier spacing indicatior %d invalid value\n", scs);
   int j = scs == 0 ? 1 : scs;
   if (tdalist) {
-    AssertFatal(tda_index < tdalist->list.count, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
+    tda_info.valid_tda = tda_index < tdalist->list.count;
+    if (!tda_info.valid_tda) {
+      LOG_E(NR_MAC, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
+      return tda_info;
+    }
     NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdalist->list.array[tda_index];
     tda_info.mapping_type = tda->mappingType;
     // As described in 38.331, when the field is absent the UE applies the value 1 when PUSCH SCS is 15/30KHz
@@ -479,6 +483,11 @@ NR_tda_info_t get_ul_tda_info(const NR_UE_UL_BWP_t *ul_bwp,
     tda_info.nrOfSymbols = L;
   } else {
     bool normal_CP = ul_bwp->cyclicprefix ? false : true;
+    tda_info.valid_tda = tda_index < 16;
+    if (!tda_info.valid_tda) {
+      LOG_E(NR_MAC, "TDA index from DCI %d exceeds default TDA list array size %d\n", tda_index, 16);
+      return tda_info;
+    }
     if (normal_CP) {
       tda_info.mapping_type = table_6_1_2_1_1_2[tda_index][0];
       tda_info.k2 = table_6_1_2_1_1_2[tda_index][1] + j;
@@ -500,6 +509,11 @@ NR_tda_info_t get_info_from_tda_tables(default_table_type_t table_type,
                                        int normal_CP)
 {
   NR_tda_info_t tda_info = {0};
+  tda_info.valid_tda = tda < 16;
+  if (!tda_info.valid_tda) {
+    LOG_E(NR_MAC, "TDA index from DCI %d exceeds default TDA list array size %d\n", tda, 16);
+    return tda_info;
+  }
   bool is_mapping_typeA;
   int k0 = 0;
   switch(table_type){
@@ -586,7 +600,11 @@ default_table_type_t get_default_table_type(int mux_pattern)
 NR_tda_info_t set_tda_info_from_list(NR_PDSCH_TimeDomainResourceAllocationList_t *tdalist, int tda_index)
 {
   NR_tda_info_t tda_info = {0};
-  AssertFatal(tda_index < tdalist->list.count, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
+  tda_info.valid_tda = tda_index < tdalist->list.count;
+  if (!tda_info.valid_tda) {
+    LOG_E(NR_MAC, "TDA index from DCI %d exceeds TDA list array size %d\n", tda_index, tdalist->list.count);
+    return tda_info;
+  }
   NR_PDSCH_TimeDomainResourceAllocation_t *tda = tdalist->list.array[tda_index];
   tda_info.mapping_type = tda->mappingType;
   int S, L;
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 52d45c938b4e9ec81e2fa6381540ad40c69714f5..50577fc4f72e8b198811cf1284cd7887ebc287e7 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -1409,11 +1409,14 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
                   ul_common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList,
                   NR_PUSCH_TimeDomainResourceAllocationList_t);
         UPDATE_IE(bwp->msg3_DeltaPreamble, ul_common->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble, long);
+        UPDATE_IE(bwp->p0_NominalWithGrant, ul_common->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant, long);
       }
       if (ul_common->pusch_ConfigCommon->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_release) {
         asn1cFreeStruc(asn_DEF_NR_PUSCH_TimeDomainResourceAllocationList, bwp->tdaList_Common);
         free(bwp->msg3_DeltaPreamble);
         bwp->msg3_DeltaPreamble = NULL;
+        free(bwp->p0_NominalWithGrant);
+        bwp->p0_NominalWithGrant = NULL;
       }
     }
   }
@@ -2130,6 +2133,8 @@ void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index)
   asn1cFreeStruc(asn_DEF_NR_SRS_Config, bwp->srs_Config);
   free(bwp->msg3_DeltaPreamble);
   bwp->msg3_DeltaPreamble = NULL;
+  free(bwp->p0_NominalWithGrant);
+  bwp->p0_NominalWithGrant = NULL;
   free(bwp);
 }
 
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index 3ffcc3495c935a2acd696c186f7e60d0949098f6..88973af84971f73f185bea8dfdf0ad56ae4f0366 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -219,6 +219,20 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
                               int subframe_number,
                               int O_uci,
                               uint16_t start_prb);
+int get_pusch_tx_power_ue(
+  NR_UE_MAC_INST_t *mac,
+  int num_rb,
+  int start_prb,
+  uint16_t nb_symb_sch,
+  uint16_t nb_dmrs_prb,
+  uint16_t nb_ptrs_prb,
+  uint16_t qm,
+  uint16_t R,
+  uint16_t beta_offset_csi1,
+  uint32_t sum_bits_in_codeblocks,
+  int delta_pusch,
+  bool is_rar_tx_retx,
+  bool transform_precoding);
 
 int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
                            int slot,
@@ -227,16 +241,18 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
                            PUCCH_sched_t *pucch,
                            fapi_nr_ul_config_pucch_pdu *pucch_pdu);
 
-int nr_get_Pcmax(int p_Max,
-                 uint16_t nr_band,
-                 frequency_range_t frequency_range,
-                 int Qm,
-                 bool powerBoostPi2BPSK,
-                 int scs,
-                 int N_RB_UL,
-                 bool is_transform_precoding,
-                 int n_prbs,
-                 int start_prb);
+float nr_get_Pcmax(int p_Max,
+                   uint16_t nr_band,
+                   frequency_range_t frequency_range,
+                   int Qm,
+                   bool powerBoostPi2BPSK,
+                   int scs,
+                   int N_RB_UL,
+                   bool is_transform_precoding,
+                   int n_prbs,
+                   int start_prb);
+
+float nr_get_Pcmin(int scs, int nr_band, int N_RB_UL);
 
 int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame);
 
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
index e826d95e4c35e3e5d30d21666eb8444d8ace38f2..0dbaa5debf1e65beac95888bf0c663b788eb8e4e 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
@@ -65,62 +65,34 @@ static int get_deltatf(uint16_t nb_of_prbs,
                        int N_sc_ctrl_RB,
                        int O_UCI);
 
-// Implementation of 6.2.4 Configured ransmitted power
-// 3GPP TS 38.101-1 version 16.5.0 Release 16
-// -
-// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot.
-// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <=  PCMAX,f,c <=  PCMAX_H,f,c
-// -
-// Measurement units:
-// - p_max:              dBm
-// - delta_TC_c:         dB
-// - P_powerclass:       dBm
-// - delta_P_powerclass: dB
-// - MPR_c:              dB
-// - delta_MPR_c:        dB
-// - delta_T_IB_c        dB
-// - delta_rx_SRS        dB
-// note:
-// - Assuming:
-// -- Powerclass 3 capable UE (which is default power class unless otherwise stated)
-// -- Maximum power reduction (MPR_c) for power class 3
-// -- no additional MPR (A_MPR_c)
-int nr_get_Pcmax(int p_Max,
-                 uint16_t nr_band,
-                 frequency_range_t frequency_range,
-                 int Qm,
-                 bool powerBoostPi2BPSK,
-                 int scs,
-                 int N_RB_UL,
-                 bool is_transform_precoding,
-                 int n_prbs,
-                 int start_prb)
+// ∆MPR according to Table 6.2.2-3 38.101-1
+static float get_delta_mpr(uint16_t nr_band, int scs, int N_RB_UL, int n_prbs, int start_prb, int power_class)
 {
-  if (frequency_range == FR1) {
-    // TODO configure P-MAX from the upper layers according to 38.331
-    int p_powerclass = 23; // dBm assuming poweclass 3 UE
-    int p_emax = p_Max != INT_MIN ? p_Max : p_powerclass;
-    int delta_P_powerclass = 0; // for powerclass 2 needs to be changed
-    if (p_Max && Qm == 1 && powerBoostPi2BPSK
-        && (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) {
-      p_emax += 3;
-      delta_P_powerclass -= 3;
+  frame_type_t frame_type = get_frame_type(nr_band, scs);
+  if (compare_relative_ul_channel_bw(nr_band, scs, N_RB_UL, frame_type)) {
+    if (power_class == 3) {
+      if ((nr_band == 28 || nr_band == 83) && get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL) == 30) {
+        return 0.5f;
+      }
     }
+    if (power_class == 3 || power_class == 2) {
+      if ((nr_band == 40 || nr_band == 97) && get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL) == 100) {
+        return 1.0f;
+      }
+    }
+  }
+  return 0;
+}
 
-    // TODO to be set for CA and DC
-    int delta_T_IB = 0;
-
-    // TODO in case of band 41 and PRB allocation within 4MHz of the upper or lower limit of the band -> delta_TC = 1.5
-    if (nr_band == 41)
-      LOG_E(NR_MAC, "Need to implement delta_TC for band 41\n");
-    int delta_TC = 0;
-
-    float MPR = 0;
-    frame_type_t frame_type = get_frame_type(nr_band, scs);
-    if (compare_relative_ul_channel_bw(nr_band, scs, N_RB_UL, frame_type)) {
-      int rb_low = (n_prbs / 2) > 1 ? (n_prbs / 2) : 1;
-      int rb_high = N_RB_UL - rb_low - n_prbs;
-      bool is_inner_rb = start_prb >= rb_low && start_prb <= rb_high && n_prbs <= ((N_RB_UL / 2) + (N_RB_UL & 1));
+// MPR according to 38-101 6.2.2
+static float get_mpr(int Qm, int N_RB_UL, bool is_transform_precoding, int n_prbs, int start_prb, int power_class)
+{
+  float MPR = 0;
+  int rb_low = (n_prbs / 2) > 1 ? (n_prbs / 2) : 1;
+  int rb_high = N_RB_UL - rb_low - n_prbs;
+  bool is_inner_rb = start_prb >= rb_low && start_prb <= rb_high && n_prbs <= ((N_RB_UL / 2) + (N_RB_UL & 1));
+  switch (power_class) {
+    case 3:
       // Table 6.2.2-1 in 38.101
       switch (Qm) {
         case 1:
@@ -166,16 +138,73 @@ int nr_get_Pcmax(int p_Max,
         default:
           AssertFatal(false, "Invalid Qm %d\n", Qm);
       }
+      break;
+    default:
+      AssertFatal(false, "PowerClass != 3 not implemented\n");
+  }
+  return MPR;
+}
+
+// Implementation of 6.2.4 Configured ransmitted power
+// 3GPP TS 38.101-1 version 16.5.0 Release 16
+// -
+// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot.
+// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <=  PCMAX,f,c <=  PCMAX_H,f,c
+// -
+// Measurement units:
+// - p_max:              dBm
+// - delta_TC_c:         dB
+// - P_powerclass:       dBm
+// - delta_P_powerclass: dB
+// - MPR_c:              dB
+// - delta_MPR_c:        dB
+// - delta_T_IB_c        dB
+// - delta_rx_SRS        dB
+// note:
+// - Assuming:
+// -- Powerclass 3 capable UE (which is default power class unless otherwise stated)
+// -- Maximum power reduction (MPR_c) for power class 3
+// -- no additional MPR (A_MPR_c)
+float nr_get_Pcmax(int p_Max,
+                   uint16_t nr_band,
+                   frequency_range_t frequency_range,
+                   int Qm,
+                   bool powerBoostPi2BPSK,
+                   int scs,
+                   int N_RB_UL,
+                   bool is_transform_precoding,
+                   int n_prbs,
+                   int start_prb)
+{
+  const int power_class = 3; // Assume power class 3
+  if (frequency_range == FR1) {
+    // TODO configure P-MAX from the upper layers according to 38.331
+    int p_powerclass = 23; // dBm assuming poweclass 3 UE
+    int p_emax = p_Max != INT_MIN ? p_Max : p_powerclass;
+    int delta_P_powerclass = 0; // for powerclass 2 needs to be changed
+    if (p_Max && Qm == 1 && powerBoostPi2BPSK
+        && (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) {
+      p_emax += 3;
+      delta_P_powerclass -= 3;
     }
 
+    // TODO to be set for CA and DC
+    int delta_T_IB = 0;
+
+    // TODO in case of band 41 and PRB allocation within 4MHz of the upper or lower limit of the band -> delta_TC = 1.5
+    if (nr_band == 41)
+      LOG_E(NR_MAC, "Need to implement delta_TC for band 41\n");
+    int delta_TC = 0;
+
+    float MPR = get_mpr(Qm, N_RB_UL, is_transform_precoding, n_prbs, start_prb, power_class);
+    float delta_MPR = get_delta_mpr(nr_band, scs, N_RB_UL, n_prbs, start_prb, power_class);
     int A_MPR = 0; // TODO too complicated to implement for now (see 6.2.3 in 38.101-1)
     int delta_rx_SRS = 0; // TODO for SRS
     int P_MPR = 0; // to ensure compliance with applicable electromagnetic energy absorption requirements
 
-    float total_reduction = (MPR > A_MPR ? MPR : A_MPR) + delta_T_IB + delta_TC + delta_rx_SRS;
-    if (P_MPR > total_reduction)
-      total_reduction = P_MPR;
-    int pcmax_high, pcmax_low;
+    float total_reduction = max(max(MPR + delta_MPR, A_MPR) + delta_T_IB + delta_TC + delta_rx_SRS, P_MPR);
+
+    float pcmax_high, pcmax_low;
     if (p_Max) {
       pcmax_high = p_emax < (p_powerclass - delta_P_powerclass) ? p_emax : (p_powerclass - delta_P_powerclass);
       pcmax_low = (p_emax - delta_TC) < (p_powerclass - delta_P_powerclass - total_reduction)
@@ -186,8 +215,8 @@ int nr_get_Pcmax(int p_Max,
       pcmax_low = p_powerclass - delta_P_powerclass - total_reduction;
     }
     // TODO we need a strategy to select a value between minimum and maximum allowed PC_max
-    int pcmax = (pcmax_low + pcmax_high) / 2;
-    LOG_D(MAC, "Configured maximum output power:  %d dBm <= PCMAX %d dBm <= %d dBm \n", pcmax_low, pcmax, pcmax_high);
+    float pcmax = (pcmax_low + pcmax_high) / 2;
+    LOG_D(MAC, "Configured maximum output power:  %f dBm <= PCMAX %f dBm <= %f dBm \n", pcmax_low, pcmax, pcmax_high);
     return pcmax;
   } else {
     // FR2 TODO it is even more complex because it is radiated power
@@ -195,6 +224,14 @@ int nr_get_Pcmax(int p_Max,
   }
 }
 
+float nr_get_Pcmin(int scs, int nr_band, int N_RB_UL) {
+  int band_index = get_supported_band_index(nr_band > 256 ? FR2 : FR1, scs, N_RB_UL);
+  const float table_38101_6_3_1_1[] = {
+    -40, -40, -40, -40, -39, -38.2, -37.5, -37, -36.5, -35.2, -34.6, -34, -33.5, -33
+  };
+  return table_38101_6_3_1_1[band_index];
+}
+
 // This is not entirely correct. In certain k2/k1/k0 settings we might postpone accumulating delta_PUCCH until next HARQ feedback
 // slot. The correct way to do this would be to calculate the K_PUCCH (delta_PUCCH summation window end) for each PUCCH occasion and
 // compare PUCCH transmission symbol with the reception symbol of the DCI containing delta_PUCCH to determine if the delta_PUCCH
@@ -297,8 +334,9 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
     delta_F_PUCCH = *delta_F_PUCCH_config;
   }
 
-  // PUCCH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1)
-  // TODO: P_CMAX for format 2
+  // 38.101-1: The allowed MPR for SRS, PUCCH formats 0, 1, 3 and 4, and PRACH shall be as specified for QPSK modulated DFT-
+  // s-OFDM of equivalent RB allocation. The allowed MPR for PUCCH format 2 shall be as specified for QPSK
+  // modulated CP-OFDM of equivalent RB allocation.
   int P_CMAX = nr_get_Pcmax(mac->p_Max,
                             mac->nr_band,
                             mac->frequency_range,
@@ -306,10 +344,10 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
                             false,
                             mac->current_UL_BWP->scs,
                             mac->current_UL_BWP->BWPSize,
-                            true,
+                            format_type == 2,
                             1,
                             start_prb);
-  int P_CMIN = -40; // TODO: minimum TX power, possibly 38.101-1 6.3.1
+  int P_CMIN = nr_get_Pcmin(mac->current_UL_BWP->scs, mac->nr_band,  mac->current_UL_BWP->BWPSize);
   int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
 
   if (power_config->twoPUCCH_PC_AdjustmentStates && *power_config->twoPUCCH_PC_AdjustmentStates > 1) {
@@ -396,3 +434,136 @@ int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm)
 
   return pathloss;
 }
+
+// PUSCH transmission power according to 38.213 7.1
+int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac,
+                          int num_rb,
+                          int start_prb,
+                          uint16_t nb_symb_sch,
+                          uint16_t nb_dmrs_prb,
+                          uint16_t nb_ptrs_prb,
+                          uint16_t qm,
+                          uint16_t R,
+                          uint16_t beta_offset_csi1,
+                          uint32_t sum_bits_in_codeblocks,
+                          int delta_pusch,
+                          bool is_rar_tx_retx,
+                          bool transform_precoding)
+{
+  LOG_D(NR_MAC,
+        "PUSCH tx power determination num_rb=%d start_prb=%d nb_symb_sch=%u nb_dmrs_prb=%u nb_ptrs_prb=%u Qm=%u R= %u "
+        "beta_offset_cs1=%u sum_bits_in_codeblocks=%u delta_pusch=%d is_rar_tx_retx=%d transform_precoding=%d\n",
+        num_rb,
+        start_prb,
+        nb_symb_sch,
+        nb_dmrs_prb,
+        nb_ptrs_prb,
+        qm,
+        R,
+        beta_offset_csi1,
+        sum_bits_in_codeblocks,
+        delta_pusch,
+        is_rar_tx_retx,
+        transform_precoding);
+  NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+  AssertFatal(current_UL_BWP, "Missing configuration: need UL_BWP to calculate PUSCH tx power\n");
+  NR_PUSCH_Config_t *pusch_Config = current_UL_BWP->pusch_Config;
+  bool has_pusch_config = pusch_Config != NULL;
+  bool has_pusch_power_control_config = has_pusch_config && pusch_Config->pusch_PowerControl != NULL;
+  bool is_provided_alpha_sets = has_pusch_power_control_config && pusch_Config->pusch_PowerControl->p0_AlphaSets != NULL;
+  AssertFatal(!has_pusch_power_control_config || pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToAddModList == NULL,
+              "SRI-PUSCH-PowerControl handling not implemented\n");
+
+  int P_O_NOMINAL_PUSCH;
+  float alpha;
+  const float alpha_factor_table[8] = {0.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f};
+  if (is_rar_tx_retx || !is_provided_alpha_sets || current_UL_BWP->p0_NominalWithGrant == NULL) {
+    int DELTA_PREAMBLE_MSG3 = 0;
+    if (current_UL_BWP->msg3_DeltaPreamble) {
+      DELTA_PREAMBLE_MSG3 = *current_UL_BWP->msg3_DeltaPreamble;
+    }
+    NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon;
+    long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
+    int P_O_PRE = preambleReceivedTargetPower;
+    P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3;
+
+    if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->msg3_Alpha) {
+      alpha = alpha_factor_table[*pusch_Config->pusch_PowerControl->msg3_Alpha];
+    } else {
+      alpha = 1.0f;
+    }
+  } else {
+    P_O_NOMINAL_PUSCH = *current_UL_BWP->p0_NominalWithGrant;
+    if (pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->alpha) {
+      alpha = alpha_factor_table[*pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->alpha];
+    } else {
+      // Default according to 38.331 P0-PUSCH-AlphaSet field descriptions
+      alpha = 1.0f;
+    }
+  }
+
+  int P_O_UE_PUSCH;
+  if (is_rar_tx_retx || !is_provided_alpha_sets) {
+    P_O_UE_PUSCH = 0;
+  } else {
+    if (pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->p0) {
+      P_O_UE_PUSCH = *pusch_Config->pusch_PowerControl->p0_AlphaSets->list.array[0]->p0;
+    } else {
+      // Default according to 38.331 P0-PUSCH-AlphaSet field descriptions
+      P_O_UE_PUSCH = 0;
+    }
+  }
+
+  int mu = current_UL_BWP->scs;
+
+  int M_pusch_component = 10 * log10((pow(2, mu)) * num_rb);
+  int P_CMAX = nr_get_Pcmax(mac->p_Max,
+                            mac->nr_band,
+                            mac->frequency_range,
+                            2,
+                            false,
+                            mac->current_UL_BWP->scs,
+                            mac->current_UL_BWP->BWPSize,
+                            transform_precoding,
+                            1,
+                            start_prb);
+
+  int P_O_PUSCH = P_O_NOMINAL_PUSCH + P_O_UE_PUSCH;
+
+  float DELTA_TF = 0;
+  if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->deltaMCS) {
+    float beta_offset = 1;
+    float BPRE;
+    if (sum_bits_in_codeblocks == 0) {
+      float table_38_213_9_3_2[] = {
+          1.125,   11.250,  21.375,  31.625,  41.750,  52.000,   62.250,   72.500,   82.875,   93.125,
+          103.500, 114.000, 125.000, 136.250, 148.000, 1510.000, 1612.625, 1715.875, 1820.000,
+      };
+      beta_offset = table_38_213_9_3_2[beta_offset_csi1];
+      BPRE = (qm * R / beta_offset) / 1024;
+    } else {
+      const int nb_subcarrier_per_rb = 12;
+      const uint32_t N_RE = nb_subcarrier_per_rb * nb_symb_sch - nb_dmrs_prb - nb_ptrs_prb;
+      BPRE = sum_bits_in_codeblocks / (float)(N_RE * num_rb);
+    }
+    DELTA_TF = 10 * log10(pow(2, BPRE * 1.25f) * beta_offset);
+  }
+
+  // TODO: compute pathoss using correct reference
+  int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
+
+  int f_b_f_c = 0;
+  if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->tpc_Accumulation) {
+    f_b_f_c = delta_pusch;
+  } else {
+    // TODO: PUSCH power control state
+  }
+  LOG_D(NR_MAC,
+        "PUSCH tx power components P_O_PUSCH=%d, M_pusch_component=%d, alpha*pathloss=%f, delta_TF=%f, f_b_f_c=%d\n",
+        P_O_PUSCH,
+        M_pusch_component,
+        alpha * pathloss,
+        DELTA_TF,
+        f_b_f_c);
+  return min(P_CMAX, P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + f_b_f_c);
+}
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index fcc5eb4d50da56d7b6d262df3df9c49ad5a36972..82e7a541d5b8f3d71a2a1d2e4972dfe62479c436 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -435,11 +435,12 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
                                            dci_ind->ss_type,
                                            get_rnti_type(mac, dci_ind->rnti),
                                            dci->time_domain_assignment.val);
-  frame_t frame_tx;
-  int slot_tx;
-  if (tda_info.nrOfSymbols == 0)
+
+  if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0)
     return -1;
 
+  frame_t frame_tx;
+  int slot_tx;
   if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2)) {
     LOG_E(MAC, "Cannot schedule PUSCH\n");
     return -1;
@@ -525,15 +526,18 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
                                            get_rnti_type(mac, dci_ind->rnti),
                                            dci->time_domain_assignment.val);
 
+  if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0)
+    return -1;
+
   if (dci->ulsch_indicator == 0) {
     // in case of CSI on PUSCH and no ULSCH we need to use reportSlotOffset in trigger state
-    AssertFatal(csi_K2 > 0, "Invalid CSI K2 value %ld\n", csi_K2);
+    if (csi_K2 <= 0) {
+      LOG_E(MAC, "Invalid CSI K2 value %ld\n", csi_K2);
+      return -1;
+    }
     tda_info.k2 = csi_K2;
   }
 
-  if (tda_info.nrOfSymbols == 0)
-    return -1;
-
   if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2)) {
     LOG_E(MAC, "Cannot schedule PUSCH\n");
     return -1;
@@ -679,6 +683,8 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
                                            rnti_type,
                                            coreset_type,
                                            mac->get_sib1);
+  if (!tda_info.valid_tda)
+    return -1;
 
   dlsch_pdu->number_symbols = tda_info.nrOfSymbols;
   dlsch_pdu->start_symbol = tda_info.startSymbolIndex;
@@ -990,6 +996,8 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
                                            rnti_type,
                                            coreset_type,
                                            false);
+  if (!tda_info.valid_tda)
+    return -1;
 
   dlsch_pdu->number_symbols = tda_info.nrOfSymbols;
   dlsch_pdu->start_symbol = tda_info.startSymbolIndex;
@@ -3949,7 +3957,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
                                              pdcch_config->ra_SS->searchSpaceType->present,
                                              TYPE_RA_RNTI_,
                                              rar_grant.Msg3_t_alloc);
-    if (tda_info.nrOfSymbols == 0) {
+    if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) {
       LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
       return;
     }
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 29b36d3e9d420361470d115aa77d23bd98da1650..20b0e80f61c607708ed05ddaadbe1a0edc450b2c 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -913,6 +913,22 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
     pusch_config_pdu->pusch_data.tb_size = mac->ul_harq_info[pid].TBS;
   }
 
+  bool is_rar_tx_retx = rnti_type == TYPE_TC_RNTI_;
+
+  pusch_config_pdu->tx_power = get_pusch_tx_power_ue(mac,
+                                                     pusch_config_pdu->rb_size,
+                                                     pusch_config_pdu->rb_start,
+                                                     pusch_config_pdu->nr_of_symbols,
+                                                     nb_dmrs_re_per_rb * number_dmrs_symbols,
+                                                     0, //TODO: count PTRS per RB
+                                                     pusch_config_pdu->qam_mod_order,
+                                                     pusch_config_pdu->target_code_rate,
+                                                     pusch_config_pdu->pusch_uci.beta_offset_csi1,
+                                                     pusch_config_pdu->pusch_data.tb_size << 3,
+                                                     pusch_config_pdu->absolute_delta_PUSCH,
+                                                     is_rar_tx_retx,
+                                                     pusch_config_pdu->transform_precoding);
+
   pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate);
 
   //The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH
diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
index 179d94bd1b1e37f76451de653c7cca82f42c13fa..49f2d58f279876deaea4f470aa684e168b36815c 100644
--- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
+++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp
@@ -19,43 +19,314 @@
  *      contact@openairinterface.org
  */
 
-
 #include "gtest/gtest.h"
 extern "C" {
 #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
 #include "executables/softmodem-common.h"
-uint64_t get_softmodem_optmask(void) {return 0;}
+uint64_t get_softmodem_optmask(void)
+{
+  return 0;
+}
 static softmodem_params_t softmodem_params;
-softmodem_params_t *get_softmodem_params(void) {
+softmodem_params_t* get_softmodem_params(void)
+{
   return &softmodem_params;
-
 }
 }
 #include <cstdio>
 #include "common/utils/LOG/log.h"
 
-TEST(power_procedures_fr1, test_prach_max_tx_power_mpr)
+TEST(test_pcmax, test_mpr)
 {
-  // Inner PRB, MPR = 1.5
+  // Inner PRB, MPR = 1.5, no delta MPR
   int prb_start = 4;
   int N_RB_UL = 51; // 10Mhz
-  EXPECT_EQ(22, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
+  int nr_band = 20;
+  float expected_power = 23 - (1.5 / 2);
+  EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
 
-  // Outer PRB, MPR = 3
+  // Outer PRB, MPR = 3, no delta MPR
   prb_start = 0;
-  EXPECT_EQ(21, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
+  expected_power = 23 - (3.0 / 2);
+  EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
 
-  // Channel bandwidth conditon not met, no MPR
-  N_RB_UL = 106;
-  EXPECT_EQ(23, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 6, prb_start));
+  // Outer PRB on band 28, MPR = 3, delta MPR = 0.5 dB
+  N_RB_UL = 78;
+  nr_band = 28;
+  expected_power = 23 - ((3.0 + 0.5) / 2);
+  EXPECT_EQ(expected_power, nr_get_Pcmax(23, nr_band, FR1, 2, false, 1, N_RB_UL, false, 100, prb_start));
 }
 
-TEST(power_procedures_fr1, test_not_implemented)
+TEST(test_pcmax, test_not_implemented)
 {
   int N_RB_UL = 51;
   EXPECT_DEATH(nr_get_Pcmax(23, 20, FR1, 1, false, 1, N_RB_UL, false, 6, 0), "MPR for Pi/2 BPSK not implemented yet");
 }
 
+TEST(test_pcmax, test_pucch_max_power)
+{
+  // Format 2, transform precoding, MPR = 1
+  int prb_start = 0;
+  int N_RB_UL = 51; // 10Mhz
+  float expected_power = 23 - (1.0 / 2);
+  EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, true, 1, prb_start));
+
+  // Other fromats, no transform precoding, MPR = 3
+  expected_power = 23 - (3.0 / 2);
+  EXPECT_EQ(expected_power, nr_get_Pcmax(23, 20, FR1, 2, false, 1, N_RB_UL, false, 1, prb_start));
+}
+
+TEST(test_pucch_power_state, test_accumulated_delta_pucch)
+{
+  NR_UE_MAC_INST_t mac = {0};
+  NR_UE_UL_BWP_t current_UL_BWP = {0};
+  current_UL_BWP.scs = 1;
+  current_UL_BWP.BWPSize = 106;
+  NR_PUCCH_ConfigCommon_t pucch_ConfigCommon = {0};
+  mac.current_UL_BWP = &current_UL_BWP;
+  mac.current_UL_BWP->pucch_ConfigCommon = &pucch_ConfigCommon;
+  mac.nr_band = 20;
+  NR_PUCCH_Config_t pucch_Config = {0};
+  struct NR_PUCCH_PowerControl power_config;
+  pucch_Config.pucch_PowerControl = &power_config;
+  mac.G_b_f_c = 0;
+  mac.pucch_power_control_initialized = true;
+
+  int scs = 1;
+  int sum_delta_pucch = 3;
+  uint8_t format_type = 1;
+  uint16_t nb_of_prbs = 1;
+  uint8_t freq_hop_flag = 0;
+  uint8_t add_dmrs_flag = 0;
+  uint8_t N_symb_PUCCH = 12;
+  int subframe_number = 0;
+  int O_uci = 2;
+  uint16_t start_prb = 0;
+  int P_CMAX =
+      nr_get_Pcmax(23, mac.nr_band, FR1, 2, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, false, nb_of_prbs, start_prb);
+  int pucch_power_prev = get_pucch_tx_power_ue(&mac,
+                                               scs,
+                                               &pucch_Config,
+                                               sum_delta_pucch,
+                                               format_type,
+                                               nb_of_prbs,
+                                               freq_hop_flag,
+                                               add_dmrs_flag,
+                                               N_symb_PUCCH,
+                                               subframe_number,
+                                               O_uci,
+                                               start_prb);
+  EXPECT_LT(pucch_power_prev, P_CMAX);
+  for (int i = 0; i < 10; i++) {
+    int pucch_power_state = mac.G_b_f_c;
+    int pucch_power = get_pucch_tx_power_ue(&mac,
+                                            scs,
+                                            &pucch_Config,
+                                            sum_delta_pucch,
+                                            format_type,
+                                            nb_of_prbs,
+                                            freq_hop_flag,
+                                            add_dmrs_flag,
+                                            N_symb_PUCCH,
+                                            subframe_number,
+                                            O_uci,
+                                            start_prb);
+    if (pucch_power_prev == P_CMAX) {
+      EXPECT_EQ(pucch_power_state, mac.G_b_f_c) << "PUCCH power control state increased after reaching max TX power";
+    }
+    EXPECT_LE(pucch_power, P_CMAX) << "PUUCH TX power above P_CMAX";
+    EXPECT_EQ(std::min(P_CMAX, pucch_power_prev + sum_delta_pucch), pucch_power)
+        << "PUCCH power expected to change by delta pucch only, between P_CMAX and P_CMIN";
+    pucch_power_prev = pucch_power;
+
+    if (i > 5) {
+      EXPECT_EQ(pucch_power, P_CMAX) << "Expected to reach MAX PUCCH TX power";
+    }
+  }
+
+  sum_delta_pucch = -15;
+  for (int i = 0; i < 10; i++) {
+    int pucch_power_state = mac.G_b_f_c;
+    int pucch_power = get_pucch_tx_power_ue(&mac,
+                                            scs,
+                                            &pucch_Config,
+                                            sum_delta_pucch,
+                                            format_type,
+                                            nb_of_prbs,
+                                            freq_hop_flag,
+                                            add_dmrs_flag,
+                                            N_symb_PUCCH,
+                                            subframe_number,
+                                            O_uci,
+                                            start_prb);
+    EXPECT_LE(mac.G_b_f_c, pucch_power_state) << "PUCCH power control state increased with negative delta pucch";
+    pucch_power_prev = pucch_power;
+  }
+}
+
+TEST(pc_min, check_all_bw_indexes)
+{
+  const int NB_RB_UL[] = {11, 24, 38, 51, 65, 78, 106, 133, 162, 217, 245, 273};
+  for (auto i = 0U; i < sizeof(NB_RB_UL) / sizeof(NB_RB_UL[0]); i++) {
+    (void)nr_get_Pcmin(1, 20, NB_RB_UL[i]);
+  }
+}
+
+TEST(pusch_power_control, pusch_power_control_msg3)
+{
+  NR_UE_MAC_INST_t mac = {0};
+  NR_UE_UL_BWP_t current_UL_BWP = {0};
+  current_UL_BWP.scs = 1;
+  current_UL_BWP.BWPSize = 106;
+  mac.current_UL_BWP = &current_UL_BWP;
+  NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
+  current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
+  mac.nr_band = 78;
+  NR_PUSCH_Config_t pusch_Config = {0};
+  current_UL_BWP.pusch_Config = &pusch_Config;
+  NR_PUSCH_PowerControl pusch_PowerControl = {0};
+  pusch_Config.pusch_PowerControl = &pusch_PowerControl;
+  pusch_PowerControl.tpc_Accumulation = (long*)1;
+
+  // msg3 cofiguration as in 5g_rfsimulator testcase
+  int num_rb = 8;
+  int start_prb = 0;
+  uint16_t nb_symb_sch = 3;
+  uint16_t nb_dmrs_prb = 12;
+  uint16_t nb_ptrs_prb = 0;
+  uint16_t Qm = 2;
+  uint16_t R = 1570;
+  uint16_t beta_offset_csi1 = 0;
+  uint32_t sum_bits_in_codeblocks = 56;
+  int delta_pusch = 0;
+  bool is_rar_tx_retx = true;
+
+  int P_CMAX = nr_get_Pcmax(23, mac.nr_band, FR1, Qm, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, false, num_rb, start_prb);
+
+  long preambleReceivedTargetPower = -96;
+  nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower;
+
+  int power = get_pusch_tx_power_ue(&mac,
+                                    num_rb,
+                                    start_prb,
+                                    nb_symb_sch,
+                                    nb_dmrs_prb,
+                                    nb_ptrs_prb,
+                                    Qm,
+                                    R,
+                                    beta_offset_csi1,
+                                    sum_bits_in_codeblocks,
+                                    delta_pusch,
+                                    is_rar_tx_retx,
+                                    false);
+  EXPECT_EQ(power, -84);
+  EXPECT_LT(power, P_CMAX);
+  nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower -= 2;
+
+  int reduced_power = get_pusch_tx_power_ue(&mac,
+                                            num_rb,
+                                            start_prb,
+                                            nb_symb_sch,
+                                            nb_dmrs_prb,
+                                            nb_ptrs_prb,
+                                            Qm,
+                                            R,
+                                            beta_offset_csi1,
+                                            sum_bits_in_codeblocks,
+                                            delta_pusch,
+                                            is_rar_tx_retx,
+                                            false);
+  EXPECT_EQ(std::min(P_CMAX, power - 2), reduced_power)
+      << "Incorrect handling of preambleReceivedTargetPower";
+  EXPECT_LT(reduced_power, P_CMAX) << "Power above P_CMAX";
+
+  delta_pusch = 4;
+  int increased_power = get_pusch_tx_power_ue(&mac,
+                                            num_rb,
+                                            start_prb,
+                                            nb_symb_sch,
+                                            nb_dmrs_prb,
+                                            nb_ptrs_prb,
+                                            Qm,
+                                            R,
+                                            beta_offset_csi1,
+                                            sum_bits_in_codeblocks,
+                                            delta_pusch,
+                                            is_rar_tx_retx,
+                                            false);
+  EXPECT_EQ(std::min(P_CMAX, reduced_power + delta_pusch), increased_power)
+      << "delta_pusch should increase tx power";
+  EXPECT_LT(increased_power, P_CMAX) << "Power above P_CMAX";
+}
+
+TEST(pusch_power_control, pusch_power_data)
+{
+  NR_UE_MAC_INST_t mac = {0};
+  NR_UE_UL_BWP_t current_UL_BWP = {0};
+  current_UL_BWP.scs = 1;
+  current_UL_BWP.BWPSize = 106;
+  mac.current_UL_BWP = &current_UL_BWP;
+  NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0};
+  current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon;
+  mac.nr_band = 78;
+
+  bool is_rar_tx_retx = false;
+  int num_rb = 5;
+  int start_prb = 0;
+  uint16_t nb_symb_sch = 3;
+  uint16_t nb_dmrs_prb = 6;
+  uint16_t nb_ptrs_prb = 0;
+  uint16_t Qm = 2;
+  uint16_t R = 6790;
+  uint16_t beta_offset_csi1 = 0;
+  uint32_t sum_bits_in_codeblocks = 192;
+  int delta_pusch = 4;
+  bool transform_precoding = false;
+  NR_PUSCH_Config_t pusch_Config = {0};
+  current_UL_BWP.pusch_Config = &pusch_Config;
+  NR_PUSCH_PowerControl pusch_PowerControl = {0};
+  pusch_Config.pusch_PowerControl = &pusch_PowerControl;
+  pusch_PowerControl.tpc_Accumulation = (long*)1;
+  long p0_NominalWithGrant = 0;
+  current_UL_BWP.p0_NominalWithGrant = &p0_NominalWithGrant;
+  pusch_PowerControl.deltaMCS = (long*)1;
+
+  int P_CMAX = nr_get_Pcmax(23, mac.nr_band, FR1, Qm, false, current_UL_BWP.scs, current_UL_BWP.BWPSize, transform_precoding, num_rb, start_prb);
+
+  int power = get_pusch_tx_power_ue(&mac,
+                                    num_rb,
+                                    start_prb,
+                                    nb_symb_sch,
+                                    nb_dmrs_prb,
+                                    nb_ptrs_prb,
+                                    Qm,
+                                    R,
+                                    beta_offset_csi1,
+                                    sum_bits_in_codeblocks,
+                                    delta_pusch,
+                                    is_rar_tx_retx,
+                                    transform_precoding);
+  EXPECT_LE(power, P_CMAX);
+  EXPECT_EQ(power, 18);
+
+  const int BETA_OFFSET_CSI1_DEFAULT = 13;
+  sum_bits_in_codeblocks = 0; // CSI-only
+  power = get_pusch_tx_power_ue(&mac,
+                                num_rb,
+                                start_prb,
+                                nb_symb_sch,
+                                nb_dmrs_prb,
+                                nb_ptrs_prb,
+                                Qm,
+                                R,
+                                BETA_OFFSET_CSI1_DEFAULT,
+                                sum_bits_in_codeblocks,
+                                delta_pusch,
+                                is_rar_tx_retx,
+                                transform_precoding);
+  EXPECT_EQ(power, P_CMAX) << "Expecting max tx power because of deltaMCS with CSI-only";
+}
+
 int main(int argc, char** argv)
 {
   logInit();
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index 3f752dae232bfd5f6933de7984475f838d08c801..9daabdddaf1b6fe9801116b979d95ee7bffe5f35 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -1271,6 +1271,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
                                            TYPE_RA_RNTI_,
                                            coresetid,
                                            false);
+  if (!tda_info.valid_tda)
+    return;
 
   uint16_t *vrb_map = cc[CC_id].vrb_map;
   for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) {
@@ -1804,6 +1806,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
                                              TYPE_TC_RNTI_,
                                              coreset->controlResourceSetId,
                                              false);
+    if (!msg4_tda.valid_tda)
+      return;
 
     NR_pdsch_dmrs_t dmrs_info = get_dl_dmrs_params(scc,
                                                    dl_bwp,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 29b5fbe7137c6a443e552b35404812b6e431cd74..95832f515809053694c006a3aad40026f6dee3dc 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -455,6 +455,8 @@ static bool allocate_dl_retransmission(module_id_t module_id,
                                            TYPE_C_RNTI_,
                                            coresetid,
                                            false);
+  if (!temp_tda.valid_tda)
+    return false;
 
   bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == temp_tda.startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= temp_tda.nrOfSymbols);
   LOG_D(NR_MAC, "[UE %x] %s old TDA, %s number of layers\n",
@@ -775,6 +777,7 @@ static void pf_dl(module_id_t module_id,
                                             TYPE_C_RNTI_,
                                             coresetid,
                                             false);
+    AssertFatal(sched_pdsch->tda_info.valid_tda, "Invalid TDA from get_dl_tda_info\n");
 
     NR_tda_info_t *tda_info = &sched_pdsch->tda_info;
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
index 6d6c6a20478854ab9b9a8b221e6b4ff2db72d0fb..db04417150ac3b78c9c878f3fc2e05e1d1381618 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
@@ -75,6 +75,8 @@ void nr_preprocessor_phytest(module_id_t module_id,
                                            TYPE_C_RNTI_,
                                            sched_ctrl->coreset->controlResourceSetId,
                                            false);
+  if(!tda_info.valid_tda)
+    return;
 
   sched_ctrl->sched_pdsch.tda_info = tda_info;
   sched_ctrl->sched_pdsch.time_domain_allocation = tda;
@@ -271,18 +273,15 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
                                            sched_ctrl->search_space->searchSpaceType->present,
                                            TYPE_C_RNTI_,
                                            tda);
+  if (!tda_info.valid_tda)
+    return false;
   sched_ctrl->sched_pusch.tda_info = tda_info;
 
   const int buffer_index = ul_buffer_index(sched_frame, sched_slot, mu, nr_mac->vrb_map_UL_size);
   uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
   for (int i = rbStart; i < rbStart + rbSize; ++i) {
     if ((vrb_map_UL[i+BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) != 0) {
-      LOG_E(MAC,
-            "%s(): %4d.%2d RB %d is already reserved, cannot schedule UE\n",
-            __func__,
-            frame,
-            slot,
-            i);
+      LOG_E(MAC, "%4d.%2d RB %d is already reserved, cannot schedule UE\n", frame, slot, i);
       return false;
     }
   }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 3134ec3cda78494416f621e55f5d60c7345f572c..1e133a028b65f6a50dd390972f0d72deb891fbc1 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -1116,10 +1116,12 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
   }
   /* phy-test has hardcoded allocation, so no use to handle CSI reports */
   if ((uci_234->pduBitmap >> 2) & 0x01 && !get_softmodem_params()->phy_test) {
-    //API to parse the csi report and store it into sched_ctrl
-    extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon);
-    //TCI handling function
-    tci_handling(UE,frame, slot);
+    if (uci_234->csi_part1.csi_part1_crc != 1) {
+      // API to parse the csi report and store it into sched_ctrl
+      extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon);
+      // TCI handling function
+      tci_handling(UE, frame, slot);
+    }
     free(uci_234->csi_part1.csi_part1_payload);
   }
   if ((uci_234->pduBitmap >> 3) & 0x01) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 820eba2b5bb66717a2ff3d1444c9d3f1c3a7024b..612cbc0eab67185ef0fe6a36a381229444e57665 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -1601,6 +1601,8 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac,
                                            sched_ctrl->search_space->searchSpaceType->present,
                                            TYPE_C_RNTI_,
                                            tda);
+  if (!tda_info.valid_tda)
+    return false;
   bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == tda_info.startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= tda_info.nrOfSymbols);
   if (reuse_old_tda && nrOfLayers == retInfo->nrOfLayers) {
     /* Check the resource is enough for retransmission */
@@ -1844,6 +1846,7 @@ static void pf_ul(module_id_t module_id,
                                               sched_ctrl->search_space->searchSpaceType->present,
                                               TYPE_C_RNTI_,
                                               sched_pusch->time_domain_allocation);
+      AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n");
       sched_pusch->dmrs_info = get_ul_dmrs_params(scc,
                                                   current_BWP,
                                                   &sched_pusch->tda_info,
@@ -1967,6 +1970,7 @@ static void pf_ul(module_id_t module_id,
                                             sched_ctrl->search_space->searchSpaceType->present,
                                             TYPE_C_RNTI_,
                                             sched_pusch->time_domain_allocation);
+    AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n");
     sched_pusch->dmrs_info = get_ul_dmrs_params(scc,
                                                 current_BWP,
                                                 &sched_pusch->tda_info,
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
index 0e07e14fc98cf09259d94fb6b2da092fc8707c31..a4207716f55fc19d275ed7cbe2f3f90f3179d90e 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
@@ -110,11 +110,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_am(
   ret->max_retx_threshold = max_retx_threshold;
   ret->sn_field_length    = sn_field_length;
 
-  if (!(sn_field_length == 12 || sn_field_length == 18)) {
-    LOG_E(RLC, "%s:%d:%s: wrong SN field_lenght (%d), must be 12 or 18\n",
-          __FILE__, __LINE__, __FUNCTION__, sn_field_length);
-    exit(1);
-  }
+  AssertFatal(sn_field_length == 12 || sn_field_length == 18, "Wrong SN field_length (%d), must be 12 or 18\n", sn_field_length);
+
   ret->sn_modulus = 1 << ret->sn_field_length;
   ret->window_size = ret->sn_modulus / 2;
 
@@ -172,11 +169,8 @@ nr_rlc_entity_t *new_nr_rlc_entity_um(
   ret->t_reassembly    = t_reassembly;
   ret->sn_field_length = sn_field_length;
 
-  if (!(sn_field_length == 6 || sn_field_length == 12)) {
-    LOG_E(RLC, "%s:%d:%s: wrong SN field_lenght (%d), must be 6 or 12\n",
-          __FILE__, __LINE__, __FUNCTION__, sn_field_length);
-    exit(1);
-  }
+  AssertFatal(sn_field_length == 6 || sn_field_length == 12, "Wrong SN field_length (%d), must be 6 or 12\n", sn_field_length);
+
   ret->sn_modulus = 1 << ret->sn_field_length;
   ret->window_size = ret->sn_modulus / 2;
 
diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c
index 9bbd4f38b7f42385774683916b148a9ca6d1170c..de660f176538db32eaac710b52a47ce9cef73120 100644
--- a/openair2/RRC/NR/nr_rrc_config.c
+++ b/openair2/RRC/NR/nr_rrc_config.c
@@ -655,6 +655,7 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCo
                                                     const int uid,
                                                     const int res_id,
                                                     const long maxMIMO_Layers,
+                                                    const int minRXTXTIME,
                                                     int do_srs)
 {
   NR_SetupRelease_SRS_Config_t *setup_release_srs_Config = calloc(1,sizeof(*setup_release_srs_Config));
@@ -679,10 +680,10 @@ static NR_SetupRelease_SRS_Config_t *get_config_srs(const NR_ServingCellConfigCo
   } else {
     srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_aperiodic;
     srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
-    srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
-    srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
+    srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger = 1;
+    srs_resset0->resourceType.choice.aperiodic->csi_RS = NULL;
     srs_resset0->resourceType.choice.aperiodic->slotOffset = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
-    *srs_resset0->resourceType.choice.aperiodic->slotOffset = 2;
+    *srs_resset0->resourceType.choice.aperiodic->slotOffset = minRXTXTIME;
     srs_resset0->resourceType.choice.aperiodic->ext1 = NULL;
   }
   srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook;
@@ -1487,7 +1488,14 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp,
                                 && servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers ?
                             *servingcellconfigdedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers : 1;
 
-  ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc, NULL, curr_bwp, uid, bwp_loop + 1, maxMIMO_Layers, configuration->do_SRS);
+  ubwp->bwp_Dedicated->srs_Config = get_config_srs(scc,
+                                                   NULL,
+                                                   curr_bwp,
+                                                   uid,
+                                                   bwp_loop + 1,
+                                                   maxMIMO_Layers,
+                                                   configuration->minRXTXTIME,
+                                                   configuration->do_SRS);
 
   ubwp->bwp_Dedicated->configuredGrantConfig = NULL;
   ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL;
@@ -2633,7 +2641,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
                             : 1;
 
   // We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1
-  initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, uid, 0, maxMIMO_Layers, 0);
+  initialUplinkBWP->srs_Config = get_config_srs(scc, NULL, curr_bwp, uid, 0, maxMIMO_Layers, configuration->minRXTXTIME, 0);
 
   scheduling_request_config(scc, pucch_Config, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing);
 
@@ -2937,7 +2945,14 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
   // UL and SRS configuration
   if (configuration->do_SRS && uplinkConfig && uplinkConfig->initialUplinkBWP) {
     ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, uplinkConfig->initialUplinkBWP->srs_Config);
-    uplinkConfig->initialUplinkBWP->srs_Config = get_config_srs(scc, uecap, curr_bwp, uid, 0, maxMIMO_Layers, configuration->do_SRS);
+    uplinkConfig->initialUplinkBWP->srs_Config = get_config_srs(scc,
+                                                                uecap,
+                                                                curr_bwp,
+                                                                uid,
+                                                                0,
+                                                                maxMIMO_Layers,
+                                                                configuration->minRXTXTIME,
+                                                                configuration->do_SRS);
   }
 
   // Set DL MCS table
@@ -2974,7 +2989,14 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
       }
 
       ASN_STRUCT_FREE(asn_DEF_NR_SetupRelease_SRS_Config, ul_bwp->bwp_Dedicated->srs_Config);
-      ul_bwp->bwp_Dedicated->srs_Config = get_config_srs(scc, uecap, bwp_size, uid, i + 1, maxMIMO_Layers, configuration->do_SRS);
+      ul_bwp->bwp_Dedicated->srs_Config = get_config_srs(scc,
+                                                         uecap,
+                                                         bwp_size,
+                                                         uid,
+                                                         i + 1,
+                                                         maxMIMO_Layers,
+                                                         configuration->minRXTXTIME,
+                                                         configuration->do_SRS);
     }
   }
   update_cqitables(bwp_Dedicated->pdsch_Config, csi_MeasConfig);
@@ -3172,7 +3194,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
 
   int curr_bwp = NRRIV2BW(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,
                           MAX_BWP_SIZE);
-  initialUplinkBWP->srs_Config = get_config_srs(servingcellconfigcommon, NULL, curr_bwp, uid, 0, maxMIMO_Layers, configuration->do_SRS);
+  initialUplinkBWP->srs_Config = get_config_srs(servingcellconfigcommon,
+                                                NULL,
+                                                curr_bwp,
+                                                uid,
+                                                0,
+                                                maxMIMO_Layers,
+                                                configuration->minRXTXTIME,
+                                                configuration->do_SRS);
 
   // Downlink BWPs
   int n_dl_bwp = 1;
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index a6d5c86449e847613c866d7a3d0bf67f31845201..d024eff20f0b6e29bacdef2e78c5850bb7c25fcf 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -200,59 +200,55 @@ rrc_gNB_send_NGAP_NAS_FIRST_REQ(
   //              ue_context_pP);
 
   /* Fill UE identities with available information */
-  req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE;
   if (UE->Initialue_identity_5g_s_TMSI.presence) {
     /* Fill s-TMSI */
     req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_FiveG_s_tmsi;
     req->ue_identity.s_tmsi.amf_set_id = UE->Initialue_identity_5g_s_TMSI.amf_set_id;
     req->ue_identity.s_tmsi.amf_pointer = UE->Initialue_identity_5g_s_TMSI.amf_pointer;
     req->ue_identity.s_tmsi.m_tmsi = UE->Initialue_identity_5g_s_TMSI.fiveg_tmsi;
-  }
+  } else if (rrcSetupComplete->registeredAMF != NULL) {
+    NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF;
+    req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_guami;
+
+    /* The IE AMF-Identifier (AMFI) comprises of an AMF Region ID (8b), an AMF Set ID (10b) and an AMF Pointer (6b) as specified in TS 23.003 [21], clause 2.10.1. */
+    uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier);
+    req->ue_identity.guami.amf_region_id = (amf_Id >> 16) & 0xff;
+    req->ue_identity.guami.amf_set_id = (amf_Id >> 6) & 0x3ff;
+    req->ue_identity.guami.amf_pointer = amf_Id & 0x3f;
+
+    UE->ue_guami.amf_region_id = req->ue_identity.guami.amf_region_id;
+    UE->ue_guami.amf_set_id = req->ue_identity.guami.amf_set_id;
+    UE->ue_guami.amf_pointer = req->ue_identity.guami.amf_pointer;
+
+    if (r_amf->plmn_Identity != NULL) {
+      AssertFatal(false, "At the moment, OAI RAN does not support multiple PLMN IDs. Therefore, this part has not been tested\n");
+      /* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
+      int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1;
+      req->selected_plmn_identity = selected_plmn_identity;
+
+      if ((r_amf->plmn_Identity->mcc != NULL) && (r_amf->plmn_Identity->mcc->list.count > 0)) {
+        /* Use first indicated PLMN MCC if it is defined */
+        req->ue_identity.guami.mcc = *r_amf->plmn_Identity->mcc->list.array[selected_plmn_identity];
+        LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, req->ue_identity.guami.mcc, UE->rnti);
+      }
 
-  /* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
-  int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1;
-  req->selected_plmn_identity = selected_plmn_identity;
-
-  if (rrcSetupComplete->registeredAMF != NULL) {
-      NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF;
-      req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_guami;
-
-      if (r_amf->plmn_Identity != NULL) {
-          if ((r_amf->plmn_Identity->mcc != NULL) && (r_amf->plmn_Identity->mcc->list.count > 0)) {
-              /* Use first indicated PLMN MCC if it is defined */
-              req->ue_identity.guami.mcc = *r_amf->plmn_Identity->mcc->list.array[selected_plmn_identity];
-              LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, req->ue_identity.guami.mcc, UE->rnti);
-          }
-
-          if (r_amf->plmn_Identity->mnc.list.count > 0) {
-              /* Use first indicated PLMN MNC if it is defined */
-              req->ue_identity.guami.mnc = *r_amf->plmn_Identity->mnc.list.array[selected_plmn_identity];
-              LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", ctxt_pP->module_id, req->ue_identity.guami.mnc, UE->rnti);
-          }
-      } else {
-          /* TODO */
+      if (r_amf->plmn_Identity->mnc.list.count > 0) {
+        /* Use first indicated PLMN MNC if it is defined */
+        req->ue_identity.guami.mnc = *r_amf->plmn_Identity->mnc.list.array[selected_plmn_identity];
+        LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", ctxt_pP->module_id, req->ue_identity.guami.mnc, UE->rnti);
       }
+    } else {
+        /* TODO */
+    }
 
-      /* amf_Identifier */
-      uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier);
-      req->ue_identity.guami.amf_region_id = amf_Id >> 16;
-      req->ue_identity.guami.amf_set_id = UE->Initialue_identity_5g_s_TMSI.amf_set_id;
-      req->ue_identity.guami.amf_pointer = UE->Initialue_identity_5g_s_TMSI.amf_pointer;
-
-      // fixme: illogical place to set UE values, should be in the function that call this one
-      UE->ue_guami.mcc = req->ue_identity.guami.mcc;
-      UE->ue_guami.mnc = req->ue_identity.guami.mnc;
-      UE->ue_guami.mnc_len = req->ue_identity.guami.mnc_len;
-      UE->ue_guami.amf_region_id = req->ue_identity.guami.amf_region_id;
-      UE->ue_guami.amf_set_id = req->ue_identity.guami.amf_set_id;
-      UE->ue_guami.amf_pointer = req->ue_identity.guami.amf_pointer;
-
-      LOG_I(NGAP,
-            "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n",
-            ctxt_pP->module_id,
-            req->ue_identity.guami.amf_set_id,
-            req->ue_identity.guami.amf_region_id,
-            UE->rnti);
+    LOG_I(NGAP,
+          "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n",
+          ctxt_pP->module_id,
+          req->ue_identity.guami.amf_set_id,
+          req->ue_identity.guami.amf_region_id,
+          UE->rnti);
+  } else {
+    req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE;
   }
 
   itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, message_p);
@@ -482,6 +478,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
   PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rrc_ue_id, 0, 0);
   UE->amf_ue_ngap_id = req->amf_ue_ngap_id;
 
+  /* store guami in gNB_RRC_UE_t context;
+   * we copy individual members because the guami types are different (nr_rrc_guami_t and ngap_guami_t) */
+  UE->ue_guami.mcc = req->guami.mcc;
+  UE->ue_guami.mnc = req->guami.mnc;
+  UE->ue_guami.mnc_len = req->guami.mnc_len;
+  UE->ue_guami.amf_region_id = req->guami.amf_region_id;
+  UE->ue_guami.amf_set_id = req->guami.amf_set_id;
+  UE->ue_guami.amf_pointer = req->guami.amf_pointer;
+
   /* NAS PDU */
   // this is malloced pointers, we pass it for later free()
   UE->nas_pdu = req->nas_pdu;
diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c
index 5a639e7305c5c59890e0f01f5dbd5f703bbe7444..de113b310039adda5a420afdfefb471cfd8d1769 100644
--- a/openair3/NGAP/ngap_gNB_handlers.c
+++ b/openair3/NGAP/ngap_gNB_handlers.c
@@ -740,37 +740,38 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
   NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,
                              NGAP_ProtocolIE_ID_id_GUAMI, true);
 
-    TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, msg->guami.mcc,
-                    msg->guami.mnc, msg->guami.mnc_len);
+  TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, msg->guami.mcc,
+                  msg->guami.mnc, msg->guami.mnc_len);
     
-    OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, msg->guami.amf_region_id);
-    OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, msg->guami.amf_set_id);
-    OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, msg->guami.amf_pointer);
-
-    NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false);
-    if (ie != NULL) {
-      msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count;
-
-      for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) {
-        NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
-        msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
-
-        OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->pdusession_param[i].nssai.sst);
-        if (item_p->s_NSSAI.sD != NULL) {
-          uint8_t *sd_p = (uint8_t *)&msg->pdusession_param[i].nssai.sd;
-          sd_p[0] = item_p->s_NSSAI.sD->buf[0];
-          sd_p[1] = item_p->s_NSSAI.sD->buf[1];
-          sd_p[2] = item_p->s_NSSAI.sD->buf[2];
-        } else {
-          msg->pdusession_param[i].nssai.sd = 0xffffff;
-        }
+  msg->guami.amf_region_id = BIT_STRING_to_uint8(&ie->value.choice.GUAMI.aMFRegionID);
+  msg->guami.amf_set_id = BIT_STRING_to_uint16(&ie->value.choice.GUAMI.aMFSetID);
+  msg->guami.amf_pointer = BIT_STRING_to_uint8(&ie->value.choice.GUAMI.aMFPointer);
 
-        if (item_p->nAS_PDU) {
-          allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
-        }
-        allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
+
+  NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false);
+  if (ie != NULL) {
+    msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count;
+
+    for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) {
+      NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i];
+      msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID;
+
+      OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->pdusession_param[i].nssai.sst);
+      if (item_p->s_NSSAI.sD != NULL) {
+        uint8_t *sd_p = (uint8_t *)&msg->pdusession_param[i].nssai.sd;
+        sd_p[0] = item_p->s_NSSAI.sD->buf[0];
+        sd_p[1] = item_p->s_NSSAI.sD->buf[1];
+        sd_p[2] = item_p->s_NSSAI.sD->buf[2];
+      } else {
+        msg->pdusession_param[i].nssai.sd = 0xffffff;
+      }
+
+      if (item_p->nAS_PDU) {
+        allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
       }
+      allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
     }
+  }
 
   /* id-AllowedNSSAI */
   NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container,