From 23a2f638308c28b287cc0ca475c37f4b50cf988c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=BAben=20Soares=20da=20Silva?= <rsilva@allbesmart.pt>
Date: Tue, 23 Apr 2024 23:55:44 +0100
Subject: [PATCH] Move functions for packing/unpacking CONFIG.request

Add unitary test for CONFIG.request ( test pack/unpack, free, copy and compare )
---
 nfapi/open-nFAPI/fapi/inc/nr_fapi.h           |   3 +
 nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h        |   2 +
 nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c        | 716 ++++++++++++++++++
 .../nfapi/public_inc/nfapi_interface.h        |   5 -
 nfapi/open-nFAPI/nfapi/src/nfapi_p5.c         | 716 ------------------
 nfapi/tests/p5/CMakeLists.txt                 |   2 +-
 nfapi/tests/p5/nr_fapi_config_request_test.c  | 296 ++++++++
 7 files changed, 1018 insertions(+), 722 deletions(-)
 create mode 100644 nfapi/tests/p5/nr_fapi_config_request_test.c

diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h
index 0193edabe3d..322c09b59c5 100644
--- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h
@@ -38,6 +38,9 @@
 #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 {
diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
index fb84cb0689c..f3d9fec52a3 100644
--- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
+++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5.h
@@ -38,4 +38,6 @@ uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *en
 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);
 #endif // OPENAIRINTERFACE_NR_FAPI_P5_H
diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
index fec25a57a31..72502be3bac 100644
--- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
+++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
@@ -850,3 +850,719 @@ uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *
                                 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;
+}
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
index 7bf43056c04..3e5be8d2fd7 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
@@ -20,7 +20,6 @@
 
 #include "stddef.h"
 #include <stdint.h>
-#include <stdbool.h>
 
 // Constants - update based on implementation
 #define NFAPI_MAX_PHY_RF_INSTANCES 2
@@ -4122,10 +4121,6 @@ int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t
  */
 int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen);
 
-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);
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
index bdc8ea109e4..e92f18a2cc8 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c
@@ -1146,387 +1146,6 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_
                   &pack_uint8_tlv_value));
 }
 
-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 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;
@@ -2486,341 +2105,6 @@ static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo
                              &pNfapiMsg->vendor_extension));
 }
 
-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;
-}
-
 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) &&
diff --git a/nfapi/tests/p5/CMakeLists.txt b/nfapi/tests/p5/CMakeLists.txt
index bac6676dd72..d9e209ea446 100644
--- a/nfapi/tests/p5/CMakeLists.txt
+++ b/nfapi/tests/p5/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(Test_Labels fapi p5)
-set(_fapi_p5_messages "param_request;param_response")
+set(_fapi_p5_messages "param_request;param_response;config_request")
 
 foreach (fapi_p5_message IN LISTS _fapi_p5_messages)
     add_executable(nr_fapi_${fapi_p5_message}_test nr_fapi_${fapi_p5_message}_test.c)
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 00000000000..3e098722b23
--- /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;
+}
-- 
GitLab