/* * 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_p5_utils.h" bool eq_param_request(const nfapi_nr_param_request_scf_t *unpacked_req, const nfapi_nr_param_request_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); return true; } bool eq_param_response(const nfapi_nr_param_response_scf_t *unpacked_req, const nfapi_nr_param_response_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); EQ(unpacked_req->num_tlv, req->num_tlv); EQ(unpacked_req->error_code, req->error_code); EQ_TLV(unpacked_req->cell_param.release_capability, req->cell_param.release_capability); EQ_TLV(unpacked_req->cell_param.phy_state, req->cell_param.phy_state); EQ_TLV(unpacked_req->cell_param.skip_blank_dl_config, req->cell_param.skip_blank_dl_config); EQ_TLV(unpacked_req->cell_param.skip_blank_ul_config, req->cell_param.skip_blank_ul_config); EQ_TLV(unpacked_req->cell_param.num_config_tlvs_to_report, req->cell_param.num_config_tlvs_to_report); for (int i = 0; i < unpacked_req->cell_param.num_config_tlvs_to_report.value; ++i) { EQ_TLV(unpacked_req->cell_param.config_tlvs_to_report_list[i], req->cell_param.config_tlvs_to_report_list[i]); } EQ_TLV(unpacked_req->carrier_param.cyclic_prefix, req->carrier_param.cyclic_prefix); EQ_TLV(unpacked_req->carrier_param.supported_subcarrier_spacings_dl, req->carrier_param.supported_subcarrier_spacings_dl); EQ_TLV(unpacked_req->carrier_param.supported_bandwidth_dl, req->carrier_param.supported_bandwidth_dl); EQ_TLV(unpacked_req->carrier_param.supported_subcarrier_spacings_ul, req->carrier_param.supported_subcarrier_spacings_ul); EQ_TLV(unpacked_req->carrier_param.supported_bandwidth_ul, req->carrier_param.supported_bandwidth_ul); EQ_TLV(unpacked_req->pdcch_param.cce_mapping_type, req->pdcch_param.cce_mapping_type); EQ_TLV(unpacked_req->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot, req->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot); EQ_TLV(unpacked_req->pdcch_param.coreset_precoder_granularity_coreset, req->pdcch_param.coreset_precoder_granularity_coreset); EQ_TLV(unpacked_req->pdcch_param.pdcch_mu_mimo, req->pdcch_param.pdcch_mu_mimo); EQ_TLV(unpacked_req->pdcch_param.pdcch_precoder_cycling, req->pdcch_param.pdcch_precoder_cycling); EQ_TLV(unpacked_req->pdcch_param.max_pdcch_per_slot, req->pdcch_param.max_pdcch_per_slot); EQ_TLV(unpacked_req->pucch_param.pucch_formats, req->pucch_param.pucch_formats); EQ_TLV(unpacked_req->pucch_param.max_pucchs_per_slot, req->pucch_param.max_pucchs_per_slot); EQ_TLV(unpacked_req->pdsch_param.pdsch_mapping_type, req->pdsch_param.pdsch_mapping_type); EQ_TLV(unpacked_req->pdsch_param.pdsch_allocation_types, req->pdsch_param.pdsch_allocation_types); EQ_TLV(unpacked_req->pdsch_param.pdsch_vrb_to_prb_mapping, req->pdsch_param.pdsch_vrb_to_prb_mapping); EQ_TLV(unpacked_req->pdsch_param.pdsch_cbg, req->pdsch_param.pdsch_cbg); EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_config_types, req->pdsch_param.pdsch_dmrs_config_types); EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_max_length, req->pdsch_param.pdsch_dmrs_max_length); EQ_TLV(unpacked_req->pdsch_param.pdsch_dmrs_additional_pos, req->pdsch_param.pdsch_dmrs_additional_pos); EQ_TLV(unpacked_req->pdsch_param.max_pdsch_tbs_per_slot, req->pdsch_param.max_pdsch_tbs_per_slot); EQ_TLV(unpacked_req->pdsch_param.max_number_mimo_layers_pdsch, req->pdsch_param.max_number_mimo_layers_pdsch); EQ_TLV(unpacked_req->pdsch_param.supported_max_modulation_order_dl, req->pdsch_param.supported_max_modulation_order_dl); EQ_TLV(unpacked_req->pdsch_param.max_mu_mimo_users_dl, req->pdsch_param.max_mu_mimo_users_dl); EQ_TLV(unpacked_req->pdsch_param.pdsch_data_in_dmrs_symbols, req->pdsch_param.pdsch_data_in_dmrs_symbols); EQ_TLV(unpacked_req->pdsch_param.premption_support, req->pdsch_param.premption_support); EQ_TLV(unpacked_req->pdsch_param.pdsch_non_slot_support, req->pdsch_param.pdsch_non_slot_support); EQ_TLV(unpacked_req->pusch_param.uci_mux_ulsch_in_pusch, req->pusch_param.uci_mux_ulsch_in_pusch); EQ_TLV(unpacked_req->pusch_param.uci_only_pusch, req->pusch_param.uci_only_pusch); EQ_TLV(unpacked_req->pusch_param.pusch_frequency_hopping, req->pusch_param.pusch_frequency_hopping); EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_config_types, req->pusch_param.pusch_dmrs_config_types); EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_max_len, req->pusch_param.pusch_dmrs_max_len); EQ_TLV(unpacked_req->pusch_param.pusch_dmrs_additional_pos, req->pusch_param.pusch_dmrs_additional_pos); EQ_TLV(unpacked_req->pusch_param.pusch_cbg, req->pusch_param.pusch_cbg); EQ_TLV(unpacked_req->pusch_param.pusch_mapping_type, req->pusch_param.pusch_mapping_type); EQ_TLV(unpacked_req->pusch_param.pusch_allocation_types, req->pusch_param.pusch_allocation_types); EQ_TLV(unpacked_req->pusch_param.pusch_vrb_to_prb_mapping, req->pusch_param.pusch_vrb_to_prb_mapping); EQ_TLV(unpacked_req->pusch_param.pusch_max_ptrs_ports, req->pusch_param.pusch_max_ptrs_ports); EQ_TLV(unpacked_req->pusch_param.max_pduschs_tbs_per_slot, req->pusch_param.max_pduschs_tbs_per_slot); EQ_TLV(unpacked_req->pusch_param.max_number_mimo_layers_non_cb_pusch, req->pusch_param.max_number_mimo_layers_non_cb_pusch); EQ_TLV(unpacked_req->pusch_param.supported_modulation_order_ul, req->pusch_param.supported_modulation_order_ul); EQ_TLV(unpacked_req->pusch_param.max_mu_mimo_users_ul, req->pusch_param.max_mu_mimo_users_ul); EQ_TLV(unpacked_req->pusch_param.dfts_ofdm_support, req->pusch_param.dfts_ofdm_support); EQ_TLV(unpacked_req->pusch_param.pusch_aggregation_factor, req->pusch_param.pusch_aggregation_factor); EQ_TLV(unpacked_req->prach_param.prach_long_formats, req->prach_param.prach_long_formats); EQ_TLV(unpacked_req->prach_param.prach_short_formats, req->prach_param.prach_short_formats); EQ_TLV(unpacked_req->prach_param.prach_restricted_sets, req->prach_param.prach_restricted_sets); EQ_TLV(unpacked_req->prach_param.max_prach_fd_occasions_in_a_slot, req->prach_param.max_prach_fd_occasions_in_a_slot); EQ_TLV(unpacked_req->measurement_param.rssi_measurement_support, req->measurement_param.rssi_measurement_support); return true; } bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const nfapi_nr_config_request_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); EQ(unpacked_req->num_tlv, req->num_tlv); EQ_TLV(unpacked_req->carrier_config.dl_bandwidth, req->carrier_config.dl_bandwidth); EQ_TLV(unpacked_req->carrier_config.dl_frequency, req->carrier_config.dl_frequency); for (int i = 0; i < 5; ++i) { EQ_TLV(unpacked_req->carrier_config.dl_k0[i], req->carrier_config.dl_k0[i]); EQ_TLV(unpacked_req->carrier_config.dl_grid_size[i], req->carrier_config.dl_grid_size[i]); } EQ_TLV(unpacked_req->carrier_config.num_tx_ant, req->carrier_config.num_tx_ant); EQ_TLV(unpacked_req->carrier_config.uplink_bandwidth, req->carrier_config.uplink_bandwidth); EQ_TLV(unpacked_req->carrier_config.uplink_frequency, req->carrier_config.uplink_frequency); for (int i = 0; i < 5; ++i) { EQ_TLV(unpacked_req->carrier_config.ul_k0[i], req->carrier_config.ul_k0[i]); EQ_TLV(unpacked_req->carrier_config.ul_grid_size[i], req->carrier_config.ul_grid_size[i]); } EQ_TLV(unpacked_req->carrier_config.num_rx_ant, req->carrier_config.num_rx_ant); EQ_TLV(unpacked_req->carrier_config.frequency_shift_7p5khz, req->carrier_config.frequency_shift_7p5khz); EQ_TLV(unpacked_req->cell_config.phy_cell_id, req->cell_config.phy_cell_id); EQ_TLV(unpacked_req->cell_config.frame_duplex_type, req->cell_config.frame_duplex_type); EQ_TLV(unpacked_req->ssb_config.ss_pbch_power, req->ssb_config.ss_pbch_power); EQ_TLV(unpacked_req->ssb_config.bch_payload, req->ssb_config.bch_payload); EQ_TLV(unpacked_req->ssb_config.scs_common, req->ssb_config.scs_common); EQ_TLV(unpacked_req->prach_config.prach_sequence_length, req->prach_config.prach_sequence_length); EQ_TLV(unpacked_req->prach_config.prach_sub_c_spacing, req->prach_config.prach_sub_c_spacing); EQ_TLV(unpacked_req->prach_config.restricted_set_config, req->prach_config.restricted_set_config); EQ_TLV(unpacked_req->prach_config.num_prach_fd_occasions, req->prach_config.num_prach_fd_occasions); EQ_TLV(unpacked_req->prach_config.prach_ConfigurationIndex, req->prach_config.prach_ConfigurationIndex); for (int i = 0; i < unpacked_req->prach_config.num_prach_fd_occasions.value; i++) { nfapi_nr_num_prach_fd_occasions_t unpacked_prach_fd_occasion = unpacked_req->prach_config.num_prach_fd_occasions_list[i]; nfapi_nr_num_prach_fd_occasions_t req_prach_fd_occasion = req->prach_config.num_prach_fd_occasions_list[i]; EQ_TLV(unpacked_prach_fd_occasion.prach_root_sequence_index, req_prach_fd_occasion.prach_root_sequence_index); EQ_TLV(unpacked_prach_fd_occasion.num_root_sequences, req_prach_fd_occasion.num_root_sequences); EQ_TLV(unpacked_prach_fd_occasion.k1, req_prach_fd_occasion.k1); EQ_TLV(unpacked_prach_fd_occasion.prach_zero_corr_conf, req_prach_fd_occasion.prach_zero_corr_conf); EQ_TLV(unpacked_prach_fd_occasion.num_unused_root_sequences, req_prach_fd_occasion.num_unused_root_sequences); for (int k = 0; k < unpacked_prach_fd_occasion.num_unused_root_sequences.value; k++) { EQ_TLV(unpacked_prach_fd_occasion.unused_root_sequences_list[k], req_prach_fd_occasion.unused_root_sequences_list[k]); } } EQ_TLV(unpacked_req->prach_config.ssb_per_rach, req->prach_config.ssb_per_rach); EQ_TLV(unpacked_req->prach_config.prach_multiple_carriers_in_a_band, req->prach_config.prach_multiple_carriers_in_a_band); EQ_TLV(unpacked_req->ssb_table.ssb_offset_point_a, req->ssb_table.ssb_offset_point_a); EQ_TLV(unpacked_req->ssb_table.beta_pss, req->ssb_table.beta_pss); EQ_TLV(unpacked_req->ssb_table.ssb_period, req->ssb_table.ssb_period); EQ_TLV(unpacked_req->ssb_table.ssb_subcarrier_offset, req->ssb_table.ssb_subcarrier_offset); EQ_TLV(unpacked_req->ssb_table.MIB, req->ssb_table.MIB); EQ_TLV(unpacked_req->ssb_table.ssb_mask_list[0].ssb_mask, req->ssb_table.ssb_mask_list[0].ssb_mask); EQ_TLV(unpacked_req->ssb_table.ssb_mask_list[1].ssb_mask, req->ssb_table.ssb_mask_list[1].ssb_mask); for (int i = 0; i < 64; i++) { EQ_TLV(unpacked_req->ssb_table.ssb_beam_id_list[i].beam_id, req->ssb_table.ssb_beam_id_list[i].beam_id); } EQ_TLV(unpacked_req->ssb_table.case_v3, req->ssb_table.case_v3); if (req->cell_config.frame_duplex_type.value == 1 /* TDD */) { EQ_TLV(unpacked_req->tdd_table.tdd_period, req->tdd_table.tdd_period); const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; for (int i = 0; i < slotsperframe[unpacked_req->ssb_config.scs_common.value]; i++) { for (int k = 0; k < number_of_symbols_per_slot; k++) { EQ_TLV(unpacked_req->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config, req->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config); } } } EQ_TLV(unpacked_req->measurement_config.rssi_measurement, req->measurement_config.rssi_measurement); EQ(unpacked_req->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->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->r, req_pm_weight->r); EQ(unpacked_pm_weight->i, req_pm_weight->i); } } } EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); } EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv6.tl.tag, req->nfapi_config.p7_vnf_address_ipv6.tl.tag); for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv6.address[i], req->nfapi_config.p7_vnf_address_ipv6.address[i]); } EQ_TLV(unpacked_req->nfapi_config.p7_vnf_port, req->nfapi_config.p7_vnf_port); EQ_TLV(unpacked_req->nfapi_config.timing_window, req->nfapi_config.timing_window); EQ_TLV(unpacked_req->nfapi_config.timing_info_mode, req->nfapi_config.timing_info_mode); EQ_TLV(unpacked_req->nfapi_config.timing_info_period, req->nfapi_config.timing_info_period); EQ_TLV(unpacked_req->analog_beamforming_ve.num_beams_period_vendor_ext, req->analog_beamforming_ve.num_beams_period_vendor_ext); EQ_TLV(unpacked_req->analog_beamforming_ve.analog_bf_vendor_ext, req->analog_beamforming_ve.analog_bf_vendor_ext); return true; } static bool eq_config_response_tlv_lists(nfapi_nr_generic_tlv_scf_t *unpacked_list, nfapi_nr_generic_tlv_scf_t *req_list, uint8_t size) { for (int i = 0; i < size; ++i) { nfapi_nr_generic_tlv_scf_t *unpacked_element = &(unpacked_list[i]); nfapi_nr_generic_tlv_scf_t *req_element = &(req_list[i]); EQ(unpacked_element->tl.tag, req_element->tl.tag); EQ(unpacked_element->tl.length, req_element->tl.length); // check according to value type switch (unpacked_element->tl.length) { case UINT_8: EQ(unpacked_element->value.u8, req_element->value.u8); break; case UINT_16: EQ(unpacked_element->value.u16, req_element->value.u16); break; case UINT_32: EQ(unpacked_element->value.u32, req_element->value.u32); break; case ARRAY_UINT_16: for (int j = 0; j < 5; ++j) { EQ(unpacked_element->value.array_u16[j], req_element->value.array_u16[j]); } break; default: printf("unknown length %d\n", unpacked_element->tl.length); DevAssert(1 == 0); break; } } return true; } bool eq_config_response(const nfapi_nr_config_response_scf_t *unpacked_req, const nfapi_nr_config_response_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); EQ(unpacked_req->error_code, req->error_code); EQ(unpacked_req->num_invalid_tlvs, req->num_invalid_tlvs); EQ(unpacked_req->num_invalid_tlvs_configured_in_idle, req->num_invalid_tlvs_configured_in_idle); EQ(unpacked_req->num_invalid_tlvs_configured_in_running, req->num_invalid_tlvs_configured_in_running); EQ(unpacked_req->num_missing_tlvs, req->num_missing_tlvs); // compare the list elements EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_list, req->invalid_tlvs_list, req->num_invalid_tlvs), true); EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_idle_list, req->invalid_tlvs_configured_in_idle_list, req->num_invalid_tlvs_configured_in_idle), true); EQ(eq_config_response_tlv_lists(unpacked_req->invalid_tlvs_configured_in_running_list, req->invalid_tlvs_configured_in_running_list, req->num_invalid_tlvs_configured_in_running), true); EQ(eq_config_response_tlv_lists(unpacked_req->missing_tlvs_list, req->missing_tlvs_list, req->num_missing_tlvs), true); return true; } bool eq_start_request(const nfapi_nr_start_request_scf_t *unpacked_req, const nfapi_nr_start_request_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); return true; } bool eq_start_response(const nfapi_nr_start_response_scf_t *unpacked_req, const nfapi_nr_start_response_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); EQ(unpacked_req->error_code, req->error_code); return true; } bool eq_stop_request(const nfapi_nr_stop_request_scf_t *unpacked_req, const nfapi_nr_stop_request_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); return true; } bool eq_stop_indication(const nfapi_nr_stop_indication_scf_t *unpacked_req, const nfapi_nr_stop_indication_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); return true; } bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, const nfapi_nr_error_indication_scf_t *req) { EQ(unpacked_req->header.message_id, req->header.message_id); EQ(unpacked_req->header.message_length, req->header.message_length); EQ(unpacked_req->sfn, req->sfn); EQ(unpacked_req->slot, req->slot); EQ(unpacked_req->message_id, req->message_id); EQ(unpacked_req->error_code, req->error_code); return true; } void free_param_request(nfapi_nr_param_request_scf_t *msg) { free(msg->vendor_extension); } void free_param_response(nfapi_nr_param_response_scf_t *msg) { free(msg->vendor_extension); free(msg->cell_param.config_tlvs_to_report_list); } void free_config_request(nfapi_nr_config_request_scf_t *msg) { free(msg->vendor_extension); if (msg->prach_config.num_prach_fd_occasions_list) { for (int i = 0; i < msg->prach_config.num_prach_fd_occasions.value; i++) { nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(msg->prach_config.num_prach_fd_occasions_list[i]); if (prach_fd_occasion->unused_root_sequences_list) { free(prach_fd_occasion->unused_root_sequences_list); } } free(msg->prach_config.num_prach_fd_occasions_list); } const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; if (msg->tdd_table.max_tdd_periodicity_list) { for (int i = 0; i < slotsperframe[msg->ssb_config.scs_common.value]; i++) { free(msg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list); } free(msg->tdd_table.max_tdd_periodicity_list); } 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); } void free_config_response(nfapi_nr_config_response_scf_t *msg) { free(msg->vendor_extension); free(msg->invalid_tlvs_list); free(msg->invalid_tlvs_configured_in_idle_list); free(msg->invalid_tlvs_configured_in_running_list); free(msg->missing_tlvs_list); } void free_start_request(nfapi_nr_start_request_scf_t *msg) { free(msg->vendor_extension); } void free_start_response(nfapi_nr_start_response_scf_t *msg) { free(msg->vendor_extension); } void free_stop_request(nfapi_nr_stop_request_scf_t *msg) { free(msg->vendor_extension); } void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg) { free(msg->vendor_extension); } void free_error_indication(nfapi_nr_error_indication_scf_t *msg) { free(msg->vendor_extension); } void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } } void copy_param_response(const nfapi_nr_param_response_scf_t *src, nfapi_nr_param_response_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } dst->error_code = src->error_code; dst->num_tlv = src->num_tlv; COPY_TLV(dst->cell_param.release_capability, src->cell_param.release_capability); COPY_TLV(dst->cell_param.phy_state, src->cell_param.phy_state); COPY_TLV(dst->cell_param.skip_blank_dl_config, src->cell_param.skip_blank_dl_config); COPY_TLV(dst->cell_param.skip_blank_ul_config, src->cell_param.skip_blank_ul_config); COPY_TLV(dst->cell_param.num_config_tlvs_to_report, src->cell_param.num_config_tlvs_to_report); if (src->cell_param.config_tlvs_to_report_list) { dst->cell_param.config_tlvs_to_report_list = calloc(src->cell_param.num_config_tlvs_to_report.value, sizeof(nfapi_uint8_tlv_t *)); for (int i = 0; i < src->cell_param.num_config_tlvs_to_report.value; ++i) { COPY_TLV(dst->cell_param.config_tlvs_to_report_list[i], src->cell_param.config_tlvs_to_report_list[i]); } } COPY_TLV(dst->carrier_param.cyclic_prefix, src->carrier_param.cyclic_prefix); COPY_TLV(dst->carrier_param.supported_subcarrier_spacings_dl, src->carrier_param.supported_subcarrier_spacings_dl); COPY_TLV(dst->carrier_param.supported_bandwidth_dl, src->carrier_param.supported_bandwidth_dl); COPY_TLV(dst->carrier_param.supported_subcarrier_spacings_ul, src->carrier_param.supported_subcarrier_spacings_ul); COPY_TLV(dst->carrier_param.supported_bandwidth_ul, src->carrier_param.supported_bandwidth_ul); COPY_TLV(dst->pdcch_param.cce_mapping_type, src->pdcch_param.cce_mapping_type); COPY_TLV(dst->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot, src->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot); COPY_TLV(dst->pdcch_param.coreset_precoder_granularity_coreset, src->pdcch_param.coreset_precoder_granularity_coreset); COPY_TLV(dst->pdcch_param.pdcch_mu_mimo, src->pdcch_param.pdcch_mu_mimo); COPY_TLV(dst->pdcch_param.pdcch_precoder_cycling, src->pdcch_param.pdcch_precoder_cycling); COPY_TLV(dst->pdcch_param.max_pdcch_per_slot, src->pdcch_param.max_pdcch_per_slot); COPY_TLV(dst->pucch_param.pucch_formats, src->pucch_param.pucch_formats); COPY_TLV(dst->pucch_param.max_pucchs_per_slot, src->pucch_param.max_pucchs_per_slot); COPY_TLV(dst->pdsch_param.pdsch_mapping_type, src->pdsch_param.pdsch_mapping_type); COPY_TLV(dst->pdsch_param.pdsch_allocation_types, src->pdsch_param.pdsch_allocation_types); COPY_TLV(dst->pdsch_param.pdsch_vrb_to_prb_mapping, src->pdsch_param.pdsch_vrb_to_prb_mapping); COPY_TLV(dst->pdsch_param.pdsch_cbg, src->pdsch_param.pdsch_cbg); COPY_TLV(dst->pdsch_param.pdsch_dmrs_config_types, src->pdsch_param.pdsch_dmrs_config_types); COPY_TLV(dst->pdsch_param.pdsch_dmrs_max_length, src->pdsch_param.pdsch_dmrs_max_length); COPY_TLV(dst->pdsch_param.pdsch_dmrs_additional_pos, src->pdsch_param.pdsch_dmrs_additional_pos); COPY_TLV(dst->pdsch_param.max_pdsch_tbs_per_slot, src->pdsch_param.max_pdsch_tbs_per_slot); COPY_TLV(dst->pdsch_param.max_number_mimo_layers_pdsch, src->pdsch_param.max_number_mimo_layers_pdsch); COPY_TLV(dst->pdsch_param.supported_max_modulation_order_dl, src->pdsch_param.supported_max_modulation_order_dl); COPY_TLV(dst->pdsch_param.max_mu_mimo_users_dl, src->pdsch_param.max_mu_mimo_users_dl); COPY_TLV(dst->pdsch_param.pdsch_data_in_dmrs_symbols, src->pdsch_param.pdsch_data_in_dmrs_symbols); COPY_TLV(dst->pdsch_param.premption_support, src->pdsch_param.premption_support); COPY_TLV(dst->pdsch_param.pdsch_non_slot_support, src->pdsch_param.pdsch_non_slot_support); COPY_TLV(dst->pusch_param.uci_mux_ulsch_in_pusch, src->pusch_param.uci_mux_ulsch_in_pusch); COPY_TLV(dst->pusch_param.uci_only_pusch, src->pusch_param.uci_only_pusch); COPY_TLV(dst->pusch_param.pusch_frequency_hopping, src->pusch_param.pusch_frequency_hopping); COPY_TLV(dst->pusch_param.pusch_dmrs_config_types, src->pusch_param.pusch_dmrs_config_types); COPY_TLV(dst->pusch_param.pusch_dmrs_max_len, src->pusch_param.pusch_dmrs_max_len); COPY_TLV(dst->pusch_param.pusch_dmrs_additional_pos, src->pusch_param.pusch_dmrs_additional_pos); COPY_TLV(dst->pusch_param.pusch_cbg, src->pusch_param.pusch_cbg); COPY_TLV(dst->pusch_param.pusch_mapping_type, src->pusch_param.pusch_mapping_type); COPY_TLV(dst->pusch_param.pusch_allocation_types, src->pusch_param.pusch_allocation_types); COPY_TLV(dst->pusch_param.pusch_vrb_to_prb_mapping, src->pusch_param.pusch_vrb_to_prb_mapping); COPY_TLV(dst->pusch_param.pusch_max_ptrs_ports, src->pusch_param.pusch_max_ptrs_ports); COPY_TLV(dst->pusch_param.max_pduschs_tbs_per_slot, src->pusch_param.max_pduschs_tbs_per_slot); COPY_TLV(dst->pusch_param.max_number_mimo_layers_non_cb_pusch, src->pusch_param.max_number_mimo_layers_non_cb_pusch); COPY_TLV(dst->pusch_param.supported_modulation_order_ul, src->pusch_param.supported_modulation_order_ul); COPY_TLV(dst->pusch_param.max_mu_mimo_users_ul, src->pusch_param.max_mu_mimo_users_ul); COPY_TLV(dst->pusch_param.dfts_ofdm_support, src->pusch_param.dfts_ofdm_support); COPY_TLV(dst->pusch_param.pusch_aggregation_factor, src->pusch_param.pusch_aggregation_factor); COPY_TLV(dst->prach_param.prach_long_formats, src->prach_param.prach_long_formats); COPY_TLV(dst->prach_param.prach_short_formats, src->prach_param.prach_short_formats); COPY_TLV(dst->prach_param.prach_restricted_sets, src->prach_param.prach_restricted_sets); COPY_TLV(dst->prach_param.max_prach_fd_occasions_in_a_slot, src->prach_param.max_prach_fd_occasions_in_a_slot); COPY_TLV(dst->measurement_param.rssi_measurement_support, src->measurement_param.rssi_measurement_support); COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, sizeof(dst->nfapi_config.p7_vnf_address_ipv4.address)); COPY_TL(dst->nfapi_config.p7_vnf_address_ipv6.tl, src->nfapi_config.p7_vnf_address_ipv6.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv6.address, src->nfapi_config.p7_vnf_address_ipv6.address, sizeof(dst->nfapi_config.p7_vnf_address_ipv6.address)); COPY_TLV(dst->nfapi_config.p7_vnf_port, src->nfapi_config.p7_vnf_port); COPY_TL(dst->nfapi_config.p7_pnf_address_ipv4.tl, src->nfapi_config.p7_pnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_pnf_address_ipv4.address, src->nfapi_config.p7_pnf_address_ipv4.address, sizeof(dst->nfapi_config.p7_pnf_address_ipv4.address)); COPY_TL(dst->nfapi_config.p7_pnf_address_ipv6.tl, src->nfapi_config.p7_pnf_address_ipv6.tl); memcpy(dst->nfapi_config.p7_pnf_address_ipv6.address, src->nfapi_config.p7_pnf_address_ipv6.address, sizeof(dst->nfapi_config.p7_pnf_address_ipv6.address)); COPY_TLV(dst->nfapi_config.p7_pnf_port, src->nfapi_config.p7_pnf_port); COPY_TLV(dst->nfapi_config.timing_window, src->nfapi_config.timing_window); COPY_TLV(dst->nfapi_config.timing_info_mode, src->nfapi_config.timing_info_mode); COPY_TLV(dst->nfapi_config.timing_info_period, src->nfapi_config.timing_info_period); COPY_TLV(dst->nfapi_config.dl_tti_timing_offset, src->nfapi_config.dl_tti_timing_offset); COPY_TLV(dst->nfapi_config.ul_tti_timing_offset, src->nfapi_config.ul_tti_timing_offset); COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset); COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset); } void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_config_request_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } dst->num_tlv = src->num_tlv; COPY_TLV(dst->carrier_config.dl_bandwidth, src->carrier_config.dl_bandwidth); COPY_TLV(dst->carrier_config.dl_frequency, src->carrier_config.dl_frequency); for (int i = 0; i < 5; ++i) { COPY_TLV(dst->carrier_config.dl_k0[i], src->carrier_config.dl_k0[i]); COPY_TLV(dst->carrier_config.dl_grid_size[i], src->carrier_config.dl_grid_size[i]); } COPY_TLV(dst->carrier_config.num_tx_ant, src->carrier_config.num_tx_ant); COPY_TLV(dst->carrier_config.uplink_bandwidth, src->carrier_config.uplink_bandwidth); COPY_TLV(dst->carrier_config.uplink_frequency, src->carrier_config.uplink_frequency); COPY_TLV(dst->carrier_config.uplink_frequency, src->carrier_config.uplink_frequency); for (int i = 0; i < 5; ++i) { COPY_TLV(dst->carrier_config.ul_k0[i], src->carrier_config.ul_k0[i]); COPY_TLV(dst->carrier_config.ul_grid_size[i], src->carrier_config.ul_grid_size[i]); } COPY_TLV(dst->carrier_config.num_rx_ant, src->carrier_config.num_rx_ant); COPY_TLV(dst->carrier_config.frequency_shift_7p5khz, src->carrier_config.frequency_shift_7p5khz); COPY_TLV(dst->cell_config.phy_cell_id, src->cell_config.phy_cell_id); COPY_TLV(dst->cell_config.frame_duplex_type, src->cell_config.frame_duplex_type); COPY_TLV(dst->ssb_config.ss_pbch_power, src->ssb_config.ss_pbch_power); COPY_TLV(dst->ssb_config.bch_payload, src->ssb_config.bch_payload); COPY_TLV(dst->ssb_config.scs_common, src->ssb_config.scs_common); COPY_TLV(dst->prach_config.prach_sequence_length, src->prach_config.prach_sequence_length); COPY_TLV(dst->prach_config.prach_sub_c_spacing, src->prach_config.prach_sub_c_spacing); COPY_TLV(dst->prach_config.restricted_set_config, src->prach_config.restricted_set_config); COPY_TLV(dst->prach_config.num_prach_fd_occasions, src->prach_config.num_prach_fd_occasions); COPY_TLV(dst->prach_config.prach_ConfigurationIndex, src->prach_config.prach_ConfigurationIndex); COPY_TLV(dst->prach_config.prach_ConfigurationIndex, src->prach_config.prach_ConfigurationIndex); dst->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *)malloc( dst->prach_config.num_prach_fd_occasions.value * sizeof(nfapi_nr_num_prach_fd_occasions_t)); for (int i = 0; i < dst->prach_config.num_prach_fd_occasions.value; i++) { nfapi_nr_num_prach_fd_occasions_t *src_prach_fd_occasion = &(src->prach_config.num_prach_fd_occasions_list[i]); nfapi_nr_num_prach_fd_occasions_t *dst_prach_fd_occasion = &(dst->prach_config.num_prach_fd_occasions_list[i]); COPY_TLV(dst_prach_fd_occasion->prach_root_sequence_index, src_prach_fd_occasion->prach_root_sequence_index); COPY_TLV(dst_prach_fd_occasion->num_root_sequences, src_prach_fd_occasion->num_root_sequences); COPY_TLV(dst_prach_fd_occasion->k1, src_prach_fd_occasion->k1); COPY_TLV(dst_prach_fd_occasion->prach_zero_corr_conf, src_prach_fd_occasion->prach_zero_corr_conf); COPY_TLV(dst_prach_fd_occasion->num_unused_root_sequences, src_prach_fd_occasion->num_unused_root_sequences); dst_prach_fd_occasion->unused_root_sequences_list = (nfapi_uint8_tlv_t *)malloc(dst_prach_fd_occasion->num_unused_root_sequences.value * sizeof(nfapi_uint8_tlv_t)); for (int k = 0; k < dst_prach_fd_occasion->num_unused_root_sequences.value; k++) { COPY_TLV(dst_prach_fd_occasion->unused_root_sequences_list[k], src_prach_fd_occasion->unused_root_sequences_list[k]); } } COPY_TLV(dst->prach_config.ssb_per_rach, src->prach_config.ssb_per_rach); COPY_TLV(dst->prach_config.prach_multiple_carriers_in_a_band, src->prach_config.prach_multiple_carriers_in_a_band); COPY_TLV(dst->ssb_table.ssb_offset_point_a, src->ssb_table.ssb_offset_point_a); COPY_TLV(dst->ssb_table.beta_pss, src->ssb_table.beta_pss); COPY_TLV(dst->ssb_table.ssb_period, src->ssb_table.ssb_period); COPY_TLV(dst->ssb_table.ssb_subcarrier_offset, src->ssb_table.ssb_subcarrier_offset); COPY_TLV(dst->ssb_table.MIB, src->ssb_table.MIB); COPY_TLV(dst->ssb_table.ssb_mask_list[0].ssb_mask, src->ssb_table.ssb_mask_list[0].ssb_mask); COPY_TLV(dst->ssb_table.ssb_mask_list[1].ssb_mask, src->ssb_table.ssb_mask_list[1].ssb_mask); for (int i = 0; i < 64; i++) { COPY_TLV(dst->ssb_table.ssb_beam_id_list[i].beam_id, src->ssb_table.ssb_beam_id_list[i].beam_id); } COPY_TLV(dst->ssb_table.case_v3, src->ssb_table.case_v3); if (src->cell_config.frame_duplex_type.value == 1 /* TDD */) { COPY_TLV(dst->tdd_table.tdd_period, src->tdd_table.tdd_period); const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 uint8_t cyclicprefix = 1; // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; dst->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t *)malloc(slotsperframe[dst->ssb_config.scs_common.value] * sizeof(nfapi_nr_max_tdd_periodicity_t)); for (int i = 0; i < slotsperframe[dst->ssb_config.scs_common.value]; i++) { dst->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t *)malloc(number_of_symbols_per_slot * sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); } for (int i = 0; i < slotsperframe[dst->ssb_config.scs_common.value]; i++) { // TODO check right number of slots for (int k = 0; k < number_of_symbols_per_slot; k++) { // TODO can change? COPY_TLV(dst->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config, src->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config); } } } COPY_TLV(dst->measurement_config.rssi_measurement, src->measurement_config.rssi_measurement); 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; } } 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) { dst_pmi_pdu->weights[j][k] = src_pmi_pdu->weights[j][k]; } } } } COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, sizeof(dst->nfapi_config.p7_vnf_address_ipv4.address)); COPY_TL(dst->nfapi_config.p7_vnf_address_ipv6.tl, src->nfapi_config.p7_vnf_address_ipv6.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv6.address, src->nfapi_config.p7_vnf_address_ipv6.address, sizeof(dst->nfapi_config.p7_vnf_address_ipv6.address)); COPY_TLV(dst->nfapi_config.p7_vnf_port, src->nfapi_config.p7_vnf_port); COPY_TL(dst->nfapi_config.p7_pnf_address_ipv4.tl, src->nfapi_config.p7_pnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_pnf_address_ipv4.address, src->nfapi_config.p7_pnf_address_ipv4.address, sizeof(dst->nfapi_config.p7_pnf_address_ipv4.address)); COPY_TL(dst->nfapi_config.p7_pnf_address_ipv6.tl, src->nfapi_config.p7_pnf_address_ipv6.tl); memcpy(dst->nfapi_config.p7_pnf_address_ipv6.address, src->nfapi_config.p7_pnf_address_ipv6.address, sizeof(dst->nfapi_config.p7_pnf_address_ipv6.address)); COPY_TLV(dst->nfapi_config.p7_pnf_port, src->nfapi_config.p7_pnf_port); COPY_TLV(dst->nfapi_config.timing_window, src->nfapi_config.timing_window); COPY_TLV(dst->nfapi_config.timing_info_mode, src->nfapi_config.timing_info_mode); COPY_TLV(dst->nfapi_config.timing_info_period, src->nfapi_config.timing_info_period); COPY_TLV(dst->nfapi_config.dl_tti_timing_offset, src->nfapi_config.dl_tti_timing_offset); COPY_TLV(dst->nfapi_config.ul_tti_timing_offset, src->nfapi_config.ul_tti_timing_offset); COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset); COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset); COPY_TLV(dst->analog_beamforming_ve.num_beams_period_vendor_ext, src->analog_beamforming_ve.num_beams_period_vendor_ext); COPY_TLV(dst->analog_beamforming_ve.analog_bf_vendor_ext, src->analog_beamforming_ve.analog_bf_vendor_ext); } void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } dst->error_code = src->error_code; dst->num_invalid_tlvs = src->num_invalid_tlvs; dst->num_invalid_tlvs_configured_in_idle = src->num_invalid_tlvs_configured_in_idle; dst->num_invalid_tlvs_configured_in_running = src->num_invalid_tlvs_configured_in_running; dst->num_missing_tlvs = src->num_missing_tlvs; dst->invalid_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); dst->invalid_tlvs_configured_in_idle_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_idle * sizeof(nfapi_nr_generic_tlv_scf_t)); dst->invalid_tlvs_configured_in_running_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_invalid_tlvs_configured_in_running * sizeof(nfapi_nr_generic_tlv_scf_t)); dst->missing_tlvs_list = (nfapi_nr_generic_tlv_scf_t *)malloc(dst->num_missing_tlvs * sizeof(nfapi_nr_generic_tlv_scf_t)); for (int i = 0; i < dst->num_invalid_tlvs; ++i) { COPY_TLV(dst->invalid_tlvs_list[i], src->invalid_tlvs_list[i]); } for (int i = 0; i < dst->num_invalid_tlvs_configured_in_idle; ++i) { COPY_TLV(dst->invalid_tlvs_configured_in_idle_list[i], src->invalid_tlvs_configured_in_idle_list[i]); } for (int i = 0; i < dst->num_invalid_tlvs_configured_in_running; ++i) { COPY_TLV(dst->invalid_tlvs_configured_in_running_list[i], src->invalid_tlvs_configured_in_running_list[i]); } for (int i = 0; i < dst->num_missing_tlvs; ++i) { COPY_TLV(dst->missing_tlvs_list[i], src->missing_tlvs_list[i]); } } void copy_start_request(const nfapi_nr_start_request_scf_t *src, nfapi_nr_start_request_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } } void copy_start_response(const nfapi_nr_start_response_scf_t *src, nfapi_nr_start_response_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } dst->error_code = src->error_code; } void copy_stop_request(const nfapi_nr_stop_request_scf_t *src, nfapi_nr_stop_request_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } } void copy_stop_indication(const nfapi_nr_stop_indication_scf_t *src, nfapi_nr_stop_indication_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } } void copy_error_indication(const nfapi_nr_error_indication_scf_t *src, nfapi_nr_error_indication_scf_t *dst) { dst->header.message_id = src->header.message_id; dst->header.message_length = src->header.message_length; if (src->vendor_extension) { dst->vendor_extension = calloc(1, sizeof(nfapi_vendor_extension_tlv_t)); dst->vendor_extension->tag = src->vendor_extension->tag; dst->vendor_extension->length = src->vendor_extension->length; copy_vendor_extension_value(&dst->vendor_extension, &src->vendor_extension); } dst->sfn = src->sfn; dst->slot = src->slot; dst->message_id = src->message_id; dst->error_code = src->error_code; } static void dump_p5_message_header(const nfapi_nr_p4_p5_message_header_t *hdr, int depth) { INDENTED_PRINTF("Message ID = 0x%02x\n", hdr->message_id); INDENTED_PRINTF("Message Length = 0x%02x\n", hdr->message_length); } void dump_param_request(const nfapi_nr_param_request_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); } void dump_param_response(const nfapi_nr_param_response_scf_t *msg) { int depth = 0; 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--; } void dump_config_request(const nfapi_nr_config_request_scf_t *msg) { int depth = 0; 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); // Only print if it's filled if (ssb_table->case_v3.tl.tag == NFAPI_NR_FAPI_SSB_CASE_VENDOR_EXTENSION_TAG) { INDENTED_TLV_PRINT("SSB Case V3", ssb_table->case_v3); } /* 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->r); INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", pm_weights->i); } } 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--; } 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; dump_p5_message_header(&msg->header,depth); depth++; INDENTED_PRINTF("Error Code = 0x%02x\n", msg->error_code); INDENTED_PRINTF("Number of Invalid or Unsupported TLVs = 0x%02x\n", msg->num_invalid_tlvs); INDENTED_PRINTF("Number of Invalid TLVs that can be configured in IDLE = 0x%02x\n", msg->num_invalid_tlvs_configured_in_idle); INDENTED_PRINTF("Number of Invalid TLVs that can be configured in RUNNING = 0x%02x\n", 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--; } void dump_start_request(const nfapi_nr_start_request_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); } void dump_start_response(const nfapi_nr_start_response_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); } void dump_stop_request(const nfapi_nr_stop_request_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); } void dump_stop_indication(const nfapi_nr_stop_indication_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); } char* error_ind_code_to_str(nfapi_nr_phy_notifications_errors_e error_code) { switch (error_code) { #define X(name, value) case name: return #name; NFAPI_PHY_ERROR_LIST #undef X default: return "UNKNOWN_ERROR"; } } void dump_error_indication(const nfapi_nr_error_indication_scf_t *msg) { int depth = 0; dump_p5_message_header(&msg->header,depth); depth++; INDENTED_PRINTF("SFN = 0x%02x (%d)\n", msg->sfn, msg->sfn); INDENTED_PRINTF("Slot = 0x%02x (%d)\n", msg->slot, msg->slot); INDENTED_PRINTF("Message ID = 0x%02x\n", msg->message_id); INDENTED_PRINTF("Error Code = 0x%02x (%s) \n", msg->error_code, error_ind_code_to_str(msg->error_code)); depth--; }