From 5a30abc29e4808930dbacb0c0c24b5e80a1555ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 10 Apr 2025 15:58:14 +0100 Subject: [PATCH 1/9] Finish dump procedure for PARAM.response message Remove unnecessary checks on free_param_response --- nfapi/open-nFAPI/fapi/inc/nr_fapi.h | 3 + nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 128 ++++++++++++++++++- 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index e8e645b8cf..ee405792d2 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -35,6 +35,9 @@ #include "debug.h" #define INDENTED_PRINTF(format, ...) printf("%*s" format, depth * 2, "", ##__VA_ARGS__) +#define INDENTED_GENERIC_PRINT(string, format, ...) INDENTED_PRINTF(string " = " format "\n", ##__VA_ARGS__) +#define INDENTED_TLV_PRINT(tlv_name, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, "0x%02x", tlv.tl.tag, tlv.value) +#define INDENTED_TLV_FORMAT_PRINT(tlv_name, format, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, format, tlv.tl.tag, tlv.value) #define EQ_TLV(_tlv_a, _tlv_b) \ do { \ 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 1b5e3f0ad8..f4d2a618ec 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -398,13 +398,10 @@ void free_param_request(nfapi_nr_param_request_scf_t *msg) void free_param_response(nfapi_nr_param_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); + + free(msg->cell_param.config_tlvs_to_report_list); - if (msg->cell_param.config_tlvs_to_report_list) { - free(msg->cell_param.config_tlvs_to_report_list); - } } void free_config_request(nfapi_nr_config_request_scf_t *msg) @@ -986,11 +983,128 @@ void dump_param_request(const nfapi_nr_param_request_scf_t *msg) void dump_param_response(const nfapi_nr_param_response_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Error Code = 0x%02x\n", msg->error_code); INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Cell Param */ + const nfapi_nr_cell_param_t *cell_param = &msg->cell_param; + depth++; + INDENTED_TLV_PRINT("Release Capability", cell_param->release_capability); + INDENTED_TLV_PRINT("PHY State", cell_param->phy_state); + INDENTED_TLV_PRINT("Skip Blank Dl Config", cell_param->skip_blank_dl_config); + INDENTED_TLV_PRINT("Skip Blank UL Config", cell_param->skip_blank_ul_config); + INDENTED_TLV_PRINT("NumConfigTLVsToReport", cell_param->num_config_tlvs_to_report); + depth++; + for (int i = 0; i < cell_param->num_config_tlvs_to_report.value; i++) { + const nfapi_uint8_tlv_t *reportedTLV = &cell_param->config_tlvs_to_report_list[i]; + INDENTED_PRINTF("(0x%04x) Reported CONFIG TLV #%d = 0x%02x\n", reportedTLV->tl.tag, i + 1, reportedTLV->value); + } + depth--; + /* Carrier Param */ + const nfapi_nr_carrier_param_t *carrier_param = &msg->carrier_param; + INDENTED_TLV_PRINT("Cyclic Prefix", carrier_param->cyclic_prefix); + INDENTED_TLV_PRINT("Supported SCS DL", carrier_param->supported_subcarrier_spacings_dl); + INDENTED_TLV_PRINT("Supported BW DL", carrier_param->supported_bandwidth_dl); + INDENTED_TLV_PRINT("Supported SCS UL", carrier_param->supported_subcarrier_spacings_ul); + INDENTED_TLV_PRINT("Supported BW UL", carrier_param->supported_bandwidth_ul); + /* PDCCH Param */ + const nfapi_nr_pdcch_param_t *pdcch_param = &msg->pdcch_param; + INDENTED_TLV_PRINT("CCE Mapping Type", pdcch_param->cce_mapping_type); + INDENTED_TLV_PRINT("CSet Outside First 3 OFDM Symbols of Slot", pdcch_param->coreset_outside_first_3_of_ofdm_syms_of_slot); + INDENTED_TLV_PRINT("Precoder Granularity Coreset", pdcch_param->coreset_precoder_granularity_coreset); + INDENTED_TLV_PRINT("PDCCH Mu MIMO", pdcch_param->pdcch_mu_mimo); + INDENTED_TLV_PRINT("PDCCH Precoder Cycling", pdcch_param->pdcch_precoder_cycling); + INDENTED_TLV_PRINT("Max PDCCH per Slot", pdcch_param->max_pdcch_per_slot); + /* PUCHH Params */ + const nfapi_nr_pucch_param_t *pucch_param = &msg->pucch_param; + INDENTED_TLV_PRINT("PUCCH Formats", pucch_param->pucch_formats); + INDENTED_TLV_PRINT("Max PUCCH per Slot", pucch_param->max_pucchs_per_slot); + /* PDSCH Params */ + const nfapi_nr_pdsch_param_t *pdsch_param = &msg->pdsch_param; + INDENTED_TLV_PRINT("PDSCH Mapping Type", pdsch_param->pdsch_mapping_type); + INDENTED_TLV_PRINT("PDSCH Allocation Types", pdsch_param->pdsch_allocation_types); + INDENTED_TLV_PRINT("PDSCH VRB to PRB Mapping", pdsch_param->pdsch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PDSCH CBG", pdsch_param->pdsch_cbg); + INDENTED_TLV_PRINT("PDSCH DMRS Config Types", pdsch_param->pdsch_dmrs_config_types); + INDENTED_TLV_PRINT("PDSCH DMRS Max Length", pdsch_param->pdsch_dmrs_max_length); + INDENTED_TLV_PRINT("PDSCH DMRS Additional Position", pdsch_param->pdsch_dmrs_additional_pos); + INDENTED_TLV_PRINT("Max PDSCH TBs per Slot", pdsch_param->max_pdsch_tbs_per_slot); + INDENTED_TLV_PRINT("Max number MIMO Layers PDSCH", pdsch_param->max_number_mimo_layers_pdsch); + INDENTED_TLV_PRINT("Supported Max Modulation Order DL", pdsch_param->supported_max_modulation_order_dl); + INDENTED_TLV_PRINT("Max Mu MIMO Users DL", pdsch_param->max_mu_mimo_users_dl); + INDENTED_TLV_PRINT("PDSCH Data in DMRS Symbols", pdsch_param->pdsch_data_in_dmrs_symbols); + INDENTED_TLV_PRINT("Preemption Support", pdsch_param->premption_support); + INDENTED_TLV_PRINT("PDSCH Non Slot Support", pdsch_param->pdsch_non_slot_support); + /* PUSCH Params */ + const nfapi_nr_pusch_param_t *pusch_param = &msg->pusch_param; + INDENTED_TLV_PRINT("UCI Mux ULSCH in PUSCH", pusch_param->uci_mux_ulsch_in_pusch); + INDENTED_TLV_PRINT("UCI Only PUSCH", pusch_param->uci_only_pusch); + INDENTED_TLV_PRINT("PUSCH Frequency Hopping", pusch_param->pusch_frequency_hopping); + INDENTED_TLV_PRINT("PUSCH DMRS Config Types", pusch_param->pusch_dmrs_config_types); + INDENTED_TLV_PRINT("PUSCH DMRS Max Len", pusch_param->pusch_dmrs_max_len); + INDENTED_TLV_PRINT("PUSCH DMRS Additional Pos", pusch_param->pusch_dmrs_additional_pos); + INDENTED_TLV_PRINT("PUSCH CBG", pusch_param->pusch_cbg); + INDENTED_TLV_PRINT("PUSCH Mapping Type", pusch_param->pusch_mapping_type); + INDENTED_TLV_PRINT("PUSCH Allocation Types", pusch_param->pusch_allocation_types); + INDENTED_TLV_PRINT("PUSCH VRB to PRB Mapping", pusch_param->pusch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PUSCH Max PTRS Ports", pusch_param->pusch_max_ptrs_ports); + INDENTED_TLV_PRINT("Max PUSCH TBs per Slot", pusch_param->max_pduschs_tbs_per_slot); + INDENTED_TLV_PRINT("Max Number MIMO Layers non CB PUSCH", pusch_param->max_number_mimo_layers_non_cb_pusch); + INDENTED_TLV_PRINT("Supported Modulation Order UL", pusch_param->supported_modulation_order_ul); + INDENTED_TLV_PRINT("Max MU MIMO Users UL", pusch_param->max_mu_mimo_users_ul); + INDENTED_TLV_PRINT("DTFS OFDM Support", pusch_param->dfts_ofdm_support); + INDENTED_TLV_PRINT("PUSCH Aggregation Factor", pusch_param->pusch_aggregation_factor); + /* PRACH Params */ + const nfapi_nr_prach_param_t *prach_param = &msg->prach_param; + INDENTED_TLV_PRINT("PRACH Long Formats", prach_param->prach_long_formats); + INDENTED_TLV_PRINT("PRACH Short Formats", prach_param->prach_short_formats); + INDENTED_TLV_PRINT("PRACH Restricted Sets", prach_param->prach_restricted_sets); + INDENTED_TLV_PRINT("Max PRACH Occasions in a Slot", prach_param->max_prach_fd_occasions_in_a_slot); + /* Measurement Params */ + const nfapi_nr_measurement_param_t *measurement_param = &msg->measurement_param; + INDENTED_TLV_PRINT("RSSI Measurement Support", measurement_param->rssi_measurement_support); + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); depth--; } From 5016fc75c6a729596c50d279766213a37e4b1a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 11 Apr 2025 14:12:08 +0100 Subject: [PATCH 2/9] Finish dump procedure for CONFIG.request message Remove unnecessary checks on free_config_request Added logic to fill random data for PNF addresses and port TLVs to test dumping function --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 219 ++++++++++++++++++- nfapi/tests/p5/nr_fapi_config_request_test.c | 15 ++ 2 files changed, 233 insertions(+), 1 deletion(-) 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 f4d2a618ec..52f2ee8031 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -1111,10 +1111,227 @@ void dump_param_response(const nfapi_nr_param_response_scf_t *msg) void dump_config_request(const nfapi_nr_config_request_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Carrier Config */ + const nfapi_nr_carrier_config_t *carrier_config = &msg->carrier_config; + INDENTED_TLV_PRINT("DL Bandwidth", carrier_config->dl_bandwidth); + INDENTED_TLV_PRINT("DL Frequency", carrier_config->dl_frequency); + INDENTED_PRINTF("(0x%04x) DL K0 = ", NFAPI_NR_CONFIG_DL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) DL Grid Size = ", NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num TX Antennas", carrier_config->num_tx_ant); + INDENTED_TLV_PRINT("UL Bandwidth", carrier_config->uplink_bandwidth); + INDENTED_TLV_PRINT("UL Frequency", carrier_config->uplink_frequency); + INDENTED_PRINTF("(0x%04x) UL K0 = ", NFAPI_NR_CONFIG_UL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) UL Grid Size = ", NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num RX Antennas", carrier_config->num_rx_ant); + INDENTED_TLV_PRINT("Frequency Shift 7p5KHz", carrier_config->frequency_shift_7p5khz); + /* Cell Config */ + const nfapi_nr_cell_config_t *cell_config = &msg->cell_config; + INDENTED_TLV_PRINT("Physical Cell ID", cell_config->phy_cell_id); + INDENTED_TLV_PRINT("Frame Duplex Type", cell_config->frame_duplex_type); + /* SSB Config */ + const nfapi_nr_ssb_config_t *ssb_config = &msg->ssb_config; + INDENTED_TLV_PRINT("SSB Block Power", ssb_config->ss_pbch_power); + INDENTED_TLV_PRINT("BCH Payload", ssb_config->bch_payload); + INDENTED_TLV_PRINT("SCS Common", ssb_config->scs_common); + /* PRACH Config */ + const nfapi_nr_prach_config_t *prach_config = &msg->prach_config; + INDENTED_TLV_PRINT("PRACH Sequence Length", prach_config->prach_sequence_length); + INDENTED_TLV_PRINT("PRACH Subcarrier Spacing", prach_config->prach_sub_c_spacing); + INDENTED_TLV_PRINT("Restricted Set Config", prach_config->restricted_set_config); + INDENTED_TLV_PRINT("Num PRACH FD Occasions", prach_config->num_prach_fd_occasions); + INDENTED_TLV_PRINT("PRACH Config Index", prach_config->prach_ConfigurationIndex); + depth++; + for (int i = 0; i < prach_config->num_prach_fd_occasions.value; i++) { + const nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(prach_config->num_prach_fd_occasions_list[i]); + INDENTED_TLV_PRINT("PRACH Root Sequence Index", prach_fd_occasion->prach_root_sequence_index); + INDENTED_TLV_PRINT("Num Root Sequences", prach_fd_occasion->num_root_sequences); + INDENTED_TLV_PRINT("K1", prach_fd_occasion->k1); + INDENTED_TLV_PRINT("PRACH Zero CorrelationZone Config", prach_fd_occasion->prach_zero_corr_conf); + INDENTED_TLV_PRINT("Num Unused Root Sequences", prach_fd_occasion->num_unused_root_sequences); + depth++; + for (int k = 0; k < prach_fd_occasion->num_unused_root_sequences.value; k++) { + INDENTED_TLV_PRINT("Unused Root Sequence", prach_fd_occasion->unused_root_sequences_list[k]); + } + depth--; + } + depth--; + INDENTED_TLV_PRINT("SSB Per RACH", prach_config->ssb_per_rach); + INDENTED_TLV_PRINT("PRACH Multiple Carriers in a Band", prach_config->prach_multiple_carriers_in_a_band); + /* SSB Table */ + const nfapi_nr_ssb_table_t *ssb_table = &msg->ssb_table; + INDENTED_TLV_PRINT("SSB Offset PointA", ssb_table->ssb_offset_point_a); + INDENTED_TLV_PRINT("Beta PSS", ssb_table->beta_pss); + INDENTED_TLV_PRINT("SSB Period", ssb_table->ssb_period); + INDENTED_TLV_PRINT("SSB Subcarrier Offset", ssb_table->ssb_subcarrier_offset); + INDENTED_TLV_PRINT("MIB", ssb_table->MIB); + + INDENTED_PRINTF("SSB Mask:\n"); + depth++; + for (int i = 0; i < 2; i++) { + INDENTED_TLV_PRINT("SSB Mask", ssb_table->ssb_mask_list[i].ssb_mask); + } + depth--; + INDENTED_PRINTF("Beam ID:\n"); + depth++; + for (int i = 0; i < 64; i++) { + INDENTED_TLV_PRINT("Beam ID", ssb_table->ssb_beam_id_list[i].beam_id); + } + depth--; + INDENTED_TLV_PRINT("ssPBCH Multiple Carriers in a Band", ssb_table->ss_pbch_multiple_carriers_in_a_band); + INDENTED_TLV_PRINT("Multiple Cells ssPBCH in a Carrier", ssb_table->multiple_cells_ss_pbch_in_a_carrier); + /* TDD Table */ + const nfapi_nr_tdd_table_t *tdd_table = &msg->tdd_table; + if (cell_config->frame_duplex_type.value == 1 /* TDD */) { + INDENTED_TLV_PRINT("TDD Period", tdd_table->tdd_period); + const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; + // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 + uint8_t cyclicprefix = 1; + // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; + INDENTED_PRINTF("Slot Config:\n"); + depth++; + for (int i = 0; i < slotsperframe[ssb_config->scs_common.value]; i++) { + for (int k = 0; k < number_of_symbols_per_slot; k++) { + const uint8_t slot_type = tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.value; + const char *slot_dir = slot_type == 0 ? "DL" : slot_type == 1 ? "UL" : "S"; + INDENTED_GENERIC_PRINT("(0x%04x) Slot Config", + "%d (%s)", + tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.tl.tag, + slot_type, + slot_dir); + } + } + depth--; + } + /* Measurement Config */ + const nfapi_nr_measurement_config_t *measurement_config = &msg->measurement_config; + INDENTED_TLV_PRINT("RSSI Measurement", measurement_config->rssi_measurement); + /* Beamforming Table */ + const nfapi_nr_dbt_pdu_t *dbt_config = &msg->dbt_config; + INDENTED_PRINTF("Digital Beam Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Digital Beams", "%d", dbt_config->num_dig_beams); + INDENTED_GENERIC_PRINT("Num TX RUs", "%d", dbt_config->num_txrus); + depth++; + 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]; + INDENTED_GENERIC_PRINT("Beam IDX", "%d", dig_beam->beam_idx); + depth++; + for (int k = 0; k < dbt_config->num_txrus; k++) { + const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", tx_ru->dig_beam_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", tx_ru->dig_beam_weight_Im); + } + depth--; + } + depth--; + depth--; + + /* Precoding Table */ + const nfapi_nr_pm_list_t *pmi_list = &msg->pmi_list; + INDENTED_PRINTF("Precoding Matrix Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Precoding Tables", "%d", pmi_list->num_pm_idx); + depth++; + for (int i = 0; i < pmi_list->num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i]; + + INDENTED_GENERIC_PRINT("Precoding Matrix IDX", "0x%02x", pm_pdu->pm_idx); + INDENTED_GENERIC_PRINT("Number of Layers", "%d", pm_pdu->numLayers); + INDENTED_GENERIC_PRINT("Number of Antenna Ports", "%d", pm_pdu->num_ant_ports); + depth++; + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int l = 0; l < pm_pdu->num_ant_ports; l++) { + const nfapi_nr_pm_weights_t *pm_weights = &pm_pdu->weights[k][l]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", pm_weights->precoder_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", pm_weights->precoder_weight_Im); + } + } + depth--; + } + depth--; + depth--; + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); + /* Beamforming VE */ + const nfapi_nr_analog_beamforming_ve_t *analog_beamforming_ve = &msg->analog_beamforming_ve; + INDENTED_TLV_FORMAT_PRINT("Num Beams per Period", "%d", analog_beamforming_ve->num_beams_period_vendor_ext); + INDENTED_TLV_PRINT("Analog Beamforming VE", analog_beamforming_ve->analog_bf_vendor_ext); + /* Vendor Extension */ + if (msg->vendor_extension) { + const nfapi_tl_t *vendor_extension = (nfapi_tl_t *)&msg->vendor_extension; + switch (vendor_extension->tag) { + case VENDOR_EXT_TLV_1_TAG: { + vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + case VENDOR_EXT_TLV_2_TAG: { + vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + default: + break; + } + } + depth--; } diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 93ff5b5f3a..384cf13c2b 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -221,6 +221,21 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->nfapi_config.p7_vnf_port, NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, rand16()); nfapi_resp->num_tlv++; + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG; + for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG; + for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + FILL_TLV(nfapi_resp->nfapi_config.p7_pnf_port, NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, rand16()); + nfapi_resp->num_tlv++; + FILL_TLV(nfapi_resp->nfapi_config.timing_window, NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, rand8()); nfapi_resp->num_tlv++; From 8519c748d1b5454212d81068153b3bc1b4b1231a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 11 Apr 2025 16:54:47 +0100 Subject: [PATCH 3/9] Add pack/unpack for CONFIG.request Beamforming Table Adds the packing and unpacking functions needed for the DBT Table in CONFIG.request This table tag is specified in SCF222.5.0 (0x1043) and this tag is used to transport the table, previous versions did not include a tag for the table. A struct nfapi_nr_dbt_tlv_ve_t is added to represent this TLV in order to be able to use the pack_nr_tlv function. The necessary additions to the utility functions are done to account for this table. The unitary test is changed to fill this table with randomized data to test transport and copy. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 60 ++++++++++++++++++- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 44 ++++++++++++-- .../nfapi/public_inc/nfapi_nr_interface.h | 1 + .../nfapi/public_inc/nfapi_nr_interface_scf.h | 6 ++ nfapi/tests/p5/nr_fapi_config_request_test.c | 19 ++++++ 5 files changed, 124 insertions(+), 6 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 281043b6d3..e66ce48ac0 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -724,6 +724,28 @@ uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void * &pNfapiMsg->vendor_extension)); } +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; +} + 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; @@ -1044,7 +1066,11 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e // END Measurement Config // START Digital Beam Table (DBT) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_dbt_pdu_t, currently unused + 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 @@ -1156,6 +1182,33 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e 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; +} + 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 @@ -1221,6 +1274,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {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_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}, @@ -1268,6 +1322,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * 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_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; 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 52f2ee8031..4df5169d8c 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -259,6 +259,22 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const EQ_TLV(unpacked_req->measurement_config.rssi_measurement, req->measurement_config.rssi_measurement); + EQ(unpacked_req->dbt_config.num_dig_beams, req->dbt_config.num_dig_beams); + + EQ(unpacked_req->dbt_config.num_txrus, req->dbt_config.num_txrus); + + for (int i = 0; i < req->dbt_config.num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *unpacked_dig_beam = &unpacked_req->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *req_dig_beam = &req->dbt_config.dig_beam_list[i]; + EQ(unpacked_dig_beam->beam_idx, req_dig_beam->beam_idx); + for (int k = 0; k < req->dbt_config.num_txrus; ++k) { + const nfapi_nr_txru_t *unpacked_tx_ru = &unpacked_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *req_tx_ru = &req_dig_beam->txru_list[k]; + EQ(unpacked_tx_ru->dig_beam_weight_Re, req_tx_ru->dig_beam_weight_Re); + EQ(unpacked_tx_ru->dig_beam_weight_Im, req_tx_ru->dig_beam_weight_Im); + } + } + EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); @@ -406,9 +422,7 @@ void free_param_response(nfapi_nr_param_response_scf_t *msg) void free_config_request(nfapi_nr_config_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); if (msg->prach_config.num_prach_fd_occasions_list) { for (int i = 0; i < msg->prach_config.num_prach_fd_occasions.value; i++) { @@ -427,10 +441,14 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) free(msg->tdd_table.max_tdd_periodicity_list); } - if (msg->pmi_list.pmi_pdu) { - free(msg->pmi_list.pmi_pdu); + for (int i = 0; i < msg->dbt_config.num_dig_beams; i++) { + free(msg->dbt_config.dig_beam_list[i].txru_list); } + free(msg->dbt_config.dig_beam_list); + + free(msg->pmi_list.pmi_pdu); + if (msg->analog_beamforming_ve.analog_beam_list) { free(msg->analog_beamforming_ve.analog_beam_list); } @@ -807,6 +825,22 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf COPY_TLV(dst->measurement_config.rssi_measurement, src->measurement_config.rssi_measurement); + dst->dbt_config.num_dig_beams = src->dbt_config.num_dig_beams; + dst->dbt_config.num_txrus = src->dbt_config.num_txrus; + dst->dbt_config.dig_beam_list = calloc(dst->dbt_config.num_dig_beams, sizeof(*dst->dbt_config.dig_beam_list)); + for (int i = 0; i < dst->dbt_config.num_dig_beams; i++) { + nfapi_nr_dig_beam_t *dst_dig_beam = &dst->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *src_dig_beam = &src->dbt_config.dig_beam_list[i]; + dst_dig_beam->beam_idx = src_dig_beam->beam_idx; + dst_dig_beam->txru_list = calloc(dst->dbt_config.num_txrus , sizeof(*dst_dig_beam->txru_list )); + for (int k = 0; k < dst->dbt_config.num_txrus; ++k) { + nfapi_nr_txru_t *dst_tx_ru = &dst_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *src_tx_ru = &src_dig_beam->txru_list[k]; + dst_tx_ru->dig_beam_weight_Re = src_tx_ru->dig_beam_weight_Re; + dst_tx_ru->dig_beam_weight_Im = src_tx_ru->dig_beam_weight_Im; + } + } + COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index b7e6577fa2..eb668f3e73 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -34,6 +34,7 @@ #define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002 #define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003 + typedef struct { uint16_t phy_id; uint16_t message_id; 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 0533a76c6d..7af9d07d1c 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 @@ -328,6 +328,7 @@ typedef struct #define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028 #define NFAPI_NR_CONFIG_TDD_TABLE 0x1035 +#define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 ) //table 3-21 typedef struct @@ -473,6 +474,11 @@ typedef struct { nfapi_nr_dig_beam_t *dig_beam_list; } nfapi_nr_dbt_pdu_t; +typedef struct { + nfapi_tl_t tl; + nfapi_nr_dbt_pdu_t value; +} nfapi_nr_dbt_tlv_ve_t; + // Table 3–62 Precoding matrix (PM) PDU (v.222.10.04) typedef struct { int16_t precoder_weight_Re; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 384cf13c2b..7964af55c0 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -206,6 +206,25 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->measurement_config.rssi_measurement, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, rand8()); nfapi_resp->num_tlv++; + uint16_t nb_beams = rand16_range(1, 15); + uint16_t nb_tx = rand16_range(1, 15); + nfapi_resp->dbt_config.num_dig_beams = nb_beams; + if (nfapi_resp->dbt_config.num_dig_beams > 0) { + nfapi_resp->dbt_config.num_txrus = nb_tx; + nfapi_resp->dbt_config.dig_beam_list = calloc(nb_beams , sizeof(*nfapi_resp->dbt_config.dig_beam_list)); + for (int i = 0; i < nb_beams; i++) { + nfapi_nr_dig_beam_t *beam = &nfapi_resp->dbt_config.dig_beam_list[i]; + beam->beam_idx = i; + beam->txru_list = calloc(nb_tx , sizeof(*beam->txru_list)); + for (int j = 0; j < nb_tx; j++) { + nfapi_nr_txru_t *txru = &beam->txru_list[j]; + txru->dig_beam_weight_Re = rand16_range(1, 0xffff); + txru->dig_beam_weight_Im = rand16_range(1, 0xffff); + } + } + nfapi_resp->num_tlv++; + } + nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8(); From 018d456a2a8807de4302538a29516fd23ee87d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:09:46 +0100 Subject: [PATCH 4/9] Add pack/unpack for CONFIG.request Precoding Matrix table Adds the packing and unpacking functions needed for the PM Table in CONFIG.request This table tag is specified in SCF222.10.06(0x104B), previous versions didn't have a tag for this table, and this version of the spec introduces the parameter `num_pm_idx`, previously not present. A struct nfapi_nr_pm_tlv_ve_t is added to represent this TLV in order to be able to use the pack_nr_tlv function. The necessary additions to the utility functions are done to account for this table. The unitary test is changed to fill this table with randomized data to test transport and copy. --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c | 65 ++++++++++++++++++- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 38 +++++++++++ .../nfapi/public_inc/nfapi_nr_interface_scf.h | 8 ++- nfapi/tests/p5/nr_fapi_config_request_test.c | 22 +++++++ 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index e66ce48ac0..6bf2ff37ea 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -746,6 +746,31 @@ static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, u 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; +} + 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; @@ -1074,7 +1099,11 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e // END Digital Beam Table (DBT) PDU // START Precoding Matrix (PM) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL + 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 #ifndef ENABLE_AERIAL // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states @@ -1209,6 +1238,35 @@ static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, 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; +} + 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 @@ -1275,6 +1333,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {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}, @@ -1326,6 +1385,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * 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; 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; 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 4df5169d8c..fc34c66df9 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -275,6 +275,24 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const } } + EQ(unpacked_req->pmi_list.num_pm_idx, req->pmi_list.num_pm_idx); + + for (int i = 0; i < req->pmi_list.num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *req_pmi_pdu = &req->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t *unpacked_pmi_pdu = &unpacked_req->pmi_list.pmi_pdu[i]; + EQ(unpacked_pmi_pdu->pm_idx, req_pmi_pdu->pm_idx); + EQ(unpacked_pmi_pdu->numLayers, req_pmi_pdu->numLayers); + EQ(unpacked_pmi_pdu->num_ant_ports, req_pmi_pdu->num_ant_ports); + for (int j = 0; j < req_pmi_pdu->num_ant_ports; ++j) { + for (int k = 0; k < req_pmi_pdu->num_ant_ports; ++k) { + const nfapi_nr_pm_weights_t* req_pm_weight = &req_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* unpacked_pm_weight = &unpacked_pmi_pdu->weights[j][k]; + EQ(unpacked_pm_weight->precoder_weight_Re, req_pm_weight->precoder_weight_Re); + EQ(unpacked_pm_weight->precoder_weight_Im, req_pm_weight->precoder_weight_Im); + } + } + } + EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); @@ -841,6 +859,26 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf } } + dst->pmi_list.num_pm_idx = src->pmi_list.num_pm_idx; + if (dst->pmi_list.num_pm_idx > 0) { + dst->pmi_list.pmi_pdu = calloc(dst->pmi_list.num_pm_idx , sizeof(*dst->pmi_list.pmi_pdu)); + for (int i = 0; i < dst->pmi_list.num_pm_idx; i++) { + nfapi_nr_pm_pdu_t * dst_pmi_pdu = &dst->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t * src_pmi_pdu = &src->pmi_list.pmi_pdu[i]; + dst_pmi_pdu->pm_idx = src_pmi_pdu->pm_idx; + dst_pmi_pdu->numLayers = src_pmi_pdu->numLayers; + dst_pmi_pdu->num_ant_ports = src_pmi_pdu->num_ant_ports; + for (int j = 0; j < dst_pmi_pdu->numLayers; ++j) { + for (int k = 0; k < dst_pmi_pdu->num_ant_ports; ++k) { + nfapi_nr_pm_weights_t* dst_pm_weight = &dst_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* src_pm_weight = &src_pmi_pdu->weights[j][k]; + dst_pm_weight->precoder_weight_Re = src_pm_weight->precoder_weight_Re; + dst_pm_weight->precoder_weight_Im = src_pm_weight->precoder_weight_Im; + } + } + } + } + COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, 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 7af9d07d1c..f213868328 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 @@ -329,6 +329,7 @@ typedef struct #define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028 #define NFAPI_NR_CONFIG_TDD_TABLE 0x1035 #define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 ) +#define NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG 0x104B // This tag was added in version 6 of the SCF222 standard ( Table 3-52 of SCF222.10.06 ) //table 3-21 typedef struct @@ -497,7 +498,12 @@ typedef struct { typedef struct { uint16_t num_pm_idx; nfapi_nr_pm_pdu_t *pmi_pdu; -} nfapi_nr_pm_list_t; +} nfapi_nr_pm_list_t; // This corresponds to Table 3-69 of SCF222.10.06, which introduces the num_pm_idx parameter + +typedef struct { + nfapi_tl_t tl; + nfapi_nr_pm_list_t value; +} nfapi_nr_pm_tlv_ve_t; typedef struct { nfapi_uint8_tlv_t num_beams_period_vendor_ext; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 7964af55c0..82ce60ca3b 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -225,6 +225,28 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap nfapi_resp->num_tlv++; } + nfapi_nr_pm_list_t *pm_list = &nfapi_resp->pmi_list; + const uint16_t num_layers = rand16_range(1, 4); + const uint16_t num_ant_ports = rand16_range(1, 4); + pm_list->num_pm_idx = rand16_range(1, 4); + if (nfapi_resp->pmi_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 *pmi_pdu = &pm_list->pmi_pdu[i]; + pmi_pdu->pm_idx = i+1; + pmi_pdu->numLayers = num_layers; + pmi_pdu->num_ant_ports = num_ant_ports; + for (int j = 0; j < num_layers; j++) { + for (int k = 0; k < num_ant_ports; k++) { + nfapi_nr_pm_weights_t* pm_weight = &pmi_pdu->weights[j][k]; + pm_weight->precoder_weight_Re = (int16_t)rand16_range(1, 0xffff); + pm_weight->precoder_weight_Im = (int16_t)rand16_range(1, 0xffff); + } + } + } + nfapi_resp->num_tlv++; + } + nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8(); From d3205ea09a451e98e52307905fab689072932220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:31:26 +0100 Subject: [PATCH 5/9] Finish dump procedure for CONFIG.response message Remove unnecessary checks on free_config_response --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 65 +++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-) 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 fc34c66df9..6b238dd69d 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -474,25 +474,15 @@ 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); - } + free(msg->vendor_extension); - if (msg->invalid_tlvs_list) { - free(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); - } + free(msg->invalid_tlvs_configured_in_idle_list); - if (msg->invalid_tlvs_configured_in_running_list) { - free(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); - } + free(msg->missing_tlvs_list); } void free_start_request(nfapi_nr_start_request_scf_t *msg) @@ -1407,6 +1397,32 @@ void dump_config_request(const nfapi_nr_config_request_scf_t *msg) depth--; } +static void dump_generic_tlv(const nfapi_nr_generic_tlv_scf_t* tlv, int depth) +{ + INDENTED_PRINTF("TLV tag 0x%02x , Length 0x%02x , Value ", tlv->tl.tag, tlv->tl.length); + switch (tlv->tl.length) { + case UINT_8: + printf("0x%x\n", tlv->value.u8); + break; + case UINT_16: + printf("0x%02x\n", tlv->value.u16); + break; + case UINT_32: + printf("0x%04x\n", tlv->value.u32); + break; + case ARRAY_UINT_16: + for (int i = 0; i< 5 ; i++) { + printf("0x%04x ", tlv->value.array_u16[i]); + } + printf("\n"); + break; + default: + printf("unknown length %d\n", tlv->tl.length); + DevAssert(1 == 0); + break; + } +} + void dump_config_response(const nfapi_nr_config_response_scf_t *msg) { int depth = 0; @@ -1419,6 +1435,25 @@ void dump_config_response(const nfapi_nr_config_response_scf_t *msg) msg->num_invalid_tlvs_configured_in_running); INDENTED_PRINTF("Number of Missing TLVs = 0x%02x\n", msg->num_missing_tlvs); /* dump all TLVs from each table */ + INDENTED_PRINTF("Invalid or Unsupported TLVs (%d) :\n",msg->num_invalid_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in IDLE (%d):\n", msg->num_invalid_tlvs_configured_in_idle); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in RUNNING (%d):\n",msg->num_invalid_tlvs_configured_in_running); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("Missing TLVs (%d):\n",msg->num_missing_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } depth--; } From c9835a13e7b5fec65f8e5a0f2495eb804367ec1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 10:36:31 +0100 Subject: [PATCH 6/9] Finish dump procedure for TX_DATA.request message --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index 9939a6f535..14846d6f5b 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -2586,6 +2586,27 @@ void dump_ul_dci_request(const nfapi_nr_ul_dci_request_t *msg) } } +static void dump_tx_data_request_tlv(const nfapi_nr_tx_data_request_tlv_t *tlv, int depth) +{ + INDENTED_PRINTF("Tag = %d\n", tlv->tag); + INDENTED_PRINTF("Length = %d\n", tlv->length); + INDENTED_PRINTF("Value = "); + switch (tlv->tag) { + case 0: + for (int i = 0; i < tlv->length; i++) { + printf("0x%02x ", ((uint8_t*)tlv->value.direct)[i]); + } + break; + case 1: + printf("%p", tlv->value.ptr); + break; + default: + printf( " Unknown tag value %d",tlv->tag); + break; + } + printf("\n"); +} + void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) { int depth = 0; @@ -2594,15 +2615,18 @@ void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) INDENTED_PRINTF("SFN = %d\n", msg->SFN); INDENTED_PRINTF("Slot = %d\n", msg->Slot); INDENTED_PRINTF("Number of PDUs = %d\n", msg->Number_of_PDUs); + depth++; for (int i = 0; i < msg->Number_of_PDUs; i++) { - depth++; INDENTED_PRINTF("PDU #%d\n", i); const nfapi_nr_pdu_t *pdu = &msg->pdu_list[i]; INDENTED_PRINTF("PDU Length = 0x%02x\n", pdu->PDU_length); INDENTED_PRINTF("PDU Index = 0x%02x\n", pdu->PDU_index); INDENTED_PRINTF("numTLV = 0x%02x\n", pdu->num_TLV); + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; tlv_idx++) { + const nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; /* call to dump_tx_data_request_tlv */ - depth--; + dump_tx_data_request_tlv(tlv, depth + 1); + } } } From 923cfc9cd2e7a7960639f3bb0da31eabc78b2837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 22 May 2025 11:14:21 +0100 Subject: [PATCH 7/9] Finish dump procedure for UCI.indication message Remove unnecessary checks on free_uci_indication --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 246 ++++++++++++++----- 1 file changed, 186 insertions(+), 60 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index 14846d6f5b..bf99375203 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -930,72 +930,56 @@ void free_crc_indication(nfapi_nr_crc_indication_t *msg) void free_uci_indication(nfapi_nr_uci_indication_t *msg) { - if (msg->uci_list) { - for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { - nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; - switch (uci_pdu->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { - nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; - // Bit 0 not used in PUSCH PDU - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { + nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; + switch (uci_pdu->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; + // Bit 0 not used in PUSCH PDU + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - // Nothing to free - break; + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; - // SR - if (pdu->pduBitmap & 0x01) { - if (pdu->sr.sr_payload) { - free(pdu->sr.sr_payload); - } - } - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); } - default: - AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); - break; + break; } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + // Nothing to free + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; + // SR + if (pdu->pduBitmap & 0x01) { + free(pdu->sr.sr_payload); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); + } + break; + } + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); + break; } - free(msg->uci_list); } + free(msg->uci_list); } void free_srs_indication(nfapi_nr_srs_indication_t *msg) @@ -2688,6 +2672,134 @@ void dump_crc_indication(const nfapi_nr_crc_indication_t *msg) } } +static void dump_harq_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *harq, int depth) +{ + INDENTED_PRINTF("HARQ CRC = %01x\n", harq->harq_crc); + INDENTED_PRINTF("HARQ Bit Length = %d\n", harq->harq_bit_len); + INDENTED_PRINTF("HARQ Payload = "); + for (int i = 0; i < harq->harq_bit_len / 8 + 1; i++) { + printf("%x ", harq->harq_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_1(const nfapi_nr_csi_part1_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part1_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part1_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part1_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part1_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_2(const nfapi_nr_csi_part2_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part2_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part2_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part2_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part2_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUSCH_PDU(const nfapi_nr_uci_pusch_pdu_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // HARQ payload, CSI Part 1 and 2 are conditionally allocated + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + if ((pdu->pduBitmap >> 2) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + if ((pdu->pduBitmap >> 3) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + +static void dump_sr_0_1(const nfapi_nr_sr_pdu_0_1_t *sr, int depth) +{ + INDENTED_PRINTF("SR Indication = 0x%02x\n", sr->sr_indication); + INDENTED_PRINTF("SR Confidence Level = 0x%02x\n", sr->sr_confidence_level); +} + +static void dump_harq_0_1(const nfapi_nr_harq_pdu_0_1_t *harq, int depth) +{ + INDENTED_PRINTF("Num HARQ = 0x%02x\n", harq->num_harq); + INDENTED_PRINTF("HARQ Confidence Level = 0x%02x\n", harq->harq_confidence_level); + depth++; + for (int i = 0; i < harq->num_harq; i++) { + INDENTED_PRINTF("HARQ Value[%d] : 0x%02x \n", i, harq->harq_list[i].harq_value); + } +} + +static void dump_uci_PUCCH_0_1(const nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + if ((pdu->pduBitmap) & 0x01) { + INDENTED_PRINTF("SR Information\n"); + dump_sr_0_1(&pdu->sr, depth + 1); + } + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_0_1(&pdu->harq, depth + 1); + } +} + +static void dump_sr_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *sr, int depth) +{ + INDENTED_PRINTF("SR Bit Length = %d\n", sr->sr_bit_len); + INDENTED_PRINTF("SR Payload "); + for (int i = 0; i < sr->sr_bit_len / 8 + 1; i++) { + printf("%x ", sr->sr_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUCCH_2_3_4(const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // SR + if (pdu->pduBitmap & 0x01) { + dump_sr_2_3_4(&pdu->sr, depth + 1); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) { int depth = 0; @@ -2704,6 +2816,20 @@ void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) INDENTED_PRINTF("PDUType = 0x%02x\n", uci->pdu_type); INDENTED_PRINTF("PDUSize = 0x%02x\n", uci->pdu_size); /* call to dump_uci_indication__pdu */ + switch (uci->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + dump_uci_PUSCH_PDU(&uci->pusch_pdu, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + dump_uci_PUCCH_0_1(&uci->pucch_pdu_format_0_1, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + dump_uci_PUCCH_2_3_4(&uci->pucch_pdu_format_2_3_4, depth + 1); + break; + default: + INDENTED_PRINTF("Unknown PDU type 0x%02x\n", uci->pdu_type); + break; + } depth--; } } From 625fd54ae25e14e733f8069a1cb9cbfec3a886a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 12 Jun 2025 13:14:08 +0100 Subject: [PATCH 8/9] Remove unnecessary checks on P5 free utility functions --- nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c | 24 +++++--------------- 1 file changed, 6 insertions(+), 18 deletions(-) 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 6b238dd69d..4c3f32ef27 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -425,9 +425,7 @@ bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, co void free_param_request(nfapi_nr_param_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_param_response(nfapi_nr_param_response_scf_t *msg) @@ -487,37 +485,27 @@ void free_config_response(nfapi_nr_config_response_scf_t *msg) void free_start_request(nfapi_nr_start_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_start_response(nfapi_nr_start_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_request(nfapi_nr_stop_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_error_indication(nfapi_nr_error_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst) From ba4608d46b79a3fdc02553d37288de15d5b41baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Thu, 12 Jun 2025 13:15:47 +0100 Subject: [PATCH 9/9] Remove unnecessary checks on P7 free utility functions --- nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c | 28 ++++++-------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index bf99375203..fb645707ad 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -859,9 +859,7 @@ bool eq_rach_indication(const nfapi_nr_rach_indication_t *a, const nfapi_nr_rach void free_dl_tti_request(nfapi_nr_dl_tti_request_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_ul_tti_request(nfapi_nr_ul_tti_request_t *msg) @@ -907,9 +905,7 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) if (msg->number_of_pdus > 0) { for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { nfapi_nr_rx_data_pdu_t *rx_pdu = &msg->pdu_list[pdu_idx]; - if (rx_pdu->pdu) { - free(rx_pdu->pdu); - } + free(rx_pdu->pdu); } free(msg->pdu_list); } @@ -917,15 +913,11 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) void free_crc_indication(nfapi_nr_crc_indication_t *msg) { - if (msg->crc_list) { - for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { - nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; - if (crc->cb_crc_status) { - free(crc->cb_crc_status); - } - } - free(msg->crc_list); + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; + free(crc->cb_crc_status); } + free(msg->crc_list); } void free_uci_indication(nfapi_nr_uci_indication_t *msg) @@ -984,16 +976,12 @@ void free_uci_indication(nfapi_nr_uci_indication_t *msg) void free_srs_indication(nfapi_nr_srs_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } void free_rach_indication(nfapi_nr_rach_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } static void copy_dl_tti_beamforming(const nfapi_nr_tx_precoding_and_beamforming_t *src,