Files
openairinterface5g/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c
T
Rúben Soares Silva 0a796ebb6c Fix ERROR.indication unpack function
Fix an issue in which the unpacking is erroneously deemed unsuccessful even though it succeed in pulling all the bytes, this was due to not properly handling the return value of pull16 which is either 0 or 2, not 0 or 1.
Check the results of push and pull operation with correct boolean operator.
2025-09-15 14:54:44 +01:00

1889 lines
96 KiB
C

/*
* 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
*/
#include "nr_fapi.h"
#include "nr_fapi_p5.h"
#include "debug.h"
uint8_t fapi_nr_p5_message_body_pack(nfapi_nr_p4_p5_message_header_t *header,
uint8_t **ppWritePackedMsg,
uint8_t *end,
nfapi_p4_p5_codec_config_t *config)
{
uint8_t result = 0;
// look for the specific message
switch (header->message_id) {
case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST:
result = 1;
break;
case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
result = pack_nr_param_response(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
result = pack_nr_config_request(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
result = pack_nr_config_response(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
result = pack_nr_start_request(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
result = pack_nr_start_response(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
result = pack_nr_stop_request(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
result = pack_nr_stop_indication(header, ppWritePackedMsg, end, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
result = pack_nr_error_indication(header, ppWritePackedMsg, end, config);
break;
default: {
AssertFatal(header->message_id <= 0xFF,
"FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message",
header->message_id);
break;
}
}
return result;
}
int fapi_nr_p5_message_pack(void *pMessageBuf,
uint32_t messageBufLen,
void *pPackedBuf,
const uint32_t packedBufLen,
nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_p4_p5_message_header_t *pMessageHeader = pMessageBuf;
uint8_t *pWritePackedMessage = pPackedBuf;
AssertFatal(isFAPIMessageIDValid(pMessageHeader->message_id),
"FAPI message IDs are defined between 0x00 and 0xFF the message provided 0x%02x, which is not a FAPI message",
pMessageHeader->message_id);
AssertFatal(pMessageBuf != NULL && pPackedBuf != NULL, "P5 Pack supplied pointers are null");
uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen;
uint8_t *pPackedLengthField = &pWritePackedMessage[4];
uint8_t *pPacketBodyField = &pWritePackedMessage[8];
uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8];
const uint8_t res = fapi_nr_p5_message_body_pack(pMessageHeader, &pPacketBodyField, pPackMessageEnd, config);
AssertFatal(res > 0, "fapi_nr_p5_message_body_pack error packing message body %d\n", res);
// PHY API message header
push8(1, &pWritePackedMessage, pPackMessageEnd); // Number of messages
push8(0, &pWritePackedMessage, pPackMessageEnd); // Opaque handle
// PHY API Message structure
push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd); // Message type ID
// check for a valid message length
const uint32_t packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pPacketBodyField);
uint16_t packedMsgLen16 = get_packed_msg_len((uintptr_t)pPacketBodyFieldStart, (uintptr_t)pPacketBodyField);
if (pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST
|| pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_START_REQUEST
|| pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST
|| pMessageHeader->message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION) {
// These messages don't have a body, length is 0
packedMsgLen16 = 0;
}
AssertFatal(packedMsgLen <= 0xFFFF && packedMsgLen <= packedBufLen,
"Packed message 0x%02x length error %d, buffer supplied %d\n",
pMessageHeader->message_id,
packedMsgLen,
packedBufLen);
// Update the message length in the header
if (!push32(packedMsgLen16, &pPackedLengthField, pPackMessageEnd))
return -1;
// return the packed length
return packedMsgLen;
}
bool fapi_nr_p5_message_unpack(void *pMessageBuf,
const uint32_t messageBufLen,
void *pUnpackedBuf,
const uint32_t unpackedBufLen,
nfapi_p4_p5_codec_config_t *config)
{
fapi_message_header_t *pMessageHeader = pUnpackedBuf;
AssertFatal(pMessageBuf != NULL && pUnpackedBuf != NULL, "P5 unpack supplied pointers are null");
AssertFatal(messageBufLen >= NFAPI_HEADER_LENGTH && unpackedBufLen >= sizeof(fapi_message_header_t),
"P5 unpack supplied message buffer is too small %d, %d\n",
messageBufLen,
unpackedBufLen);
// clean the supplied buffer for - tag value blanking
(void)memset(pUnpackedBuf, 0, unpackedBufLen);
if (!fapi_nr_message_header_unpack(pMessageBuf, NFAPI_HEADER_LENGTH, pMessageHeader, sizeof(fapi_message_header_t), 0)) {
// failed to read the header
return false;
}
uint8_t *pReadPackedMessage = pMessageBuf + NFAPI_HEADER_LENGTH;
uint8_t *end = (uint8_t *)pMessageBuf + messageBufLen;
int result = -1;
if (check_nr_fapi_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) {
// the unpack buffer is not big enough for the struct
return false;
}
// look for the specific message
switch (pMessageHeader->message_id) {
case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST:
// PARAM request has no body;
result = 1;
break;
case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE:
result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST:
result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE:
result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST:
result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE:
result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST:
result = unpack_nr_stop_request(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION:
result = unpack_nr_stop_indication(&pReadPackedMessage, end, pMessageHeader, config);
break;
case NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION:
result = unpack_nr_error_indication(&pReadPackedMessage, end, pMessageHeader, config);
break;
default:
if (pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,
"%s VE NFAPI message ID %d. No ve decoder provided\n",
__FUNCTION__,
pMessageHeader->message_id);
} else {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id);
}
break;
}
return result != 0;
}
uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
}
uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg;
return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
}
uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
printf("\nRUNNING pack_param_response\n");
nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
uint8_t retval = push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end);
retval &= pack_nr_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG,
&(pNfapiMsg->cell_param.release_capability),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG,
&(pNfapiMsg->cell_param.phy_state),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG,
&(pNfapiMsg->cell_param.skip_blank_dl_config),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG,
&(pNfapiMsg->cell_param.skip_blank_ul_config),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG,
&(pNfapiMsg->cell_param.num_config_tlvs_to_report),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value);
for (int i = 0; i < pNfapiMsg->cell_param.num_config_tlvs_to_report.value; ++i) {
retval &= push16(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag, ppWritePackedMsg, end) != 0;
retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.length, ppWritePackedMsg, end);
retval &= push8(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].value, ppWritePackedMsg, end);
// Add padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
int padding = get_tlv_padding(pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.length);
NFAPI_TRACE(NFAPI_TRACE_DEBUG,
"TLV 0x%x with padding of %d bytes\n",
pNfapiMsg->cell_param.config_tlvs_to_report_list[i].tl.tag,
padding);
if (padding != 0) {
memset(*ppWritePackedMsg, 0, padding);
(*ppWritePackedMsg) += padding;
}
}
retval &= pack_nr_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG,
&(pNfapiMsg->carrier_param.cyclic_prefix),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
&(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG,
&(pNfapiMsg->carrier_param.supported_bandwidth_dl),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
&(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG,
&(pNfapiMsg->carrier_param.supported_bandwidth_ul),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG,
&(pNfapiMsg->pdcch_param.cce_mapping_type),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
&(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
&(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG,
&(pNfapiMsg->pdcch_param.pdcch_mu_mimo),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG,
&(pNfapiMsg->pdcch_param.pdcch_precoder_cycling),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG,
&(pNfapiMsg->pdcch_param.max_pdcch_per_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG,
&(pNfapiMsg->pucch_param.pucch_formats),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG,
&(pNfapiMsg->pucch_param.max_pucchs_per_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG,
&(pNfapiMsg->pdsch_param.pdsch_mapping_type),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG,
&(pNfapiMsg->pdsch_param.pdsch_allocation_types),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
&(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG,
&(pNfapiMsg->pdsch_param.pdsch_cbg),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG,
&(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG,
&(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
&(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG,
&(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
&(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG,
&(pNfapiMsg->pdsch_param.supported_max_modulation_order_dl),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG,
&(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
&(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG,
&(pNfapiMsg->pdsch_param.premption_support),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG,
&(pNfapiMsg->pdsch_param.pdsch_non_slot_support),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG,
&(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG,
&(pNfapiMsg->pusch_param.uci_only_pusch),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG,
&(pNfapiMsg->pusch_param.pusch_frequency_hopping),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG,
&(pNfapiMsg->pusch_param.pusch_dmrs_config_types),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG,
&(pNfapiMsg->pusch_param.pusch_dmrs_max_len),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
&(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG,
&(pNfapiMsg->pusch_param.pusch_cbg),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG,
&(pNfapiMsg->pusch_param.pusch_mapping_type),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG,
&(pNfapiMsg->pusch_param.pusch_allocation_types),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
&(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG,
&(pNfapiMsg->pusch_param.pusch_max_ptrs_ports),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
&(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
&(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
&(pNfapiMsg->pusch_param.supported_modulation_order_ul),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG,
&(pNfapiMsg->pusch_param.max_mu_mimo_users_ul),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG,
&(pNfapiMsg->pusch_param.dfts_ofdm_support),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
&(pNfapiMsg->pusch_param.pusch_aggregation_factor),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG,
&(pNfapiMsg->prach_param.prach_long_formats),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG,
&(pNfapiMsg->prach_param.prach_short_formats),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG,
&(pNfapiMsg->prach_param.prach_restricted_sets),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
&(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
&(pNfapiMsg->measurement_param.rssi_measurement_support),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&&
// config:
pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG,
&(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4),
ppWritePackedMsg,
end,
&pack_ipv4_address_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG,
&(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6),
ppWritePackedMsg,
end,
&pack_ipv6_address_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG,
&(pNfapiMsg->nfapi_config.p7_vnf_port),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG,
&(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4),
ppWritePackedMsg,
end,
&pack_ipv4_address_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG,
&(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6),
ppWritePackedMsg,
end,
&pack_ipv6_address_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG,
&(pNfapiMsg->nfapi_config.p7_pnf_port),
ppWritePackedMsg,
end,
&pack_uint16_tlv_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG,
&(pNfapiMsg->nfapi_config.timing_window),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG,
&(pNfapiMsg->nfapi_config.timing_info_mode),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_nr_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG,
&(pNfapiMsg->nfapi_config.timing_info_period),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value)
&& pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
return retval;
}
static uint8_t unpack_config_tlvs_to_report(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{
uint8_t *pStartOfValue = *ppReadPackedMsg;
nfapi_nr_cell_param_t *cellParamTable = (nfapi_nr_cell_param_t *)tlv;
uint8_t retval = pull16(ppReadPackedMsg, &cellParamTable->num_config_tlvs_to_report.value, end);
// check if the length was right;
if (cellParamTable->num_config_tlvs_to_report.tl.length != (*ppReadPackedMsg - pStartOfValue)) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,
"Warning tlv tag 0x%x length %d not equal to unpack %ld\n",
cellParamTable->num_config_tlvs_to_report.tl.tag,
cellParamTable->num_config_tlvs_to_report.tl.length,
(*ppReadPackedMsg - pStartOfValue));
}
// Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
int padding = get_tlv_padding(cellParamTable->num_config_tlvs_to_report.tl.length);
if (padding != 0) {
(*ppReadPackedMsg) += padding;
}
// after this value, get the tlv list
cellParamTable->config_tlvs_to_report_list = calloc(cellParamTable->num_config_tlvs_to_report.value, sizeof(nfapi_uint8_tlv_t *));
for (int i = 0; i < cellParamTable->num_config_tlvs_to_report.value; ++i) {
pull16(ppReadPackedMsg, &cellParamTable->config_tlvs_to_report_list[i].tl.tag, end);
pull8(ppReadPackedMsg, (uint8_t *)&cellParamTable->config_tlvs_to_report_list[i].tl.length, end);
pull8(ppReadPackedMsg, &cellParamTable->config_tlvs_to_report_list[i].value, end);
// Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
padding = get_tlv_padding(cellParamTable->config_tlvs_to_report_list[i].tl.length);
if (padding != 0) {
(*ppReadPackedMsg) += padding;
}
}
return retval;
}
uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg;
unpack_tlv_t unpack_fns[] = {
{NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), &unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param), &unpack_config_tlvs_to_report},
{NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG,
&(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl),
&unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG,
&(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG,
&(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG,
&(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG,
&(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG,
&(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_TBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG,
&(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_MAX_MODULATION_ORDER_DL_TAG,
&(pNfapiMsg->pdsch_param.supported_max_modulation_order_dl),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG,
&(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG,
&(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG,
&(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG,
&(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG,
&(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG,
&(pNfapiMsg->pusch_param.supported_modulation_order_ul),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG,
&(pNfapiMsg->pusch_param.pusch_aggregation_factor),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint16_tlv_value},
{NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG,
&(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot),
&unpack_uint8_tlv_value},
{NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG,
&(pNfapiMsg->measurement_param.rssi_measurement_support),
&unpack_uint8_tlv_value},
// config
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value},
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value},
{NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value},
{NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value},
{NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value},
{NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value},
{NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value},
{NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value},
{NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value},
};
return (pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end)
&& unpack_nr_tlv_list(unpack_fns,
sizeof(unpack_fns) / sizeof(unpack_tlv_t),
ppReadPackedMsg,
end,
config,
&pNfapiMsg->vendor_extension));
}
#ifndef ENABLE_AERIAL
static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
{
nfapi_nr_dbt_tlv_ve_t *dbt_ve = (nfapi_nr_dbt_tlv_ve_t *)tlv;
nfapi_nr_dbt_pdu_t *dbt_config = &dbt_ve->value;
if (!( push16(dbt_config->num_dig_beams, ppWritePackedMsg, end) && push16(dbt_config->num_txrus, ppWritePackedMsg, end) )) {
return 0;
}
for (int i = 0; i< dbt_config->num_dig_beams; i++) {
const nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i];
if (!(push16(dig_beam->beam_idx, ppWritePackedMsg, end))) {
return 0;
}
for (int k = 0; k< dbt_config->num_txrus; k++) {
const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k];
if (!(push16(tx_ru->dig_beam_weight_Re, ppWritePackedMsg, end) && push16(tx_ru->dig_beam_weight_Im, ppWritePackedMsg, end))) {
return 0;
}
}
}
return 1;
}
static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
{
nfapi_nr_pm_tlv_ve_t *pm_ve = (nfapi_nr_pm_tlv_ve_t *)tlv;
nfapi_nr_pm_list_t *pmi_list = &pm_ve->value;
if (!( push16(pmi_list->num_pm_idx, ppWritePackedMsg, end) )) {
return 0;
}
for (int i = 0; i< pmi_list->num_pm_idx; i++) {
const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i];
if (!(push16(pm_pdu->pm_idx, ppWritePackedMsg, end) && push16(pm_pdu->numLayers, ppWritePackedMsg, end)
&& push16(pm_pdu->num_ant_ports, ppWritePackedMsg, end))) {
return 0;
}
for (int k = 0; k < pm_pdu->numLayers; k++) {
for (int j = 0; j < pm_pdu->num_ant_ports; j++) {
const nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j];
if (!(push16(pm_weight->precoder_weight_Re, ppWritePackedMsg, end) && push16(pm_weight->precoder_weight_Im, ppWritePackedMsg, end))) {
return 0;
}
}
}
}
return 1;
}
#endif
#ifdef ENABLE_10_04
static uint8_t pack_nr_tdd_table_10_04(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
{
nfapi_nr_tdd_table_tlv_t *tdd_table_tlv = (nfapi_nr_tdd_table_tlv_t *)tlv;
nfapi_nr_tdd_table_t *tdd_table = tdd_table_tlv->value;
#ifndef ENABLE_AERIAL
if (!push8(tdd_table->tdd_period.value, ppWritePackedMsg, end)) {
return 0;
}
#endif
for (int i = 0; i < tdd_table_tlv->slots_per_frame; i++) {
for (int k = 0; k < tdd_table_tlv->symbols_per_slot; k++) {
if (!push8(tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.value, ppWritePackedMsg, end)) {
return 0;
}
}
}
return 1;
}
#endif
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
#endif
// START TDD Table
if (pNfapiMsg->cell_config.frame_duplex_type.value == 1 /* TDD */) {
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;
// 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12;
#ifdef ENABLE_10_02
retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG,
&(pNfapiMsg->tdd_table.tdd_period),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
numTLVs++;
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++;
}
}
#endif
#ifdef ENABLE_10_04
#ifdef ENABLE_AERIAL
retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG,
&(pNfapiMsg->tdd_table.tdd_period),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
numTLVs++;
nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, .value = &pNfapiMsg->tdd_table, .slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value], .symbols_per_slot = number_of_symbols_per_slot };
retval &= pack_nr_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG,
&tdd_table_tlv,
ppWritePackedMsg,
end,
&pack_nr_tdd_table_10_04);
numTLVs++;
#else
nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_TDD_TABLE, .value = &pNfapiMsg->tdd_table, .slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value], .symbols_per_slot = number_of_symbols_per_slot };
retval &= pack_nr_tlv(NFAPI_NR_CONFIG_TDD_TABLE,
&tdd_table_tlv,
ppWritePackedMsg,
end,
&pack_nr_tdd_table_10_04);
numTLVs++;
#endif
#endif
}
// END TDD Table
// 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
#ifndef ENABLE_AERIAL
// START Digital Beam Table (DBT) PDU
if (pNfapiMsg->dbt_config.num_dig_beams != 0) {
nfapi_nr_dbt_tlv_ve_t dbt_tlv = {.tl.tag = NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, .value = pNfapiMsg->dbt_config};
pack_nr_tlv(NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, &dbt_tlv, ppWritePackedMsg, end, &pack_dbt_table_tlv_value);
numTLVs++;
}
// END Digital Beam Table (DBT) PDU
// START Precoding Matrix (PM) PDU
if (pNfapiMsg->pmi_list.num_pm_idx != 0) {
nfapi_nr_pm_tlv_ve_t pm_tlv = {.tl.tag = NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, .value = pNfapiMsg->pmi_list};
pack_nr_tlv(NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, &pm_tlv, ppWritePackedMsg, end, &pack_pm_table_tlv_value);
numTLVs++;
}
// is 0xA011 END Precoding Matrix (PM) PDU
// 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
AssertFatal(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag == 0, "BF Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs += pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag == NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == 0, "BF Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
AssertFatal(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == 0,
"Total num beams Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs +=
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
for (int beam = 0; beam < pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value; beam++) {
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam].tl.tag == 0,
"Analog beams list Vendor extension shouldn't be set!");
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
retval &= pack_nr_tlv(NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG,
&(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam]),
ppWritePackedMsg,
end,
&pack_uint8_tlv_value);
// only increase if it was set
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
}
pNfapiMsg->num_tlv = numTLVs;
retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
return retval;
}
static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{
nfapi_nr_dbt_pdu_t *dbt_config = (nfapi_nr_dbt_pdu_t *)tlv;
if (!(pull16(ppReadPackedMsg, &dbt_config->num_dig_beams, end) && pull16(ppReadPackedMsg, &dbt_config->num_txrus, end))) {
return 0;
}
if (dbt_config->num_dig_beams > 0) {
dbt_config->dig_beam_list = calloc(dbt_config->num_dig_beams, sizeof(*dbt_config->dig_beam_list));
}
for (int i = 0; i < dbt_config->num_dig_beams; i++) {
nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i];
if (!(pull16(ppReadPackedMsg, &dig_beam->beam_idx, end))) {
return 0;
}
if (dbt_config->num_txrus > 0) {
dig_beam->txru_list = calloc(dbt_config->num_txrus, sizeof(*dig_beam->txru_list));
}
for (int k = 0; k < dbt_config->num_txrus; k++) {
nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k];
if (!(pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Re, end) && pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Im, end))) {
return 0;
}
}
}
return 1;
}
static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{
nfapi_nr_pm_list_t *pm_list = (nfapi_nr_pm_list_t *)tlv;
if (!(pull16(ppReadPackedMsg, &pm_list->num_pm_idx, end))) {
return 0;
}
if (pm_list->num_pm_idx > 0) {
pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu));
}
for (int i = 0; i < pm_list->num_pm_idx; i++) {
nfapi_nr_pm_pdu_t *pm_pdu = &pm_list->pmi_pdu[i];
if (!(pull16(ppReadPackedMsg, &pm_pdu->pm_idx, end) && pull16(ppReadPackedMsg, &pm_pdu->numLayers, end)
&& pull16(ppReadPackedMsg, &pm_pdu->num_ant_ports, end))) {
return 0;
}
AssertFatal(pm_pdu->numLayers <= 4 && pm_pdu->num_ant_ports <= 4, "Precoding matrix size limited to 4X4 for the time being\n");
for (int k = 0; k < pm_pdu->numLayers; k++) {
for (int j = 0; j < pm_pdu->num_ant_ports; j++) {
nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j];
if (!(pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Re, end)
&& pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Im, end))) {
return 0;
}
}
}
}
return 1;
}
#ifdef ENABLE_10_04
static uint8_t unpack_nr_tdd_table_10_04(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
{
nfapi_nr_tdd_table_tlv_t *tdd_table_tlv = (nfapi_nr_tdd_table_tlv_t *)tlv;
nfapi_nr_tdd_table_t *tdd_table = tdd_table_tlv->value;
if (!(pull8(ppReadPackedMsg, &tdd_table->tdd_period.value, end))) {
return 0;
}
tdd_table->tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG;
const int slots = tdd_table_tlv->slots_per_frame;
const int symbols = tdd_table_tlv->symbols_per_slot;
if (!tdd_table->max_tdd_periodicity_list) {
tdd_table->max_tdd_periodicity_list = calloc(slots, sizeof(*tdd_table->max_tdd_periodicity_list));
}
for (int slot = 0; slot < slots; slot++) {
nfapi_nr_max_tdd_periodicity_t* list = &tdd_table->max_tdd_periodicity_list[slot];
if (!list->max_num_of_symbol_per_slot_list) {
list->max_num_of_symbol_per_slot_list = calloc(symbols, sizeof(*list->max_num_of_symbol_per_slot_list));
}
for (int sym = 0; sym < symbols; sym++) {
if (!(pull8(ppReadPackedMsg, &list->max_num_of_symbol_per_slot_list[sym].slot_config.value, end))) {
return 0;
}
list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG;
}
}
return 1;
}
#endif
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;
#ifdef ENABLE_10_02
int tdd_periodicity_idx = 0;
int symbol_per_slot_idx = 0;
#endif
int beam_ve_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},
#ifdef ENABLE_10_02
{NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_uint8_tlv_value},
#endif
#ifdef ENABLE_10_04
#ifdef ENABLE_AERIAL
{NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_nr_tdd_table_10_04},
#else
{NFAPI_NR_CONFIG_TDD_TABLE, NULL, &unpack_nr_tdd_table_10_04},
#endif
#endif
{NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value},
{NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext), &unpack_uint8_tlv_value},
{NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value},
{NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
{NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value},
{NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_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}};
#ifdef ENABLE_10_04
#ifdef ENABLE_AERIAL
nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG};
#else
nfapi_nr_tdd_table_tlv_t tdd_table_tlv = {.tl.tag = NFAPI_NR_CONFIG_TDD_TABLE};
#endif
#endif
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) + 4 < 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_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG:
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = generic_tl.tag;
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.length = generic_tl.length;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext, ppReadPackedMsg, end);
pNfapiMsg->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
beam_ve_idx = 0;
break;
case NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG:
unpack_fns[idx].tlv = &pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx];
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.tag = generic_tl.tag;
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.length = generic_tl.length;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end);
beam_ve_idx ++;
break;
case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG:
unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end);
break;
case NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG:
unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->pmi_list, ppReadPackedMsg, end);
break;
#ifdef ENABLE_10_04
#ifdef ENABLE_AERIAL
case NFAPI_NR_CONFIG_SLOT_CONFIG_TAG:
#else
case NFAPI_NR_CONFIG_TDD_TABLE:
#endif
unpack_fns[idx].tlv = &generic_tl;
result = (*unpack_fns[idx].unpack_func)(&tdd_table_tlv, ppReadPackedMsg, end);
break;
#endif
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 = calloc(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);
// 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;
// 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2
uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12;
if (pNfapiMsg->cell_config.frame_duplex_type.value == 1 /* TDD */) {
const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160};
int n = slotsperframe[pNfapiMsg->ssb_config.scs_common.value];
pNfapiMsg->tdd_table.max_tdd_periodicity_list = calloc(n, sizeof(nfapi_nr_max_tdd_periodicity_t));
for (int i = 0; i < n; i++) {
pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list =
calloc(number_of_symbols_per_slot, sizeof(nfapi_nr_max_num_of_symbol_per_slot_t));
}
#ifdef ENABLE_10_04
tdd_table_tlv.slots_per_frame = slotsperframe[pNfapiMsg->ssb_config.scs_common.value];
tdd_table_tlv.symbols_per_slot = number_of_symbols_per_slot;
tdd_table_tlv.value = &pNfapiMsg->tdd_table;
#endif
}
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;
#ifdef ENABLE_10_02
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;
#endif
default:
result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end);
break;
}
// update tl pointer with updated value, if it was set in the switch (it was inside lists)
if (!tl) {
tl = (nfapi_tl_t *)(unpack_fns[idx].tlv);
tl->tag = generic_tl.tag;
tl->length = generic_tl.length;
}
if (result == 0)
return 0;
// check if the length was right;
if (tl->length != (((*ppReadPackedMsg)) - pStartOfValue))
NFAPI_TRACE(NFAPI_TRACE_ERROR,
"Warning tlv tag 0x%x length %d not equal to unpack %lu\n",
tl->tag,
tl->length,
(*ppReadPackedMsg - pStartOfValue));
// Remove padding that ensures multiple of 4 bytes (SCF 225 Section 2.3.2.1)
int padding = get_tlv_padding(tl->length);
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "TLV 0x%x length %d with padding of %d bytes\n", tl->tag, tl->length, padding);
if (padding != 0)
(*ppReadPackedMsg) += padding;
}
}
if (tagMatch == 0) {
if (generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) {
int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
if (result == 0) {
// got to the end.
return 0;
} else if (result < 0) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag);
if (++numBadTags > MAX_BAD_TAG) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
return 0;
}
if ((end - *ppReadPackedMsg) >= generic_tl.length) {
// Advance past the unknown TLV
(*ppReadPackedMsg) += generic_tl.length;
int padding = get_tlv_padding(generic_tl.length);
(*ppReadPackedMsg) += padding;
} else {
// go to the end
return 0;
}
}
} else {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag);
if (++numBadTags > MAX_BAD_TAG) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n");
return 0;
}
if ((end - *ppReadPackedMsg) >= generic_tl.length) {
// Advance past the unknown TLV
(*ppReadPackedMsg) += generic_tl.length;
int padding = get_tlv_padding(generic_tl.length);
(*ppReadPackedMsg) += padding;
} else {
// go to the end
return 0;
}
}
}
}
struct sockaddr_in vnf_p7_sockaddr;
memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), 4);
printf("[PNF] vnf p7 %s:%d\n", inet_ntoa(vnf_p7_sockaddr.sin_addr), pNfapiMsg->nfapi_config.p7_vnf_port.value);
return 1;
}
uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg;
uint8_t retval = push8(pNfapiMsg->error_code, ppWritePackedMsg, end);
retval &= push8(pNfapiMsg->num_invalid_tlvs, ppWritePackedMsg, end);
retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_idle, ppWritePackedMsg, end);
retval &= push8(pNfapiMsg->num_invalid_tlvs_configured_in_running, ppWritePackedMsg, end);
retval &= push8(pNfapiMsg->num_missing_tlvs, ppWritePackedMsg, end);
// pack lists
for (int i = 0; i < pNfapiMsg->num_invalid_tlvs; ++i) {
nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_list[i]);
pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
}
for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_idle; ++i) {
nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_idle_list[i]);
pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
}
for (int i = 0; i < pNfapiMsg->num_invalid_tlvs_configured_in_running; ++i) {
nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->invalid_tlvs_configured_in_running_list[i]);
pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
}
for (int i = 0; i < pNfapiMsg->num_missing_tlvs; ++i) {
nfapi_nr_generic_tlv_scf_t *element = &(pNfapiMsg->missing_tlvs_list[i]);
pack_nr_generic_tlv(element->tl.tag, element, ppWritePackedMsg, end);
}
retval &= pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
return retval;
}
uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_config_response_scf_t *nfapi_resp = (nfapi_nr_config_response_scf_t *)msg;
uint8_t retval = pull8(ppReadPackedMsg, &nfapi_resp->error_code, end)
&& pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs, end)
&& pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_idle, end)
&& pull8(ppReadPackedMsg, &nfapi_resp->num_invalid_tlvs_configured_in_running, end)
&& pull8(ppReadPackedMsg, &nfapi_resp->num_missing_tlvs, end);
// First unpack the invalid_tlvs_list
// allocate the memory
nfapi_resp->invalid_tlvs_list =
(nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
nfapi_resp->invalid_tlvs_configured_in_idle_list =
(nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t));
nfapi_resp->invalid_tlvs_configured_in_running_list =
(nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t));
nfapi_resp->missing_tlvs_list =
(nfapi_nr_generic_tlv_scf_t *)malloc(nfapi_resp->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t));
// unpack the TLV lists
unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_list, nfapi_resp->num_invalid_tlvs, ppReadPackedMsg, end);
unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_idle_list,
nfapi_resp->num_invalid_tlvs_configured_in_idle,
ppReadPackedMsg,
end);
unpack_nr_generic_tlv_list(nfapi_resp->invalid_tlvs_configured_in_running_list,
nfapi_resp->num_invalid_tlvs_configured_in_running,
ppReadPackedMsg,
end);
unpack_nr_generic_tlv_list(nfapi_resp->missing_tlvs_list, nfapi_resp->num_missing_tlvs, ppReadPackedMsg, end);
// TODO: Process and use the invalid TLVs fields
retval &= unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(nfapi_resp->vendor_extension));
return retval;
}
uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
}
uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg;
return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
}
uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end)
&& pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config));
}
uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg;
return (pull8(ppReadPackedMsg, (uint8_t *)&pNfapiMsg->error_code, end)
&& unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)));
}
uint8_t pack_nr_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_stop_request_scf_t *pNfapiMsg = (nfapi_nr_stop_request_scf_t *)msg;
return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
}
uint8_t unpack_nr_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_stop_request_scf_t *pNfapiMsg = (nfapi_nr_stop_request_scf_t *)msg;
return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
}
uint8_t pack_nr_stop_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_stop_indication_scf_t *pNfapiMsg = (nfapi_nr_stop_indication_scf_t *)msg;
return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
}
uint8_t unpack_nr_stop_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_stop_indication_scf_t *pNfapiMsg = (nfapi_nr_stop_indication_scf_t *)msg;
return unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension));
}
uint8_t pack_nr_error_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg;
if (push16(pNfapiMsg->sfn, ppWritePackedMsg, end) && push16(pNfapiMsg->slot, ppWritePackedMsg, end)
&& push8(pNfapiMsg->message_id, ppWritePackedMsg, end) && push8(pNfapiMsg->error_code, ppWritePackedMsg, end)
&& pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) {
return 1;
} else {
return 0;
}
}
uint8_t unpack_nr_error_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config)
{
nfapi_nr_error_indication_scf_t *pNfapiMsg = (nfapi_nr_error_indication_scf_t *)msg;
if (pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot, end)
&& pull8(ppReadPackedMsg, &pNfapiMsg->message_id, end) && pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end)
&& unpack_nr_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))) {
return 1;
} else {
return 0;
}
}