From 52aff43e2d36811d5578a3c3dc00d42d3ac9c06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20da=20Silva?= Date: Wed, 24 Apr 2024 08:46:57 +0100 Subject: [PATCH] Fix packing/unpacking procedures for CONFIG.response Add utility functions related to CONFIG.response --- nfapi/open-nFAPI/common/public_inc/nfapi.h | 3 + nfapi/open-nFAPI/common/src/nfapi.c | 128 ++++++++++++++++++ nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h | 3 + nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 123 +++++++++++++++++ .../nfapi/public_inc/nfapi_nr_interface_scf.h | 24 +++- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 69 ++++++++-- 6 files changed, 335 insertions(+), 15 deletions(-) diff --git a/nfapi/open-nFAPI/common/public_inc/nfapi.h b/nfapi/open-nFAPI/common/public_inc/nfapi.h index 7b7b89fe70..e3a5d83b9c 100644 --- a/nfapi/open-nFAPI/common/public_inc/nfapi.h +++ b/nfapi/open-nFAPI/common/public_inc/nfapi.h @@ -86,6 +86,7 @@ uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end); typedef uint8_t (*pack_tlv_fn)(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end); uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn); uint8_t pack_nr_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn); +uint8_t pack_nr_generic_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end); uint32_t pack_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config); int unpack_vendor_extension_tlv(nfapi_tl_t *tl, @@ -94,6 +95,8 @@ int unpack_vendor_extension_tlv(nfapi_tl_t *tl, nfapi_p4_p5_codec_config_t *config, nfapi_tl_t **ve_tlv); +uint8_t unpack_nr_generic_tlv_list(void *tlv_list, uint8_t tlv_count, uint8_t **ppReadPackedMsg, uint8_t *end); + uint8_t get_tlv_padding(uint16_t tlv_length); typedef uint8_t (*unpack_tlv_fn)(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end); diff --git a/nfapi/open-nFAPI/common/src/nfapi.c b/nfapi/open-nFAPI/common/src/nfapi.c index e0bc42a36c..e9aa3c9682 100644 --- a/nfapi/open-nFAPI/common/src/nfapi.c +++ b/nfapi/open-nFAPI/common/src/nfapi.c @@ -1209,6 +1209,134 @@ uint8_t pack_nr_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t return 1; } +uint8_t pack_nr_generic_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_generic_tlv_scf_t *toPack = (nfapi_nr_generic_tlv_scf_t *)tlv; + // If the tag is defined + if (toPack->tl.tag == tag && toPack->tl.length != 0) { + // write the tlv header, length comes with value + if (pack_tl(&(toPack->tl), ppWritePackedMsg, end) == 0) + return 0; + + // pack the tlv value + switch (toPack->tl.length) { + case UINT_8: + if (push8(toPack->value.u8, ppWritePackedMsg, end) == 0) { + return 0; + } + break; + case UINT_16: + if (push16(toPack->value.u16, ppWritePackedMsg, end) == 0) { + return 0; + } + break; + case UINT_32: + if (push32(toPack->value.u32, ppWritePackedMsg, end) == 0) { + return 0; + } + break; + case ARRAY_UINT_16: + if ((push16(toPack->value.array_u16[0], ppWritePackedMsg, end) && push16(toPack->value.array_u16[1], ppWritePackedMsg, end) + && push16(toPack->value.array_u16[2], ppWritePackedMsg, end) + && push16(toPack->value.array_u16[3], ppWritePackedMsg, end) + && push16(toPack->value.array_u16[4], ppWritePackedMsg, end)) + == 0) { + return 0; + } + break; + default: + break; + } + + // calculate the length of the value and rewrite the tl header + // in case of nfapi_nr_config_response_tlv_list_scf_t this is to come pre-calculated, possibly unnecessary + /*toPack->tl.length = (*ppWritePackedMsg) - pStartOfValue; + // rewrite the header with the correct length + pack_tl(&(toPack->tl), &pStartOfTlv, end);*/ + // Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1) + int padding = get_tlv_padding(toPack->tl.length); + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x with padding of %d bytes\n", toPack->tl.tag, padding); + if (padding != 0) { + memset(*ppWritePackedMsg, 0, padding); + (*ppWritePackedMsg) += padding; + } + } else { + if (toPack->tl.tag != 0) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", toPack->tl.tag, tag); + } else { + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag); + } + } + + return 1; +} + +uint8_t unpack_nr_generic_tlv() +{ + return 1; +} + +uint8_t unpack_nr_generic_tlv_list(void *tlv_list, uint8_t tlv_count, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_generic_tlv_scf_t *toUnpack = (nfapi_nr_generic_tlv_scf_t *)tlv_list; + uint8_t numBadTags = 0; + for (int i = 0; i < tlv_count; ++i) { + nfapi_nr_generic_tlv_scf_t *element = &(toUnpack[i]); + + // unpack each generic tlv + // unpack the tl and process the values accordingly + if (unpack_tl(ppReadPackedMsg, &(element->tl), end) == 0) + return 0; + + uint8_t *pStartOfValue = *ppReadPackedMsg; + // check for valid tag + if (element->tl.tag < NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG || element->tl.tag > NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG) { + numBadTags++; + if (numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + on_error(); + return 0; + } + } + // if tag is valid, check length to determine which type to unpack + switch (element->tl.length) { + case UINT_8: + pull8(ppReadPackedMsg, &(element->value.u8), end); + break; + case UINT_16: + pull16(ppReadPackedMsg, &(element->value.u16), end); + break; + case UINT_32: + pull32(ppReadPackedMsg, &(element->value.u32), end); + break; + case ARRAY_UINT_16: + for (int j = 0; j < 5; ++j) { + pull16(ppReadPackedMsg, &(element->value.array_u16[j]), end); + } + break; + default: + printf("unknown length %d\n", element->tl.length); + break; + } + + // check if the length was right; + if (element->tl.length != (*ppReadPackedMsg - pStartOfValue)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "Warning tlv tag 0x%x length %d not equal to unpack %ld\n", + element->tl.tag, + element->tl.length, + (*ppReadPackedMsg - pStartOfValue)); + on_error(); + } + // Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1) + int padding = get_tlv_padding(element->tl.length); + if (padding != 0) { + (*ppReadPackedMsg) += padding; + } + } + return 1; +} + const char *nfapi_error_code_to_str(nfapi_error_code_e value) { switch (value) { diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h index 15e17e7c82..753b4fa63d 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h @@ -66,13 +66,16 @@ void copy_vendor_extension_value(nfapi_vendor_extension_tlv_t *dst, const nfapi_ bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req); bool eq_param_response(const nfapi_nr_param_response_scf_t *unpacked_req, const nfapi_nr_param_response_scf_t *req); bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const nfapi_nr_config_request_scf_t *req); +bool eq_config_response(const nfapi_nr_config_response_scf_t *unpacked_req, const nfapi_nr_config_response_scf_t *req); void free_param_request(nfapi_nr_param_request_scf_t *msg); void free_param_response(nfapi_nr_param_response_scf_t *msg); void free_config_request(nfapi_nr_config_request_scf_t *msg); +void free_config_response(nfapi_nr_config_response_scf_t *msg); void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst); void copy_param_response(const nfapi_nr_param_response_scf_t *src, nfapi_nr_param_response_scf_t *dst); void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_config_request_scf_t *dst); +void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst); #endif // OPENAIRINTERFACE_NR_FAPI_P5_UTILS_H diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 8e4db4c695..0ae06b0201 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -309,6 +309,65 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const return true; } +static bool eq_config_response_tlv_lists(nfapi_nr_generic_tlv_scf_t *unpacked_list, + nfapi_nr_generic_tlv_scf_t *req_list, + uint8_t size) +{ + for (int i = 0; i < size; ++i) { + nfapi_nr_generic_tlv_scf_t *unpacked_element = &(unpacked_list[i]); + nfapi_nr_generic_tlv_scf_t *req_element = &(req_list[i]); + + EQ(unpacked_element->tl.tag, req_element->tl.tag); + EQ(unpacked_element->tl.length, req_element->tl.length); + // check according to value type + switch (unpacked_element->tl.length) { + case UINT_8: + EQ(unpacked_element->value.u8, req_element->value.u8); + break; + case UINT_16: + EQ(unpacked_element->value.u16, req_element->value.u16); + break; + case UINT_32: + EQ(unpacked_element->value.u32, req_element->value.u32); + break; + case ARRAY_UINT_16: + for (int j = 0; j < 5; ++j) { + EQ(unpacked_element->value.array_u16[j], req_element->value.array_u16[j]); + } + break; + default: + printf("unknown length %d\n", unpacked_element->tl.length); + DevAssert(1 == 0); + break; + } + } + return true; +} + +bool eq_config_response(const nfapi_nr_config_response_scf_t *unpacked_req, const nfapi_nr_config_response_scf_t *req) +{ + EQ(unpacked_req->header.message_id, req->header.message_id); + EQ(unpacked_req->header.message_length, req->header.message_length); + + EQ(unpacked_req->error_code, req->error_code); + EQ(unpacked_req->num_invalid_tlvs, req->num_invalid_tlvs); + EQ(unpacked_req->num_invalid_tlvs_configured_in_idle, req->num_invalid_tlvs_configured_in_idle); + EQ(unpacked_req->num_invalid_tlvs_configured_in_running, req->num_invalid_tlvs_configured_in_running); + EQ(unpacked_req->num_missing_tlvs, req->num_missing_tlvs); + // compare the list elements + EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_list, req->invalid_tlvs_list, req->num_invalid_tlvs), true); + EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_idle_list, + req->invalid_tlvs_configured_in_idle_list, + req->num_invalid_tlvs_configured_in_idle), + true); + EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_running_list, + req->invalid_tlvs_configured_in_running_list, + req->num_invalid_tlvs_configured_in_running), + true); + EQ(eq_config_response_tlv_lists(unpacked_req->missing_tlvs_list, req->missing_tlvs_list, req->num_missing_tlvs), true); + return true; +} + void free_param_request(nfapi_nr_param_request_scf_t *msg) { if (msg->vendor_extension) { @@ -355,6 +414,29 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) } } +void free_config_response(nfapi_nr_config_response_scf_t *msg) +{ + if (msg->vendor_extension) { + free(msg->vendor_extension); + } + + if (msg->invalid_tlvs_list) { + free(msg->invalid_tlvs_list); + } + + if (msg->invalid_tlvs_configured_in_idle_list) { + free(msg->invalid_tlvs_configured_in_idle_list); + } + + if (msg->invalid_tlvs_configured_in_running_list) { + free(msg->invalid_tlvs_configured_in_running_list); + } + + if (msg->missing_tlvs_list) { + free(msg->missing_tlvs_list); + } +} + void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst) { dst->header.message_id = src->header.message_id; @@ -705,3 +787,44 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset); } + +void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst) +{ + dst->header.message_id = src->header.message_id; + dst->header.message_length = src->header.message_length; + if (src->vendor_extension) { + dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); + dst->vendor_extension->tag = src->vendor_extension->tag; + dst->vendor_extension->length = src->vendor_extension->length; + copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); + } + + dst->error_code = src->error_code; + dst->num_invalid_tlvs = src->num_invalid_tlvs; + dst->num_invalid_tlvs_configured_in_idle = src->num_invalid_tlvs_configured_in_idle; + dst->num_invalid_tlvs_configured_in_running = src->num_invalid_tlvs_configured_in_running; + dst->num_missing_tlvs = src->num_missing_tlvs; + + dst->invalid_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); + dst->invalid_tlvs_configured_in_idle_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t)); + dst->invalid_tlvs_configured_in_running_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t)); + dst->missing_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); + + for (int i = 0; i < dst->num_invalid_tlvs; ++i) { + COPY_TLV(dst->invalid_tlvs_list[i], src->invalid_tlvs_list[i]); + } + + for (int i = 0; i < dst->num_invalid_tlvs_configured_in_idle; ++i) { + COPY_TLV(dst->invalid_tlvs_configured_in_idle_list[i], src->invalid_tlvs_configured_in_idle_list[i]); + } + + for (int i = 0; i < dst->num_invalid_tlvs_configured_in_running; ++i) { + COPY_TLV(dst->invalid_tlvs_configured_in_running_list[i], src->invalid_tlvs_configured_in_running_list[i]); + } + + for (int i = 0; i < dst->num_missing_tlvs; ++i) { + COPY_TLV(dst->missing_tlvs_list[i], src->missing_tlvs_list[i]); + } +} diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 1eb56fa045..3b03cedfab 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -576,6 +576,23 @@ typedef struct { nfapi_nr_pm_list_t pmi_list; } nfapi_nr_config_request_scf_t; +typedef enum { + UINT_8 = sizeof(uint8_t), + UINT_16 = sizeof(uint16_t), + UINT_32 = sizeof(uint32_t), + ARRAY_UINT_16 = 5 * sizeof(uint16_t), + UNKNOWN = 0xffff +} nfapi_nr_config_response_tlv_value_type_t; + +typedef struct { + nfapi_tl_t tl; + union { + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint16_t array_u16[5]; // 4 TLVs defined as array ( dlK0, dlGridSize, ulK0, ulGridSize ) + } value; +} nfapi_nr_generic_tlv_scf_t; /* CONFIG.RESPONSE */ typedef struct { @@ -585,8 +602,11 @@ typedef struct { uint8_t num_invalid_tlvs_configured_in_idle; uint8_t num_invalid_tlvs_configured_in_running; uint8_t num_missing_tlvs; - // TODO: add list of invalid/unsupported TLVs (see Table 3.18) - nfapi_vendor_extension_tlv_t vendor_extension; + nfapi_nr_generic_tlv_scf_t* invalid_tlvs_list; + nfapi_nr_generic_tlv_scf_t* invalid_tlvs_configured_in_idle_list; + nfapi_nr_generic_tlv_scf_t* invalid_tlvs_configured_in_running_list; + nfapi_nr_generic_tlv_scf_t* missing_tlvs_list; + nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_config_response_scf_t; //------------------------------// diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index e92f18a2cc..c31820ec22 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1149,11 +1149,32 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; - return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && push8(pNfapiMsg->num_invalid_tlvs, ppWritePackedMsg, end) - && push8(pNfapiMsg->num_invalid_tlvs_configured_in_idle, ppWritePackedMsg, end) - && push8(pNfapiMsg->num_invalid_tlvs_configured_in_running, ppWritePackedMsg, end) - && push8(pNfapiMsg->num_missing_tlvs, ppWritePackedMsg, end) - && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + uint8_t retval = push8(pNfapiMsg->error_code, ppWritePackedMsg, end); + retval &= push8(pNfapiMsg->num_invalid_tlvs, ppWritePackedMsg, end); + retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_idle, ppWritePackedMsg, end); + retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_running, ppWritePackedMsg, end); + retval &= push8(pNfapiMsg->num_missing_tlvs, ppWritePackedMsg, end); + + // pack lists + for (int i = 0; i < pNfapiMsg->num_invalid_tlvs; ++i) { + nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_list[i]); + pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end); + } + for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_idle; ++i) { + nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_idle_list[i]); + pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end); + } + for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_running; ++i) { + nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_running_list[i]); + pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end); + } + for (int i = 0; i < pNfapiMsg->num_missing_tlvs; ++i) { + nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->missing_tlvs_list[i]); + pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end); + } + + retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return retval; } static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { @@ -2113,14 +2134,36 @@ static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, v uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { - nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; - uint8_t invalid_unsupported_TLVs, invalidTLVsIdle, InvalidTLVsRunning, missingTLVS; - uint8_t retVal = (pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && pull8(ppReadPackedMsg, &invalid_unsupported_TLVs, end) - && pull8(ppReadPackedMsg, &invalidTLVsIdle, end) && pull8(ppReadPackedMsg, &InvalidTLVsRunning, end) - && pull8(ppReadPackedMsg, &missingTLVS, end) - && unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - // TODO: Process and use the invalid TLVs fields - return retVal; + nfapi_nr_config_response_scf_t *nfapi_resp = (nfapi_nr_config_response_scf_t *)msg; + uint8_t retval = pull8(ppReadPackedMsg, &nfapi_resp->error_code, end) + && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs, end) + && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_idle, end) + && pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_running, end) + && pull8(ppReadPackedMsg, &nfapi_resp->num_missing_tlvs, end); + // First unpack the invalid_tlvs_list + // allocate the memory + nfapi_resp->invalid_tlvs_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); + nfapi_resp->invalid_tlvs_configured_in_idle_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t)); + nfapi_resp->invalid_tlvs_configured_in_running_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t)); + nfapi_resp->missing_tlvs_list = + (nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); + + // unpack the TLV lists + unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_list, nfapi_resp->num_invalid_tlvs, ppReadPackedMsg, end); + unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_idle_list, + nfapi_resp->num_invalid_tlvs_configured_in_idle, + ppReadPackedMsg, + end); + unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_running_list, + nfapi_resp->num_invalid_tlvs_configured_in_running, + ppReadPackedMsg, + end); + unpack_nr_generic_tlv_list(nfapi_resp->missing_tlvs_list, nfapi_resp->num_missing_tlvs, ppReadPackedMsg, end); + retval &= unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(nfapi_resp->vendor_extension)); + return retval; } uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)