diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index f478ea9b20..d7f86ac84f 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -2033,6 +2033,7 @@ custom build: - *build_after_script artifacts: <<: *build_artifacts + expire_in: 4 hours cache: - !reference [.fetch_src_cache, cache] - *cache_build_get diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 3c20835ed7..9aa85018e5 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -18,8 +18,10 @@ variables: - "zmq" - "zmq_deb" - "zmq_single_ue" + - "zmq_2x2_mimo" - "zmq_4x4_mimo" - "zmq_srsue" + - "zmq_cudu" - "rf_b200" - "rf_hp" - "android_b200" @@ -286,6 +288,20 @@ amari 1UE: - *txrx-lib - *retina-needs +amari 1UE 2x2 mimo: + extends: .zmq + variables: + TESTBED: "zmq_2x2_mimo" + MARKERS: "zmq_2x2_mimo" + E2E_LOG_LEVEL: "info" + RETINA_PARAM_ARGS: "gnb.all.pcap=True gnb.all.rlc_enable=False gnb.all.enable_integrity_protection=True" + needs: + - job: "basic relwithdeb" + artifacts: true + - *txrx-lib + - *retina-needs + allow_failure: true + amari 1UE 4x4 mimo: extends: .zmq variables: @@ -549,6 +565,7 @@ validate n300 config: variables: MARKERS: "rf_n300" TESTBED: "android_n300" + allow_failure: true ################################################################################ # Android @@ -586,6 +603,7 @@ android n300: extends: android x300 variables: TESTBED: "android_n300" + allow_failure: true ################################################################################ # VIAVI diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index bd3844c8c6..88a1468b94 100644 --- a/.gitlab/ci/e2e/.env +++ b/.gitlab/ci/e2e/.env @@ -1,6 +1,6 @@ SRSGNB_REGISTRY_URI=registry.gitlab.com/softwareradiosystems/srsgnb RETINA_REGISTRY_PREFIX=registry.gitlab.com/softwareradiosystems/ci/retina -RETINA_VERSION=0.51.10 +RETINA_VERSION=0.51.15 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 diff --git a/.gitlab/ci/e2e/retina_request_zmq_2x2_mimo.yml b/.gitlab/ci/e2e/retina_request_zmq_2x2_mimo.yml new file mode 100644 index 0000000000..7d5eea54f2 --- /dev/null +++ b/.gitlab/ci/e2e/retina_request_zmq_2x2_mimo.yml @@ -0,0 +1,79 @@ +# +# Copyright 2013-2024 Software Radio Systems Limited +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the distribution. +# + +- name: amarisoft-ue + type: ue + image: ${RETINA_REGISTRY_PREFIX}/amarisoftue:${AMARISOFT_VERSION}_${RETINA_VERSION} + labels: + - ${ZMQ_HOSTLABEL_1} + nof_ports: 32 + requirements: + arch: amd64 + cpu: + requests: 5 + limits: 5 + memory: + requests: "26G" + limits: "26G" + ephemeral-storage: + requests: "6G" + limits: "6G" + resources: + - type: zmq + nof_antennas_dl: 2 + nof_antennas_ul: 2 + - type: license + model: amarisoft-5g + shared_files: + - local_path: ${AMARISOFT_TXRX_BINARY_PATH} + remote_path: /opt/lteue/trx_srsran.so + is_executable: true + +- name: srs-gnb + type: gnb + image: ${RETINA_REGISTRY_PREFIX}/srsgnb:${RETINA_VERSION} + labels: + - ${ZMQ_HOSTLABEL_1} + requirements: + arch: amd64 + cpu: + requests: 5 + limits: 5 + memory: + requests: "26G" + limits: "26G" + ephemeral-storage: + requests: "6G" + limits: "6G" + resources: + - type: zmq + nof_antennas_dl: 2 + nof_antennas_ul: 2 + environment: + - PATH: ${PATH}:/builds/softwareradiosystems/srsgnb/build/apps/gnb + shared_files: + - local_path: ${GNB_BINARY_PATH} + remote_path: /usr/local/bin/gnb + is_executable: true + +- name: open5gs + type: 5gc + requirements: + arch: amd64 + cpu: + requests: 1 + limits: 1 + memory: + requests: "8G" + limits: "8G" + ephemeral-storage: + requests: "6G" + limits: "6G" + image: ${RETINA_REGISTRY_PREFIX}/open5gs:${OPEN5GS_VERSION}_${RETINA_VERSION} + labels: + - ${ZMQ_HOSTLABEL_1} diff --git a/.gitlab/ci/trx.yml b/.gitlab/ci/trx.yml index 0b0273bd2a..848a2b9e66 100644 --- a/.gitlab/ci/trx.yml +++ b/.gitlab/ci/trx.yml @@ -78,7 +78,7 @@ build trx driver: artifacts: &trx_artifacts paths: - build_trx_srsran/libtrx_srsran.so - expire_in: 10 minutes + expire_in: 4 hours build amariue zmq driver: extends: build trx driver diff --git a/apps/cu/cu.cpp b/apps/cu/cu.cpp index 5a0fdc7069..d74536c192 100644 --- a/apps/cu/cu.cpp +++ b/apps/cu/cu.cpp @@ -292,7 +292,7 @@ int main(int argc, char** argv) sctp_network_gateway_config f1c_sctp_cfg = {}; f1c_sctp_cfg.if_name = "F1-C"; f1c_sctp_cfg.bind_address = cu_cfg.f1ap_cfg.bind_addr; - f1c_sctp_cfg.bind_port = 38471; + f1c_sctp_cfg.bind_port = F1AP_PORT; f1c_sctp_cfg.ppid = F1AP_PPID; f1c_cu_sctp_gateway_config f1c_server_cfg({f1c_sctp_cfg, *epoll_broker, *cu_cp_dlt_pcaps.f1ap}); std::unique_ptr cu_f1c_gw = srsran::create_f1c_gateway_server(f1c_server_cfg); diff --git a/apps/du/adapters/f1_gateways.h b/apps/du/adapters/f1_gateways.h index f55a83f222..38e51c1e1f 100644 --- a/apps/du/adapters/f1_gateways.h +++ b/apps/du/adapters/f1_gateways.h @@ -36,7 +36,7 @@ std::unique_ptr create_f1c_client_gateway(const s f1c_sctp.if_name = "F1-C"; f1c_sctp.dest_name = "CU-CP"; f1c_sctp.connect_address = cu_cp_addr; - f1c_sctp.connect_port = 38471; + f1c_sctp.connect_port = F1AP_PORT; f1c_sctp.ppid = F1AP_PPID; f1c_sctp.bind_address = bind_addr; return create_f1c_gateway_client(f1c_du_sctp_gateway_config{f1c_sctp, broker, f1ap_pcap}); diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 306fef75d5..bf9bc02dae 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -184,6 +184,26 @@ static void register_app_logs(const logger_appconfig& log_cfg, register_dynamic_du_loggers(du_loggers); } +static void autoderive_slicing_args(dynamic_du_unit_config& du_unit_cfg, cu_cp_unit_config& cu_cp_config) +{ + std::vector du_slices; + for (const auto& cell_cfg : du_unit_cfg.du_high_cfg.config.cells_cfg) { + for (const auto& slice : cell_cfg.cell.slice_cfg) { + if (du_slices.end() == std::find(du_slices.begin(), du_slices.end(), slice.s_nssai)) { + du_slices.push_back(slice.s_nssai); + } + } + } + // NOTE: A CU-CP can serve more slices than slices configured in the DU cells. + // [Implementation-defined] Ensure that all slices served by DU cells are part of CU-CP served slices. + for (const auto& slice : du_slices) { + if (cu_cp_config.slice_cfg.end() == + std::find(cu_cp_config.slice_cfg.begin(), cu_cp_config.slice_cfg.end(), slice)) { + cu_cp_config.slice_cfg.push_back(slice); + } + } +} + int main(int argc, char** argv) { // Set the application error handler. @@ -225,6 +245,7 @@ int main(int argc, char** argv) // Set the callback for the app calling all the autoderivation functions. app.callback([&app, &gnb_cfg, &du_unit_cfg, &cu_cp_config]() { autoderive_gnb_parameters_after_parsing(app, gnb_cfg); + autoderive_slicing_args(du_unit_cfg, cu_cp_config); autoderive_dynamic_du_parameters_after_parsing(app, du_unit_cfg); // Create the PLMN and TAC list from the cells. diff --git a/apps/services/metrics_log_helper.cpp b/apps/services/metrics_log_helper.cpp index 0f38ab3daa..5cb2a334e6 100644 --- a/apps/services/metrics_log_helper.cpp +++ b/apps/services/metrics_log_helper.cpp @@ -133,6 +133,7 @@ void metrics_log_helper::report_metrics(const rlc_metrics& metrics) fmt::format_to(buffer, " du={}", metrics.du_index); fmt::format_to(buffer, " ue={}", metrics.ue_index); fmt::format_to(buffer, " rb={}", metrics.rb_id); + fmt::format_to(buffer, " mode={}", metrics.rx.mode); fmt::format_to(buffer, " TX=[{}]", format_rlc_tx_metrics(metrics.metrics_period, metrics.tx)); fmt::format_to(buffer, " RX=[{}] ", format_rlc_rx_metrics(metrics.metrics_period, metrics.rx)); logger.debug("{}", to_c_str(buffer)); diff --git a/apps/services/rlc_metrics_plotter_json.cpp b/apps/services/rlc_metrics_plotter_json.cpp index 1ba1d93ba5..1f60cf0a26 100644 --- a/apps/services/rlc_metrics_plotter_json.cpp +++ b/apps/services/rlc_metrics_plotter_json.cpp @@ -96,17 +96,17 @@ void rlc_metrics_plotter_json::report_metrics(const rlc_metrics& drb) ctx.get().emplace_back(); auto& output = ctx.get().back(); - output.write(drb.du_index); + output.write(static_cast(drb.du_index)); output.write(drb.ue_index); output.write(static_cast(drb.rb_id.get_drb_id())); // TX metrics auto& tx_output = output.get(); - tx_output.write(drb.tx.num_sdus); - tx_output.write(drb.tx.num_sdu_bytes); - tx_output.write(drb.tx.num_dropped_sdus); - tx_output.write(drb.tx.num_discarded_sdus); - tx_output.write(drb.tx.num_discarded_sdus); + tx_output.write(drb.tx.tx_high.num_sdus); + tx_output.write(drb.tx.tx_high.num_sdu_bytes); + tx_output.write(drb.tx.tx_high.num_dropped_sdus); + tx_output.write(drb.tx.tx_high.num_discarded_sdus); + tx_output.write(drb.tx.tx_high.num_discarded_sdus); // RX metrics auto& rx_output = output.get(); diff --git a/apps/units/cu_cp/cu_cp_config_translators.cpp b/apps/units/cu_cp/cu_cp_config_translators.cpp index 39272006b5..e0bcd0a97f 100644 --- a/apps/units/cu_cp/cu_cp_config_translators.cpp +++ b/apps/units/cu_cp/cu_cp_config_translators.cpp @@ -227,8 +227,8 @@ srs_cu_cp::cu_cp_configuration srsran::generate_cu_cp_config(const cu_cp_unit_co cu_cfg.mobility_config.trigger_handover_from_measurements; // F1AP-CU config. - out_cfg.f1ap.ue_context_setup_timeout = std::chrono::milliseconds{cu_cfg.f1ap_config.ue_context_setup_timeout}; - out_cfg.f1ap.json_log_enabled = cu_cfg.loggers.f1ap_json_enabled; + out_cfg.f1ap.proc_timeout = std::chrono::milliseconds{cu_cfg.f1ap_config.procedure_timeout}; + out_cfg.f1ap.json_log_enabled = cu_cfg.loggers.f1ap_json_enabled; // Convert appconfig's cell list into cell manager type. for (const auto& app_cfg_item : cu_cfg.mobility_config.cells) { diff --git a/apps/units/cu_cp/cu_cp_unit_config.h b/apps/units/cu_cp/cu_cp_unit_config.h index 2226588943..3b4b594ece 100644 --- a/apps/units/cu_cp/cu_cp_unit_config.h +++ b/apps/units/cu_cp/cu_cp_unit_config.h @@ -108,8 +108,8 @@ struct cu_cp_unit_security_config { /// F1AP-CU configuration parameters. struct cu_cp_unit_f1ap_config { - /// Timeout for the UE context setup procedure in milliseconds. - unsigned ue_context_setup_timeout = 1000; + /// Timeout for the F1AP procedures in milliseconds. + unsigned procedure_timeout = 1000; }; /// RLC UM TX configuration diff --git a/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp b/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp index 95f45c3660..c3cf2c4b19 100644 --- a/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp +++ b/apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp @@ -233,9 +233,9 @@ static void configure_cli11_security_args(CLI::App& app, cu_cp_unit_security_con static void configure_cli11_f1ap_args(CLI::App& app, cu_cp_unit_f1ap_config& f1ap_params) { add_option(app, - "--ue_context_setup_timeout", - f1ap_params.ue_context_setup_timeout, - "UE context setup timeout in milliseconds") + "--procedure_timeout", + f1ap_params.procedure_timeout, + "Time that the F1AP waits for a DU response in milliseconds") ->capture_default_str(); } @@ -479,10 +479,10 @@ void srsran::configure_cli11_with_cu_cp_unit_config_schema(CLI::App& app, cu_cp_ // Slicing section. auto slicing_lambda = [&unit_cfg](const std::vector& values) { - // Prepare the radio bearers + // Prepare the slices. unit_cfg.slice_cfg.resize(values.size()); - // Format every QoS setting. + // Format every slicing setting. for (unsigned i = 0, e = values.size(); i != e; ++i) { CLI::App subapp("Slicing parameters", "Slicing config, item #" + std::to_string(i)); subapp.config_formatter(create_yaml_config_parser()); diff --git a/apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp b/apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp index d67e84d8f5..fbf6484cdf 100644 --- a/apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp +++ b/apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp @@ -158,7 +158,7 @@ static YAML::Node build_cu_cp_f1ap_section(const cu_cp_unit_f1ap_config& config) { YAML::Node node; - node["ue_context_setup_timeout"] = config.ue_context_setup_timeout; + node["procedure_timeout"] = config.procedure_timeout; return node; } diff --git a/apps/units/flexible_du/du_high/du_high_config.h b/apps/units/flexible_du/du_high/du_high_config.h index d2ab95cc2f..4aa6a11679 100644 --- a/apps/units/flexible_du/du_high/du_high_config.h +++ b/apps/units/flexible_du/du_high/du_high_config.h @@ -39,6 +39,7 @@ #include "srsran/ran/pucch/pucch_configuration.h" #include "srsran/ran/pusch/pusch_mcs.h" #include "srsran/ran/rnti.h" +#include "srsran/ran/s_nssai.h" #include "srsran/ran/sib/system_info_config.h" #include "srsran/ran/slot_pdu_capacity_constants.h" #include "srsran/ran/subcarrier_spacing.h" @@ -498,6 +499,22 @@ struct du_high_unit_prach_config { uint8_t nof_cb_preambles_per_ssb = 64; }; +/// Slice scheduling configuration for a cell. +struct du_high_unit_cell_slice_sched_config { + /// Sets the minimum percentage of PRBs to be allocated to this group. + unsigned min_prb_policy_ratio = 0; + /// Sets the maximum percentage of PRBs to be allocated to this group. + unsigned max_prb_policy_ratio = 100; +}; + +/// Slice configuration for a cell. +struct du_high_unit_cell_slice_config { + /// Slice identifier. + s_nssai_t s_nssai = s_nssai_t{1}; + /// Slice scheduling configuration. + du_high_unit_cell_slice_sched_config sched_cfg; +}; + /// Base cell configuration. struct du_high_unit_base_cell_config { /// Physical cell identifier. @@ -552,6 +569,8 @@ struct du_high_unit_base_cell_config { du_high_unit_csi_config csi_cfg; /// Scheduler expert configuration. du_high_unit_scheduler_expert_config sched_expert_cfg; + /// Network slice configuration. + std::vector slice_cfg; }; struct du_high_unit_test_mode_ue_config { diff --git a/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp b/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp index d64785a9d8..73ade5fc26 100644 --- a/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_cli11_schema.cpp @@ -1039,6 +1039,37 @@ static void configure_cli11_sib_args(CLI::App& app, du_high_unit_sib_config& sib ->check(CLI::IsMember({100, 200, 300, 400, 600, 1000, 1500, 2000})); } +static void configure_cli11_slicing_scheduling_args(CLI::App& app, + du_high_unit_cell_slice_sched_config& slice_sched_params) +{ + add_option(app, + "--min_prb_policy_ratio", + slice_sched_params.min_prb_policy_ratio, + "Minimum percentage of PRBs to be allocated to the slice") + ->capture_default_str() + ->check(CLI::Range(0U, 100U)); + add_option(app, + "--max_prb_policy_ratio", + slice_sched_params.max_prb_policy_ratio, + "Maximum percentage of PRBs to be allocated to the slice") + ->capture_default_str() + ->check(CLI::Range(1U, 100U)); +} + +static void configure_cli11_slicing_args(CLI::App& app, du_high_unit_cell_slice_config& slice_params) +{ + add_option(app, "--sst", slice_params.s_nssai.sst, "Slice Service Type") + ->capture_default_str() + ->check(CLI::Range(0, 255)); + add_option(app, "--sd", slice_params.s_nssai.sd, "Service Differentiator") + ->capture_default_str() + ->check(CLI::Range(0, 0xffffff)); + + // Scheduling configuration. + CLI::App* sched_cfg_subcmd = add_subcommand(app, "sched_cfg", "Slice scheduling configuration")->configurable(); + configure_cli11_slicing_scheduling_args(*sched_cfg_subcmd, slice_params.sched_cfg); +} + static void configure_cli11_common_cell_args(CLI::App& app, du_high_unit_base_cell_config& cell_params) { add_option(app, "--pci", cell_params.pci, "PCI")->capture_default_str()->check(CLI::Range(0, 1007)); @@ -1192,6 +1223,23 @@ static void configure_cli11_common_cell_args(CLI::App& app, du_high_unit_base_ce // Scheduler expert configuration. CLI::App* sched_expert_subcmd = add_subcommand(app, "sched_expert_cfg", "Scheduler expert parameters"); configure_cli11_scheduler_expert_args(*sched_expert_subcmd, cell_params.sched_expert_cfg); + + // Slicing configuration. + auto slicing_lambda = [&cell_params](const std::vector& values) { + // Prepare the slices and its configuration. + cell_params.slice_cfg.resize(values.size()); + + // Format every slicing setting. + for (unsigned i = 0, e = values.size(); i != e; ++i) { + CLI::App subapp("Slicing parameters", "Slicing config, item #" + std::to_string(i)); + subapp.config_formatter(create_yaml_config_parser()); + subapp.allow_config_extras(CLI::config_extras_mode::capture); + configure_cli11_slicing_args(subapp, cell_params.slice_cfg[i]); + std::istringstream ss(values[i]); + subapp.parse_from_stream(ss); + } + }; + add_option_cell(app, "--slicing", slicing_lambda, "Network slicing configuration"); } static void configure_cli11_cells_args(CLI::App& app, du_high_unit_cell_config& cell_params) diff --git a/apps/units/flexible_du/du_high/du_high_config_translators.cpp b/apps/units/flexible_du/du_high/du_high_config_translators.cpp index 3612313d86..9369b8744e 100644 --- a/apps/units/flexible_du/du_high/du_high_config_translators.cpp +++ b/apps/units/flexible_du/du_high/du_high_config_translators.cpp @@ -615,6 +615,10 @@ std::vector srsran::generate_du_cell_config(const du_high_unit_c du_pucch_cfg, out_cell.ul_cfg_common.init_ul_bwp.generic_params.crbs.length(), is_long_prach); } + // Slicing configuration. + std::vector cell_plmns{base_cell.plmn}; + out_cell.rrm_policy_members = generate_du_slicing_rrm_policy_config(cell_plmns, base_cell.slice_cfg, nof_crbs); + logger.info( "SSB derived parameters for cell: {}, band: {}, dl_arfcn:{}, crbs: {} scs:{}, ssb_scs:{}:\n\t - SSB offset " "pointA:{} \n\t - k_SSB:{} \n\t - SSB arfcn:{} \n\t - Coreset index:{} \n\t - Searchspace index:{}", @@ -679,6 +683,24 @@ static mac_lc_config generate_mac_lc_config(const du_high_unit_mac_lc_config& in return out_mac; } +std::vector +srsran::generate_du_slicing_rrm_policy_config(span plmns, + span slice_cfg, + unsigned nof_cell_crbs) +{ + std::vector rrm_policy_cfgs; + for (const auto& plmn : plmns) { + for (const auto& cfg : slice_cfg) { + rrm_policy_cfgs.emplace_back(); + rrm_policy_cfgs.back().rrc_member.s_nssai = cfg.s_nssai; + rrm_policy_cfgs.back().rrc_member.plmn_id = plmn; + rrm_policy_cfgs.back().min_prb = (nof_cell_crbs * cfg.sched_cfg.min_prb_policy_ratio) / 100; + rrm_policy_cfgs.back().max_prb = (nof_cell_crbs * cfg.sched_cfg.max_prb_policy_ratio) / 100; + } + } + return rrm_policy_cfgs; +} + std::map srsran::generate_du_qos_config(const du_high_unit_config& config) { std::map out_cfg = {}; diff --git a/apps/units/flexible_du/du_high/du_high_config_translators.h b/apps/units/flexible_du/du_high/du_high_config_translators.h index c9ddf0450d..af4a3e78d3 100644 --- a/apps/units/flexible_du/du_high/du_high_config_translators.h +++ b/apps/units/flexible_du/du_high/du_high_config_translators.h @@ -21,6 +21,8 @@ */ #pragma once + +#include "du_high_config.h" #include "srsran/du/du_cell_config.h" #include "srsran/du/du_qos_config.h" #include "srsran/du/du_srb_config.h" @@ -56,4 +58,10 @@ e2ap_configuration generate_e2_config(const du_high_unit_config& du_high); /// Augments RLC parameters based on NTN configuration. void ntn_augment_rlc_parameters(const ntn_config& ntn_cfg, std::map& srb_cfgs); +/// Converts and returns the given gnb application configuration to a DU slice RRM policy configuration list. +std::vector +generate_du_slicing_rrm_policy_config(span plmns, + span slice_cfg, + unsigned nof_cell_crbs); + } // namespace srsran diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index 57f597829c..13a823221c 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -41,6 +41,13 @@ size_t byte_buffer_segment_pool_default_segment_size(); void init_byte_buffer_segment_pool(std::size_t nof_segments, std::size_t memory_block_size = byte_buffer_segment_pool_default_segment_size()); +/// \brief Get total capacity of the byte buffer segment pool in terms of segments. +size_t get_byte_buffer_segment_pool_capacity(); + +/// \brief Get an estimate of the number of segments of the byte buffer segment pool that are currently available for +/// allocation in the caller thread. +size_t get_byte_buffer_segment_pool_current_size_approx(); + /// \brief Non-owning view to a byte sequence. /// /// The underlying byte sequence is not contiguous in memory. Instead, it is represented as an intrusive linked list of diff --git a/include/srsran/cu_up/cu_up_manager.h b/include/srsran/cu_up/cu_up_manager.h index 5f95ab19f8..0fb1215ae0 100644 --- a/include/srsran/cu_up/cu_up_manager.h +++ b/include/srsran/cu_up/cu_up_manager.h @@ -59,7 +59,7 @@ class cu_up_manager_e1ap_interface /// \brief Handle bearer release command and remove the associated UE context. /// \param[in] msg The original bearer release command. - virtual void handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) = 0; + virtual async_task handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) = 0; /// \brief Get the state of the E1AP connection. /// \return True if E1AP is connected, false otherwise. diff --git a/include/srsran/du/du_cell_config.h b/include/srsran/du/du_cell_config.h index 219f29e104..e0abff8158 100644 --- a/include/srsran/du/du_cell_config.h +++ b/include/srsran/du/du_cell_config.h @@ -32,6 +32,7 @@ #include "srsran/ran/tdd/tdd_ul_dl_config.h" #include "srsran/scheduler/config/bwp_configuration.h" #include "srsran/scheduler/config/serving_cell_config.h" +#include "srsran/scheduler/config/slice_rrm_policy_config.h" namespace srsran { @@ -179,6 +180,9 @@ struct du_cell_config { /// Defines the maximum allowable channel delay in slots when runnning in NTN mode. seee (TS 38.300 section 16.14.2) unsigned ntn_cs_koffset = 0; + + /// List of RAN slices to support in the scheduler. + std::vector rrm_policy_members; }; } // namespace srsran diff --git a/include/srsran/e1ap/cu_up/e1ap_cu_up.h b/include/srsran/e1ap/cu_up/e1ap_cu_up.h index 71ff588453..5a9eebb5b5 100644 --- a/include/srsran/e1ap/cu_up/e1ap_cu_up.h +++ b/include/srsran/e1ap/cu_up/e1ap_cu_up.h @@ -82,7 +82,8 @@ class e1ap_cu_up_manager_notifier /// \brief Notifies the UE manager to release a UE context. /// \param[in] msg The received bearer context release command. - virtual void on_bearer_context_release_command_received(const e1ap_bearer_context_release_command& msg) = 0; + virtual async_task + on_bearer_context_release_command_received(const e1ap_bearer_context_release_command& msg) = 0; /// \brief Schedules async task on UE. virtual void on_schedule_ue_async_task(srs_cu_up::ue_index_t ue_index, async_task task) = 0; diff --git a/include/srsran/f1ap/cu_cp/f1ap_configuration.h b/include/srsran/f1ap/cu_cp/f1ap_configuration.h index 20a460a236..cdc182450f 100644 --- a/include/srsran/f1ap/cu_cp/f1ap_configuration.h +++ b/include/srsran/f1ap/cu_cp/f1ap_configuration.h @@ -29,8 +29,8 @@ namespace srs_cu_cp { /// Configuration for F1AP CU-CP. struct f1ap_configuration { - /// Timeout for UE context setup procedure (Implementation-defined). - std::chrono::milliseconds ue_context_setup_timeout{1000}; + /// Timeout for waiting for the DU response during F1AP procedures (Implementation-defined). + std::chrono::milliseconds proc_timeout{1000}; /// Whether to enable JSON logging of F1AP Tx and Rx messages. bool json_log_enabled = false; }; diff --git a/include/srsran/f1ap/du/f1ap_du_connection_manager.h b/include/srsran/f1ap/du/f1ap_du_connection_manager.h index 341748a405..f4a4ff2220 100644 --- a/include/srsran/f1ap/du/f1ap_du_connection_manager.h +++ b/include/srsran/f1ap/du/f1ap_du_connection_manager.h @@ -28,6 +28,7 @@ #include "srsran/ran/gnb_du_id.h" #include "srsran/ran/nr_cgi.h" #include "srsran/ran/pci.h" +#include "srsran/ran/s_nssai.h" #include "srsran/ran/subcarrier_spacing.h" #include "srsran/support/async/async_task.h" #include @@ -47,6 +48,7 @@ struct f1_cell_setup_params { byte_buffer packed_meas_time_cfg; byte_buffer packed_mib; byte_buffer packed_sib1; + std::vector slices; }; /// \brief Message that initiates a F1 Setup procedure. diff --git a/include/srsran/gateways/sctp_network_gateway.h b/include/srsran/gateways/sctp_network_gateway.h index b46450ff92..3158a2332b 100644 --- a/include/srsran/gateways/sctp_network_gateway.h +++ b/include/srsran/gateways/sctp_network_gateway.h @@ -22,18 +22,21 @@ #pragma once -#include "srsran/adt/optional.h" #include "srsran/gateways/network_gateway.h" +#include #include namespace srsran { -constexpr uint16_t NGAP_PPID = 60; // NGAP PPID, see TS 38.412, section 7. -constexpr uint16_t F1AP_PPID = 62; // F1AP PPID, see TS 38.472, section 7. -constexpr uint16_t E1AP_PPID = 64; // E1AP PPID, see TS 37.482, section 7. -constexpr uint16_t E2_CP_PPID = 70; // E2-CP PPID assigned by IANA -constexpr uint16_t E2_UP_PPID = 71; // E2-UP PPID assigned by IANA -constexpr uint16_t E2_DU_PPID = 72; // E2-DU PPID assigned by IANA +constexpr uint16_t NGAP_PPID = 60; ///< NGAP PPID, see TS 38.412, section 7. +constexpr uint16_t F1AP_PPID = 62; ///< F1AP PPID, see TS 38.472, section 7. +constexpr uint16_t E1AP_PPID = 64; ///< E1AP PPID, see TS 37.482, section 7. +constexpr uint16_t E2_CP_PPID = 70; ///< E2-CP PPID assigned by IANA +constexpr uint16_t E2_UP_PPID = 71; ///< E2-UP PPID assigned by IANA +constexpr uint16_t E2_DU_PPID = 72; ///< E2-DU PPID assigned by IANA + +constexpr uint16_t NGAP_PORT = 38412; ///< NGAP port, see TS 38.412, section 7. +constexpr uint16_t F1AP_PORT = 38472; ///< F1AP port, see TS 38.472, section 7. /// \brief Configuration for SCTP network gateway that is common to the server and client. struct sctp_network_gateway_config : public common_network_gateway_config { diff --git a/include/srsran/ngap/gateways/n2_connection_client_factory.h b/include/srsran/ngap/gateways/n2_connection_client_factory.h index 7276e96925..88a4929e61 100644 --- a/include/srsran/ngap/gateways/n2_connection_client_factory.h +++ b/include/srsran/ngap/gateways/n2_connection_client_factory.h @@ -44,7 +44,7 @@ struct n2_connection_client_config { std::string bind_address; std::string bind_interface; std::string amf_address; - int amf_port = 38412; + int amf_port = NGAP_PORT; std::optional rto_initial; std::optional rto_min; std::optional rto_max; @@ -64,4 +64,4 @@ struct n2_connection_client_config { std::unique_ptr create_n2_connection_client(const n2_connection_client_config& params); } // namespace srs_cu_cp -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/include/srsran/nru/nru_message.h b/include/srsran/nru/nru_message.h index e12fbb6b57..d7d1f1f27d 100644 --- a/include/srsran/nru/nru_message.h +++ b/include/srsran/nru/nru_message.h @@ -84,6 +84,17 @@ struct nru_dl_user_data { /// This parameter indicates that the node hosting the NR PDCP entity requests the other side to provide the downlink /// delivery status report. bool report_polling = false; + /// Request OutOfSeq Report. + /// This parameter indicates that the node hosting the NR PDCP entity requests the corresponding node to report the NR + /// PDCP PDU sequence number successfully delivered out of sequence in downlink delivery status report. + bool request_out_of_seq_report = false; + /// Report Delivered. + /// This parameter indicates the presence of DL report NR PDCP PDU SN. + bool report_delivered = false; + /// User data existence flag. + /// This parameter indicates whether the node hosting the NR PDCP entity has some user data for the concerned data + /// radio bearer. + bool user_data_existence_flag = false; /// Assistance Information Report Polling Flag. /// This parameter indicates that the node hosting the NR PDCP entity requests the corresponding node to send an /// ASSISTANCE INFORMATION DATA PDU. @@ -101,13 +112,19 @@ struct nru_dl_user_data { std::optional dl_discard_pdcp_sn; /// Container holding the DL discard NR PDCP PDU SN blocks. std::optional discard_blocks; + /// DL report NR PDCP PDU SN. + /// This parameter indicates that the node hosting PDCP entity requests providing the down link delivery status report + /// when the NR PDCP PDU with this sequence number has been successfully delivered. + uint32_t dl_report_pdcp_sn = 0; bool operator==(const nru_dl_user_data& other) const { - return report_polling == other.report_polling && + return report_polling == other.report_polling && request_out_of_seq_report == other.request_out_of_seq_report && + report_delivered == other.report_delivered && user_data_existence_flag == other.user_data_existence_flag && assist_info_report_polling_flag == other.assist_info_report_polling_flag && retransmission_flag == other.retransmission_flag && nru_sn == other.nru_sn && - dl_discard_pdcp_sn == other.dl_discard_pdcp_sn && discard_blocks == other.discard_blocks; + dl_discard_pdcp_sn == other.dl_discard_pdcp_sn && discard_blocks == other.discard_blocks && + dl_report_pdcp_sn == other.dl_report_pdcp_sn; } }; diff --git a/include/srsran/phy/support/re_buffer.h b/include/srsran/phy/support/re_buffer.h index 2a46703d28..01bdbeb9c8 100644 --- a/include/srsran/phy/support/re_buffer.h +++ b/include/srsran/phy/support/re_buffer.h @@ -290,13 +290,15 @@ class static_re_buffer : public re_buffer_reader, public re_buffer_writer /// \ref set_slice method. /// /// \tparam T Resource element type. -template +template class modular_re_buffer_reader : public re_buffer_reader { public: - /// \brief Constructs a modular resource element buffer for a given maximum number of slices and resource elements. - /// \param[in] max_nof_slices Maximum number of slices. - modular_re_buffer_reader(unsigned max_nof_slices) : nof_slices(0), nof_re(0), data(max_nof_slices) {} + /// Constructs a modular resource element buffer. + modular_re_buffer_reader() : nof_slices(0), nof_re(0) {} + + /// Constructs a modular resource element buffer for a given number of slices and resource elements. + modular_re_buffer_reader(unsigned nof_slices_, unsigned nof_re_) { resize(nof_slices_, nof_re_); } /// \brief Resizes the buffer view to a desired number of RE and slices. /// \param[in] nof_slices Number of slices. @@ -352,7 +354,7 @@ class modular_re_buffer_reader : public re_buffer_reader unsigned nof_re; /// Internal data storage. - std::vector> data; + std::array, MaxNofSlices> data; }; /// \brief Implements a modular resource element buffer writer. @@ -360,8 +362,9 @@ class modular_re_buffer_reader : public re_buffer_reader /// In this implementation, each slice is a view to an external block of contiguous REs that must be loaded with the /// \ref set_slice method. /// -/// \tparam T Resource element type. -template +/// \tparam T Resource element type. +/// \tparam MaxNofSlices Maximum number of slices. +template class modular_re_buffer_writer : public re_buffer_writer { public: diff --git a/include/srsran/phy/upper/equalization/modular_ch_est_list.h b/include/srsran/phy/upper/equalization/modular_ch_est_list.h index 26212487e1..b4ee2e1217 100644 --- a/include/srsran/phy/upper/equalization/modular_ch_est_list.h +++ b/include/srsran/phy/upper/equalization/modular_ch_est_list.h @@ -28,6 +28,7 @@ namespace srsran { /// Implements the list of channel estimates with views to each of the channels. +template class modular_ch_est_list : public channel_equalizer::ch_est_list { public: @@ -37,6 +38,12 @@ class modular_ch_est_list : public channel_equalizer::ch_est_list modular_ch_est_list(unsigned max_nof_rx_ports_, unsigned max_nof_layers_) : max_nof_rx_ports(max_nof_rx_ports_), max_nof_layers(max_nof_layers_), data({max_nof_rx_ports, max_nof_layers}) { + srsran_assert(max_nof_rx_ports * max_nof_layers <= MaxNofElements, + "The maximum number of layers (i.e., {}) times the maximum number of ports (i.e., {}) exceeds the " + "maximum number of elements (i.e., {})", + max_nof_layers, + max_nof_rx_ports, + MaxNofElements); } /// \brief Sets the contents of a channel. @@ -109,7 +116,7 @@ class modular_ch_est_list : public channel_equalizer::ch_est_list /// Maximum number of layers. unsigned max_nof_layers; /// Data storage as a tensor of views for each channel. - dynamic_tensor(ch_dims::nof_dims), span, ch_dims> data; + static_tensor(ch_dims::nof_dims), span, MaxNofElements, ch_dims> data; }; } // namespace srsran \ No newline at end of file diff --git a/include/srsran/rlc/rlc_metrics.h b/include/srsran/rlc/rlc_metrics.h index 6483176993..0f86aae604 100644 --- a/include/srsran/rlc/rlc_metrics.h +++ b/include/srsran/rlc/rlc_metrics.h @@ -23,6 +23,7 @@ #pragma once #include "srsran/ran/du_types.h" +#include "srsran/ran/gnb_du_id.h" #include "srsran/ran/lcid.h" #include "srsran/rlc/rlc_rx_metrics.h" #include "srsran/rlc/rlc_tx_metrics.h" @@ -31,7 +32,7 @@ namespace srsran { /// Container to hold TX/RX metrics struct rlc_metrics { - uint32_t du_index; + gnb_du_id_t du_index; du_ue_index_t ue_index; rb_id_t rb_id; rlc_tx_metrics tx; diff --git a/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index ed0167348b..8e5c2a8bfa 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -29,11 +29,18 @@ namespace srsran { -struct rlc_tm_rx_metrics {}; +struct rlc_tm_rx_metrics { + void reset() {} +}; struct rlc_um_rx_metrics { uint32_t num_sdu_segments; ///< Number of SDU segments RX'ed uint32_t num_sdu_segment_bytes; ///< Number of SDU segments Bytes + void reset() + { + num_sdu_segments = {}; + num_sdu_segment_bytes = {}; + } }; struct rlc_am_rx_metrics { @@ -41,6 +48,13 @@ struct rlc_am_rx_metrics { uint32_t num_sdu_segment_bytes; ///< Number of SDU segments bytes uint32_t num_ctrl_pdus; ///< Number of control PDUs uint32_t num_ctrl_pdu_bytes; ///< Number of control PDUs bytes + void reset() + { + num_sdu_segments = {}; + num_sdu_segment_bytes = {}; + num_ctrl_pdus = {}; + num_ctrl_pdu_bytes = {}; + } }; struct rlc_rx_metrics { @@ -67,6 +81,46 @@ struct rlc_rx_metrics { rlc_um_rx_metrics um; rlc_am_rx_metrics am; } mode_specific; + + uint32_t counter = 0; ///< Counter of amount of times we collected metrics. + /// Useful to aggregate high and low metrics. + + rlc_rx_metrics get() + { + rlc_rx_metrics ret = *this; + counter++; + return ret; + } + + void reset() + { + // SDU metrics + num_sdus = {}; + num_sdu_bytes = {}; + num_pdus = {}; + num_pdu_bytes = {}; + num_lost_pdus = {}; + num_malformed_pdus = {}; + sdu_latency_us = {}; + + // reset mode-specific values + switch (mode) { + case rlc_mode::tm: + mode_specific.tm.reset(); + break; + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + mode_specific.um.reset(); + break; + case rlc_mode::am: + mode_specific.am.reset(); + break; + default: + // nothing to do here + break; + } + // do not reset mode or counter + } }; class rlc_rx_metrics_interface @@ -87,12 +141,13 @@ class rlc_rx_metrics_interface inline std::string format_rlc_rx_metrics(timer_duration metrics_period, const rlc_rx_metrics& m) { fmt::memory_buffer buffer; - fmt::format_to(buffer, - "num_sdus={} sdu_rate={}bps num_pdus={} pdu_rate={}bps", - scaled_fmt_integer(m.num_sdus, false), - float_to_eng_string(static_cast(m.num_sdu_bytes) * 8 * 1000 / metrics_period.count(), 1, false), - scaled_fmt_integer(m.num_pdus, false), - (double)m.num_pdu_bytes * 8 / (double)metrics_period.count()); + fmt::format_to( + buffer, + "num_sdus={} sdu_rate={}bps num_pdus={} pdu_rate={}bps", + scaled_fmt_integer(m.num_sdus, false), + float_to_eng_string(static_cast(m.num_sdu_bytes) * 8 * 1000 / metrics_period.count(), 1, false), + scaled_fmt_integer(m.num_pdus, false), + float_to_eng_string(static_cast(m.num_pdu_bytes) * 8 * 1000 / metrics_period.count(), 1, false)); // No TM specific metrics for RX if ((m.mode == rlc_mode::um_bidir || m.mode == rlc_mode::um_unidir_ul)) { @@ -107,8 +162,7 @@ inline std::string format_rlc_rx_metrics(timer_duration metrics_period, const rl } else if (m.mode == rlc_mode::am) { fmt::format_to( buffer, - " num_sdu_segments={} sdu_segmments_rate={}bps", - " ctrl_pdus={} ctrl_rate={}bps", + " num_sdu_segments={} sdu_segmments_rate={}bps ctrl_pdus={} ctrl_rate={}bps", scaled_fmt_integer(m.mode_specific.am.num_sdu_segments, false), float_to_eng_string( static_cast(m.mode_specific.am.num_sdu_segment_bytes) * 8 * 1000 / metrics_period.count(), 1, false), diff --git a/include/srsran/rlc/rlc_tx_metrics.h b/include/srsran/rlc/rlc_tx_metrics.h index 6681ef32a5..878f2a0862 100644 --- a/include/srsran/rlc/rlc_tx_metrics.h +++ b/include/srsran/rlc/rlc_tx_metrics.h @@ -29,37 +29,75 @@ namespace srsran { -struct rlc_tm_tx_metrics { +struct rlc_tx_metrics_higher { + uint32_t num_sdus; ///< Number of SDUs + size_t num_sdu_bytes; ///< Number of SDU bytes + uint32_t num_dropped_sdus; ///< Number of dropped SDUs (due to full queue) + uint32_t num_discarded_sdus; ///< Number of discarded SDUs (instructed from higher layer) + uint32_t num_discard_failures; ///< Number of failed SDU discards (instructed from higher layer) + + uint32_t counter = 0; ///< Counter of amount of times we collected metrics. + /// Useful to aggregate high and low metrics. + + rlc_tx_metrics_higher get() + { + rlc_tx_metrics_higher ret = *this; + counter++; + return ret; + } + + void reset() + { + num_sdus = {}; + num_sdu_bytes = {}; + num_dropped_sdus = {}; + num_discarded_sdus = {}; + num_discard_failures = {}; + // do not reset counter + } +}; + +struct rlc_tm_tx_metrics_lower { uint32_t num_small_allocs; ///< Number of allocations that are too small to TX PDU + + void reset() { num_small_allocs = {}; } }; -struct rlc_um_tx_metrics { +struct rlc_um_tx_metrics_lower { uint32_t num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation uint32_t num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation + + void reset() + { + num_pdus_with_segmentation = {}; + num_pdu_bytes_with_segmentation = {}; + } }; -struct rlc_am_tx_metrics { +struct rlc_am_tx_metrics_lower { uint32_t num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation uint32_t num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation - uint32_t num_retx_pdus; ///< Number of RETX'ed PDUs - uint32_t num_retx_pdu_bytes; ///< Number of RETX'ed PDUs bytes + uint32_t num_retx_pdus; ///< Number of retransmitted PDUs + uint32_t num_retx_pdu_bytes; ///< Number of retransmitted PDU bytes uint32_t num_ctrl_pdus; ///< Number of control PDUs uint32_t num_ctrl_pdu_bytes; ///< Number of control PDUs bytes -}; -struct rlc_tx_metrics { - // SDU metrics - uint32_t num_sdus; ///< Number of SDUs - uint32_t num_of_pulled_sdus; ///< Number of pulled SDUs - size_t num_sdu_bytes; ///< Number of SDU bytes - uint32_t num_dropped_sdus; ///< Number of dropped SDUs (due to full queue) - uint32_t num_discarded_sdus; ///< Number of discarded SDUs (instructed from higher layer) - uint32_t num_discard_failures; ///< Number of failed SDU discards (instructed from higher layer) - uint32_t sum_sdu_latency_us; ///< total SDU latency (in us)> + void reset() + { + num_pdus_with_segmentation = {}; + num_pdu_bytes_with_segmentation = {}; + num_retx_pdus = {}; + num_retx_pdu_bytes = {}; + num_ctrl_pdus = {}; + num_ctrl_pdu_bytes = {}; + } +}; - // PDU metrics +struct rlc_tx_metrics_lower { uint32_t num_pdus_no_segmentation; ///< Number of transmitted PDUs without segmentation size_t num_pdu_bytes_no_segmentation; ///< Number of transmitted PDU bytes without segmentation + uint32_t num_of_pulled_sdus; ///< Number of pulled SDUs + uint32_t sum_sdu_latency_us; ///< total SDU latency (in us)> /// RLC mode of the entity rlc_mode mode; @@ -69,10 +107,49 @@ struct rlc_tx_metrics { /// The associated union member is indicated by \c mode. /// Contents of the other fields are undefined. union { - rlc_tm_tx_metrics tm; - rlc_um_tx_metrics um; - rlc_am_tx_metrics am; + rlc_tm_tx_metrics_lower tm; + rlc_um_tx_metrics_lower um; + rlc_am_tx_metrics_lower am; } mode_specific; + + uint32_t counter = 0; ///< Counter of amount of times we collected metrics. + /// Useful to aggregate high and low metrics. + + rlc_tx_metrics_lower get() + { + rlc_tx_metrics_lower ret = *this; + counter++; + return ret; + } + void reset() + { + num_pdus_no_segmentation = {}; + num_pdu_bytes_no_segmentation = {}; + num_of_pulled_sdus = {}; + sum_sdu_latency_us = {}; + + // reset mode-specific values + switch (mode) { + case rlc_mode::tm: + mode_specific.tm.reset(); + break; + case rlc_mode::um_bidir: + case rlc_mode::um_unidir_dl: + mode_specific.um.reset(); + break; + case rlc_mode::am: + mode_specific.am.reset(); + break; + default: + // nothing to do here + break; + } + } +}; + +struct rlc_tx_metrics { + rlc_tx_metrics_higher tx_high; + rlc_tx_metrics_lower tx_low; }; class rlc_tx_metrics_interface @@ -97,39 +174,41 @@ inline std::string format_rlc_tx_metrics(timer_duration metrics_period, const rl buffer, "num_sdus={} sdu_rate={}bps dropped_sdus={} discarded_sdus={} " "num_pdus_no_segm={} pdu_rate_no_segm={}bps", - scaled_fmt_integer(m.num_sdus, false), - float_to_eng_string(static_cast(m.num_sdu_bytes) * 8 * 1000 / (metrics_period.count()), 1, false), - scaled_fmt_integer(m.num_dropped_sdus, false), - scaled_fmt_integer(m.num_discarded_sdus, false), - scaled_fmt_integer(m.num_pdus_no_segmentation, false), + scaled_fmt_integer(m.tx_high.num_sdus, false), + float_to_eng_string(static_cast(m.tx_high.num_sdu_bytes) * 8 * 1000 / (metrics_period.count()), 1, false), + scaled_fmt_integer(m.tx_high.num_dropped_sdus, false), + scaled_fmt_integer(m.tx_high.num_discarded_sdus, false), + scaled_fmt_integer(m.tx_low.num_pdus_no_segmentation, false), float_to_eng_string( - static_cast(m.num_pdu_bytes_no_segmentation) * 8 * 1000 / metrics_period.count(), 1, false)); + static_cast(m.tx_low.num_pdu_bytes_no_segmentation) * 8 * 1000 / metrics_period.count(), 1, false)); - if (m.mode == rlc_mode::tm) { + if (m.tx_low.mode == rlc_mode::tm) { // No TM specific metrics for RX - } else if ((m.mode == rlc_mode::um_bidir || m.mode == rlc_mode::um_unidir_dl)) { + } else if ((m.tx_low.mode == rlc_mode::um_bidir || m.tx_low.mode == rlc_mode::um_unidir_dl)) { fmt::format_to(buffer, " num_pdus_with_segm={} pdu_with_segm_rate={}bps", - m.mode_specific.um.num_pdus_with_segmentation, - static_cast(m.mode_specific.um.num_pdu_bytes_with_segmentation) * 8 / metrics_period.count()); - } else if (m.mode == rlc_mode::am) { - fmt::format_to( - buffer, - " num_pdus_with_segm={} pdu_rate_with_segm={}bps num_retx={} " - "retx_rate={}bps ctrl_pdus={} ctrl_rate={}bps", - scaled_fmt_integer(m.mode_specific.am.num_pdus_with_segmentation, false), - float_to_eng_string(static_cast(m.mode_specific.am.num_pdu_bytes_with_segmentation) * 8 * 1000 / - metrics_period.count(), - 1, - false), - scaled_fmt_integer(m.mode_specific.am.num_retx_pdus, false), - float_to_eng_string( - static_cast(m.mode_specific.am.num_retx_pdu_bytes) * 8 * 1000 / metrics_period.count(), 1, false), - scaled_fmt_integer(m.mode_specific.am.num_ctrl_pdus, false), - float_to_eng_string(static_cast(m.mode_specific.am.num_ctrl_pdu_bytes) * 8 * 1000 / - (double)metrics_period.count(), - 1, - false)); + m.tx_low.mode_specific.um.num_pdus_with_segmentation, + static_cast(m.tx_low.mode_specific.um.num_pdu_bytes_with_segmentation) * 8 / + metrics_period.count()); + } else if (m.tx_low.mode == rlc_mode::am) { + fmt::format_to(buffer, + " num_pdus_with_segm={} pdu_rate_with_segm={}bps num_retx={} " + "retx_rate={}bps ctrl_pdus={} ctrl_rate={}bps", + scaled_fmt_integer(m.tx_low.mode_specific.am.num_pdus_with_segmentation, false), + float_to_eng_string(static_cast(m.tx_low.mode_specific.am.num_pdu_bytes_with_segmentation) * + 8 * 1000 / metrics_period.count(), + 1, + false), + scaled_fmt_integer(m.tx_low.mode_specific.am.num_retx_pdus, false), + float_to_eng_string(static_cast(m.tx_low.mode_specific.am.num_retx_pdu_bytes) * 8 * 1000 / + metrics_period.count(), + 1, + false), + scaled_fmt_integer(m.tx_low.mode_specific.am.num_ctrl_pdus, false), + float_to_eng_string(static_cast(m.tx_low.mode_specific.am.num_ctrl_pdu_bytes) * 8 * 1000 / + (double)metrics_period.count(), + 1, + false)); } return to_c_str(buffer); } @@ -153,13 +232,13 @@ struct formatter { return format_to(ctx.out(), "num_sdus={} num_sdu_bytes={} num_dropped_sdus={} num_discarded_sdus={} " "num_discard_failures={} num_pdus_no_segm={} num_pdu_bytes_no_segm={}", - m.num_sdus, - m.num_sdu_bytes, - m.num_dropped_sdus, - m.num_discarded_sdus, - m.num_discard_failures, - m.num_pdus_no_segmentation, - m.num_pdu_bytes_no_segmentation); + m.tx_high.num_sdus, + m.tx_high.num_sdu_bytes, + m.tx_high.num_dropped_sdus, + m.tx_high.num_discarded_sdus, + m.tx_high.num_discard_failures, + m.tx_low.num_pdus_no_segmentation, + m.tx_low.num_pdu_bytes_no_segmentation); } }; } // namespace fmt diff --git a/lib/cu_up/adapters/e1ap_adapters.h b/lib/cu_up/adapters/e1ap_adapters.h index d1a029abc2..b5b16701f4 100644 --- a/lib/cu_up/adapters/e1ap_adapters.h +++ b/lib/cu_up/adapters/e1ap_adapters.h @@ -57,11 +57,14 @@ class e1ap_cu_up_manager_adapter : public e1ap_cu_up_manager_notifier return cu_up_handler->handle_bearer_context_modification_request(msg); } - void on_bearer_context_release_command_received(const e1ap_bearer_context_release_command& msg) override + async_task on_bearer_context_release_command_received(const e1ap_bearer_context_release_command& msg) override { if (cu_up_handler == nullptr) { logger.warning("Could not handle context release command, no CU-UP handler present. ue={}", msg.ue_index); - return; + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + CORO_RETURN(); + }); } return cu_up_handler->handle_bearer_context_release_command(msg); } diff --git a/lib/cu_up/cu_up_manager_impl.cpp b/lib/cu_up/cu_up_manager_impl.cpp index 22b9ae7718..8f0572ada1 100644 --- a/lib/cu_up/cu_up_manager_impl.cpp +++ b/lib/cu_up/cu_up_manager_impl.cpp @@ -59,6 +59,7 @@ cu_up_manager_impl::cu_up_manager_impl(const cu_up_configuration& config_, n3_teid_allocator, f1u_teid_allocator, *cfg.ue_exec_pool, + *cfg.ctrl_executor, *cfg.gtpu_pcap, logger); } @@ -115,7 +116,12 @@ cu_up_manager_impl::handle_bearer_context_modification_request(const e1ap_bearer ue_context* ue_ctxt = ue_mng->find_ue(msg.ue_index); if (ue_ctxt == nullptr) { logger.error("Could not find UE context"); - return {}; + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + e1ap_bearer_context_modification_response res; + res.success = false; + CORO_RETURN(res); + }); } return execute_and_continue_on_blocking( ue_ctxt->ue_exec_mapper->ctrl_executor(), *cfg.ctrl_executor, [this, ue_ctxt, msg]() { @@ -180,17 +186,21 @@ cu_up_manager_impl::handle_bearer_context_modification_request_impl(ue_context& return response; } -void cu_up_manager_impl::handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) +async_task +cu_up_manager_impl::handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) { ue_context* ue_ctxt = ue_mng->find_ue(msg.ue_index); if (ue_ctxt == nullptr) { logger.error("ue={}: Discarding E1 Bearer Context Release Command. UE context not found", msg.ue_index); - return; + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + CORO_RETURN(); + }); } ue_ctxt->get_logger().log_debug("Received E1 Bearer Context Release Command"); - ue_mng->remove_ue(msg.ue_index); + return ue_mng->remove_ue(msg.ue_index); } async_task cu_up_manager_impl::enable_test_mode() diff --git a/lib/cu_up/cu_up_manager_impl.h b/lib/cu_up/cu_up_manager_impl.h index 892e9a0c2b..369284d2fb 100644 --- a/lib/cu_up/cu_up_manager_impl.h +++ b/lib/cu_up/cu_up_manager_impl.h @@ -49,7 +49,7 @@ class cu_up_manager_impl final : public cu_up_manager async_task handle_bearer_context_modification_request(const e1ap_bearer_context_modification_request& msg) override; - void handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) override; + async_task handle_bearer_context_release_command(const e1ap_bearer_context_release_command& msg) override; void schedule_ue_async_task(srs_cu_up::ue_index_t ue_index, async_task task) override; diff --git a/lib/cu_up/ue_context.h b/lib/cu_up/ue_context.h index 56d04ed46b..5798cda4e0 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -56,6 +56,7 @@ class ue_context : public pdu_session_manager_ctrl n3_interface_config& n3_config_, const cu_up_test_mode_config& test_mode_config_, std::unique_ptr ue_exec_mapper_, + fifo_async_task_scheduler& task_sched_, timer_factory ue_dl_timer_factory_, timer_factory ue_ul_timer_factory_, timer_factory ue_ctrl_timer_factory_, @@ -65,7 +66,7 @@ class ue_context : public pdu_session_manager_ctrl gtpu_tunnel_common_tx_upper_layer_notifier& gtpu_tx_notifier_, gtpu_demux_ctrl& gtpu_rx_demux_, dlt_pcap& gtpu_pcap) : - task_sched(UE_TASK_QUEUE_SIZE), + task_sched(task_sched_), ue_exec_mapper(std::move(ue_exec_mapper_)), index(index_), cfg(std::move(cfg_)), @@ -139,7 +140,7 @@ class ue_context : public pdu_session_manager_ctrl [[nodiscard]] const cu_up_ue_logger& get_logger() const { return logger; }; - fifo_async_task_scheduler task_sched; + fifo_async_task_scheduler& task_sched; std::unique_ptr ue_exec_mapper; diff --git a/lib/cu_up/ue_manager.cpp b/lib/cu_up/ue_manager.cpp index ea02ee1621..70a8691dbf 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -21,6 +21,7 @@ */ #include "ue_manager.h" +#include "srsran/support/async/execute_on.h" using namespace srsran; using namespace srs_cu_up; @@ -36,6 +37,7 @@ ue_manager::ue_manager(network_interface_config& net_config_, gtpu_teid_pool& n3_teid_allocator_, gtpu_teid_pool& f1u_teid_allocator_, cu_up_executor_pool& exec_pool_, + task_executor& ctrl_executor_, dlt_pcap& gtpu_pcap_, srslog::basic_logger& logger_) : net_config(net_config_), @@ -48,17 +50,21 @@ ue_manager::ue_manager(network_interface_config& net_config_, n3_teid_allocator(n3_teid_allocator_), f1u_teid_allocator(f1u_teid_allocator_), exec_pool(exec_pool_), + ctrl_executor(ctrl_executor_), gtpu_pcap(gtpu_pcap_), timers(timers_), - logger(logger_), - task_sched(MAX_NOF_UES) + logger(logger_) { + // Initialize a ue task schedulers for all UE indexes. + for (size_t i = 0; i < MAX_NOF_UES; ++i) { + ue_task_schedulers.emplace(i, UE_TASK_QUEUE_SIZE); + } } ue_context* ue_manager::find_ue(ue_index_t ue_index) { srsran_assert(ue_index < MAX_NOF_UES, "Invalid ue_index={}", ue_index); - return ue_db.contains(ue_index) ? ue_db[ue_index].get() : nullptr; + return ue_db.find(ue_index) != ue_db.end() ? ue_db[ue_index].get() : nullptr; } ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) @@ -92,6 +98,7 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) n3_config, test_mode_config, std::move(ue_exec_mapper), + ue_task_schedulers[new_idx], ue_dl_timer_factory, ue_ul_timer_factory, ue_ctrl_timer_factory, @@ -107,24 +114,30 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) return ue_db[new_idx].get(); } -void ue_manager::remove_ue(ue_index_t ue_index) +async_task ue_manager::remove_ue(ue_index_t ue_index) { logger.debug("ue={}: Scheduling UE deletion", ue_index); - srsran_assert(ue_db.contains(ue_index), "Remove UE called for nonexistent ue_index={}", ue_index); + srsran_assert(ue_db.find(ue_index) != ue_db.end(), "Remove UE called for nonexistent ue_index={}", ue_index); - // TODO: remove lookup maps + // Move UE context out from ue_db and erase the slot (from CU-UP shared ctrl executor) + std::unique_ptr ue_ctxt = std::move(ue_db[ue_index]); + ue_db.erase(ue_index); - task_sched.schedule([this, ue_index](coro_context>& ctx) { + // Dispatch the stopping and deletion of the UE context to UE-specific ctrl executor + return launch_async([this, ue_ctxt = std::move(ue_ctxt), ue_index](coro_context>& ctx) mutable { CORO_BEGIN(ctx); - // Stop UE activity. - CORO_AWAIT(ue_db[ue_index]->stop()); - - // remove UE from database - ue_db.erase(ue_index); + // Dispatch execution context switch. + CORO_AWAIT(execute_on_blocking(ue_ctxt->ue_exec_mapper->ctrl_executor())); + // Stop and delete + CORO_AWAIT(ue_ctxt->stop()); + ue_ctxt.reset(); logger.info("ue={}: UE removed", ue_index); + // Continuation in the original executor. + CORO_AWAIT(execute_on_blocking(ctrl_executor)); + CORO_RETURN(); }); } @@ -133,7 +146,7 @@ ue_index_t ue_manager::get_next_ue_index() { // Search unallocated UE index for (int i = 0; i < MAX_NOF_UES; i++) { - if (not ue_db.contains(i)) { + if (ue_db.find(static_cast(i)) == ue_db.end()) { return int_to_ue_index(i); break; } diff --git a/lib/cu_up/ue_manager.h b/lib/cu_up/ue_manager.h index 81d312a152..c187d04034 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -23,11 +23,11 @@ #pragma once #include "ue_manager_interfaces.h" -#include "srsran/adt/slotted_array.h" #include "srsran/f1u/cu_up/f1u_gateway.h" #include "srsran/gtpu/gtpu_teid_pool.h" #include "srsran/support/async/fifo_async_task_scheduler.h" #include "srsran/support/timers.h" +#include namespace srsran { @@ -47,16 +47,18 @@ class ue_manager : public ue_manager_ctrl gtpu_teid_pool& n3_teid_allocator_, gtpu_teid_pool& f1u_teid_allocator_, cu_up_executor_pool& exec_pool_, + task_executor& ctrl_executor_, dlt_pcap& gtpu_pcap_, srslog::basic_logger& logger_); - using ue_db_t = slotted_array, MAX_NOF_UES>; + using ue_db_t = std::unordered_map>; + using ue_task_schedulers_t = slotted_array; const ue_db_t& get_ues() const { return ue_db; } - ue_context* add_ue(const ue_context_cfg& cfg) override; - void remove_ue(ue_index_t ue_index) override; - ue_context* find_ue(ue_index_t ue_index) override; - size_t get_nof_ues() const override { return ue_db.size(); }; + ue_context* add_ue(const ue_context_cfg& cfg) override; + async_task remove_ue(ue_index_t ue_index) override; + ue_context* find_ue(ue_index_t ue_index) override; + size_t get_nof_ues() const override { return ue_db.size(); }; void schedule_ue_async_task(ue_index_t ue_index, async_task task); @@ -75,12 +77,12 @@ class ue_manager : public ue_manager_ctrl gtpu_teid_pool& n3_teid_allocator; gtpu_teid_pool& f1u_teid_allocator; cu_up_executor_pool& exec_pool; + task_executor& ctrl_executor; dlt_pcap& gtpu_pcap; timer_manager& timers; ue_db_t ue_db; + ue_task_schedulers_t ue_task_schedulers; srslog::basic_logger& logger; - - fifo_async_task_scheduler task_sched; }; } // namespace srs_cu_up diff --git a/lib/cu_up/ue_manager_interfaces.h b/lib/cu_up/ue_manager_interfaces.h index d1dfc0a949..63b7f7be28 100644 --- a/lib/cu_up/ue_manager_interfaces.h +++ b/lib/cu_up/ue_manager_interfaces.h @@ -34,10 +34,10 @@ class ue_manager_ctrl public: virtual ~ue_manager_ctrl() = default; - virtual ue_context* add_ue(const ue_context_cfg& ue_cfg) = 0; - virtual void remove_ue(ue_index_t ue_index) = 0; - virtual ue_context* find_ue(ue_index_t ue_index) = 0; - virtual size_t get_nof_ues() const = 0; + virtual ue_context* add_ue(const ue_context_cfg& ue_cfg) = 0; + virtual async_task remove_ue(ue_index_t ue_index) = 0; + virtual ue_context* find_ue(ue_index_t ue_index) = 0; + virtual size_t get_nof_ues() const = 0; }; } // namespace srs_cu_up diff --git a/lib/du_manager/converters/f1ap_configuration_helpers.cpp b/lib/du_manager/converters/f1ap_configuration_helpers.cpp index 8a5fdc8624..f871bcf73c 100644 --- a/lib/du_manager/converters/f1ap_configuration_helpers.cpp +++ b/lib/du_manager/converters/f1ap_configuration_helpers.cpp @@ -654,6 +654,9 @@ void srsran::srs_du::fill_f1_setup_request(f1_setup_request_message& serv_cell.duplx_mode = cell_cfg.tdd_ul_dl_cfg_common.has_value() ? duplex_mode::TDD : duplex_mode::FDD; serv_cell.scs_common = cell_cfg.scs_common; serv_cell.dl_carrier = cell_cfg.dl_carrier; + for (const auto& slice : cell_cfg.rrm_policy_members) { + serv_cell.slices.push_back(slice.rrc_member.s_nssai); + } if (serv_cell.duplx_mode == duplex_mode::FDD) { serv_cell.ul_carrier = cell_cfg.ul_carrier; } diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index e54aa8accf..fa73c54116 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -82,6 +82,8 @@ srsran::srs_du::make_sched_cell_config_req(du_cell_index_t cell_index, sched_req.nzp_csi_rs_res_list = du_cfg.ue_ded_serv_cell_cfg.csi_meas_cfg->nzp_csi_rs_res_list; } + sched_req.rrm_policy_members = du_cfg.rrm_policy_members; + return sched_req; } @@ -112,6 +114,8 @@ sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const sched_lc_ch.lc_sr_mask = bearer.second->mac_cfg.lc_sr_mask; sched_lc_ch.lc_sr_delay_timer_applied = bearer.second->mac_cfg.lc_sr_delay_applied; sched_lc_ch.sr_id.emplace(bearer.second->mac_cfg.sr_id); + sched_lc_ch.rrm_policy.s_nssai = bearer.second->s_nssai; + sched_lc_ch.rrm_policy.plmn_id = ue_ctx.nr_cgi.plmn_id.to_string(); sched_cfg.drb_info_list.emplace_back(sched_drb_info{.lcid = bearer.second->lcid, .s_nssai = bearer.second->s_nssai, diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.h b/lib/du_manager/converters/scheduler_configuration_helpers.h index 24c92d8ad0..af7c8161b4 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.h +++ b/lib/du_manager/converters/scheduler_configuration_helpers.h @@ -22,6 +22,7 @@ #pragma once +#include "srsran/ran/plmn_identity.h" #include "srsran/scheduler/scheduler_configurator.h" namespace srsran { @@ -41,4 +42,4 @@ sched_cell_configuration_request_message make_sched_cell_config_req(du_cell_inde sched_ue_config_request create_scheduler_ue_config_request(const du_ue& u); } // namespace srs_du -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/lib/du_manager/du_ue/du_ue.h b/lib/du_manager/du_ue/du_ue.h index 426bebe968..ebe15caa9c 100644 --- a/lib/du_manager/du_ue/du_ue.h +++ b/lib/du_manager/du_ue/du_ue.h @@ -33,8 +33,12 @@ namespace srs_du { /// \brief This class holds the context of an UE in the DU. struct du_ue_context { - du_ue_context(du_ue_index_t ue_index_, du_cell_index_t pcell_index_, rnti_t rnti_) : - ue_index(ue_index_), rnti(rnti_), f1ap_ue_id(int_to_gnb_du_ue_f1ap_id(ue_index_)), pcell_index(pcell_index_) + du_ue_context(du_ue_index_t ue_index_, du_cell_index_t pcell_index_, rnti_t rnti_, nr_cell_global_id_t nr_cgi_) : + ue_index(ue_index_), + rnti(rnti_), + f1ap_ue_id(int_to_gnb_du_ue_f1ap_id(ue_index_)), + pcell_index(pcell_index_), + nr_cgi(nr_cgi_) { } @@ -42,6 +46,8 @@ struct du_ue_context { rnti_t rnti = rnti_t::INVALID_RNTI; gnb_du_ue_f1ap_id_t f1ap_ue_id; du_cell_index_t pcell_index; + /// \brief The NR Cell Global Identity of the UE's serving cell. + nr_cell_global_id_t nr_cgi; }; /// The interface exposes the methods to interact with the state of a DU UE. diff --git a/lib/du_manager/procedures/ue_creation_procedure.cpp b/lib/du_manager/procedures/ue_creation_procedure.cpp index 58863e46d5..9a5c85db9f 100644 --- a/lib/du_manager/procedures/ue_creation_procedure.cpp +++ b/lib/du_manager/procedures/ue_creation_procedure.cpp @@ -110,8 +110,10 @@ expected ue_creation_procedure::create_du_ue_context() return make_unexpected(ue_res.get_error()); } + // Fetch the DU cell configuration of the primary cell UE is connected to. + const auto& cell_cfg = du_params.ran.cells[req.pcell_index]; // Create the DU UE context. - return ue_mng.add_ue(du_ue_context(req.ue_index, req.pcell_index, req.tc_rnti), std::move(ue_res)); + return ue_mng.add_ue(du_ue_context(req.ue_index, req.pcell_index, req.tc_rnti, cell_cfg.nr_cgi), std::move(ue_res)); } async_task ue_creation_procedure::clear_ue() diff --git a/lib/e1ap/cu_up/CMakeLists.txt b/lib/e1ap/cu_up/CMakeLists.txt index 277b17de90..bc546e3af7 100644 --- a/lib/e1ap/cu_up/CMakeLists.txt +++ b/lib/e1ap/cu_up/CMakeLists.txt @@ -24,6 +24,8 @@ add_library(srsran_e1ap_cu_up e1ap_cu_up_impl.cpp e1ap_cu_up_connection_handler.cpp procedures/e1ap_cu_up_setup_procedure.cpp - procedures/bearer_context_modification_procedure.cpp) + procedures/bearer_context_modification_procedure.cpp + procedures/bearer_context_release_procedure.cpp + ) target_include_directories(srsran_e1ap_cu_up PRIVATE ..) target_link_libraries(srsran_e1ap_cu_up e1ap_asn1 srsran_e1ap_common) diff --git a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp index af14476199..c5ae94d9e8 100644 --- a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp +++ b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp @@ -23,6 +23,7 @@ #include "e1ap_cu_up_impl.h" #include "../common/log_helpers.h" #include "cu_up/procedures/bearer_context_modification_procedure.h" +#include "cu_up/procedures/bearer_context_release_procedure.h" #include "cu_up/procedures/e1ap_cu_up_event_manager.h" #include "e1ap_cu_up_asn1_helpers.h" #include "procedures/e1ap_cu_up_setup_procedure.h" @@ -268,38 +269,27 @@ void e1ap_cu_up_impl::handle_bearer_context_modification_request(const asn1::e1a void e1ap_cu_up_impl::handle_bearer_context_release_command(const asn1::e1ap::bearer_context_release_cmd_s& msg) { - e1ap_bearer_context_release_command bearer_context_release_cmd = {}; - if (!ue_ctxt_list.contains(int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id))) { + // create failure message for early returns + e1ap_message e1ap_msg; + e1ap_msg.pdu.set_unsuccessful_outcome(); + e1ap_msg.pdu.unsuccessful_outcome().load_info_obj(ASN1_E1AP_ID_BEARER_CONTEXT_RELEASE); + // TODO fill other values + logger.error("No UE context for the received gnb_cu_up_ue_e1ap_id={} available", msg->gnb_cu_up_ue_e1ap_id); + pdu_notifier->on_new_message(e1ap_msg); return; } - e1ap_ue_context& ue_ctxt = ue_ctxt_list[int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id)]; - - bearer_context_release_cmd.ue_index = ue_ctxt.ue_ids.ue_index; - bearer_context_release_cmd.cause = asn1_to_cause(msg->cause); + e1ap_ue_context& ue_ctxt = ue_ctxt_list[int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id)]; + ue_index_t ue_index = ue_ctxt.ue_ids.ue_index; - // Forward message to CU-UP - cu_up_notifier.on_bearer_context_release_command_received(bearer_context_release_cmd); - - // Remove UE context + // Remove UE context at E1AP before switching to UE execution context to avoid concurrent access of ue_ctxt_list ue_ctxt_list.remove_ue(ue_ctxt.ue_ids.ue_index); - e1ap_message e1ap_msg; - e1ap_msg.pdu.set_successful_outcome(); - e1ap_msg.pdu.successful_outcome().load_info_obj(ASN1_E1AP_ID_BEARER_CONTEXT_RELEASE); - e1ap_msg.pdu.successful_outcome().value.bearer_context_release_complete()->gnb_cu_cp_ue_e1ap_id = - msg->gnb_cu_cp_ue_e1ap_id; - e1ap_msg.pdu.successful_outcome().value.bearer_context_release_complete()->gnb_cu_up_ue_e1ap_id = - msg->gnb_cu_up_ue_e1ap_id; - - // send response - logger.debug("ue={} cu_up_ue_e1ap_id={} cu_cp_ue_e1ap_id={}: Sending BearerContextReleaseComplete", - bearer_context_release_cmd.ue_index, - msg->gnb_cu_up_ue_e1ap_id, - msg->gnb_cu_cp_ue_e1ap_id); - pdu_notifier->on_new_message(e1ap_msg); + // Handle the release procedure + cu_up_notifier.on_schedule_ue_async_task( + ue_index, launch_async(ue_index, msg, *pdu_notifier, cu_up_notifier, logger)); } void e1ap_cu_up_impl::handle_successful_outcome(const asn1::e1ap::successful_outcome_s& outcome) diff --git a/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp new file mode 100644 index 0000000000..0a90dcbe3a --- /dev/null +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp @@ -0,0 +1,64 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "bearer_context_release_procedure.h" +#include "common/e1ap_asn1_converters.h" +#include "srsran/e1ap/common/e1ap_message.h" +#include "srsran/e1ap/cu_up/e1ap_cu_up_bearer_context_update.h" + +using namespace srsran; +using namespace srsran::srs_cu_up; + +bearer_context_release_procedure::bearer_context_release_procedure(ue_index_t ue_index_, + const asn1::e1ap::bearer_context_release_cmd_s& cmd_, + e1ap_message_notifier& pdu_notifier_, + e1ap_cu_up_manager_notifier& cu_up_notifier_, + srslog::basic_logger& logger_) : + ue_index(ue_index_), cmd(cmd_), pdu_notifier(pdu_notifier_), cu_up_notifier(cu_up_notifier_), logger(logger_) +{ +} + +void bearer_context_release_procedure::operator()(coro_context>& ctx) +{ + CORO_BEGIN(ctx); + + bearer_context_release_cmd.ue_index = ue_index; + bearer_context_release_cmd.cause = asn1_to_cause(cmd->cause); + + // Forward message to CU-UP + CORO_AWAIT(cu_up_notifier.on_bearer_context_release_command_received(bearer_context_release_cmd)); + + e1ap_msg.pdu.set_successful_outcome(); + e1ap_msg.pdu.successful_outcome().load_info_obj(ASN1_E1AP_ID_BEARER_CONTEXT_RELEASE); + e1ap_msg.pdu.successful_outcome().value.bearer_context_release_complete()->gnb_cu_cp_ue_e1ap_id = + cmd->gnb_cu_cp_ue_e1ap_id; + e1ap_msg.pdu.successful_outcome().value.bearer_context_release_complete()->gnb_cu_up_ue_e1ap_id = + cmd->gnb_cu_up_ue_e1ap_id; + + // send response + logger.debug("ue={} cu_up_ue_e1ap_id={} cu_cp_ue_e1ap_id={}: Sending BearerContextReleaseComplete", + bearer_context_release_cmd.ue_index, + cmd->gnb_cu_up_ue_e1ap_id, + cmd->gnb_cu_cp_ue_e1ap_id); + pdu_notifier.on_new_message(e1ap_msg); + CORO_RETURN(); +} diff --git a/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h new file mode 100644 index 0000000000..5f76281d5e --- /dev/null +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "cu_up/ue_context/e1ap_cu_up_ue_context.h" +#include "srsran/asn1/e1ap/e1ap.h" +#include "srsran/asn1/e1ap/e1ap_pdu_contents.h" +#include "srsran/e1ap/common/e1ap_common.h" +#include "srsran/e1ap/common/e1ap_message.h" +#include "srsran/e1ap/cu_up/e1ap_cu_up.h" +#include "srsran/srslog/logger.h" +#include "srsran/support/async/async_task.h" + +namespace srsran::srs_cu_up { + +/// E1 Setup Procedure for the CU-UP as per TS 38.463, section TODO. +class bearer_context_release_procedure +{ +public: + bearer_context_release_procedure(ue_index_t ue_index, + const asn1::e1ap::bearer_context_release_cmd_s& cmd_, + e1ap_message_notifier& pdu_notifier_, + e1ap_cu_up_manager_notifier& cu_up_notifier_, + srslog::basic_logger& logger_); + + void operator()(coro_context>& ctx); + + static const char* name() { return "E1AP CU-UP Bearer Context Release Procedure"; } + +private: + ue_index_t ue_index; + const asn1::e1ap::bearer_context_release_cmd_s cmd; + e1ap_message_notifier& pdu_notifier; + e1ap_cu_up_manager_notifier& cu_up_notifier; + srslog::basic_logger& logger; + + // local variables + e1ap_message e1ap_msg = {}; + e1ap_bearer_context_release_command bearer_context_release_cmd = {}; +}; + +} // namespace srsran::srs_cu_up diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp index 09b85db793..ae815dd042 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.cpp @@ -147,6 +147,7 @@ void e2sm_kpm_du_meas_provider_impl::report_metrics(const rlc_metrics& metrics) ue_aggr_rlc_metrics[metrics.ue_index].pop_front(); } } + std::vector e2sm_kpm_du_meas_provider_impl::get_supported_metric_names(e2sm_kpm_metric_level_enum level) { std::vector metrics; @@ -449,20 +450,20 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_mean_throughput(const asn1::e2sm } for (auto& ue : ue_aggr_rlc_metrics) { size_t num_pdu_bytes_with_segmentation; - switch (ue.second.front().tx.mode) { + switch (ue.second.front().tx.tx_low.mode) { case rlc_mode::um_bidir: case rlc_mode::um_unidir_dl: // get average from queue num_pdu_bytes_with_segmentation = std::accumulate(ue.second.begin(), ue.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.mode_specific.um.num_pdu_bytes_with_segmentation; + return sum + metric.tx.tx_low.mode_specific.um.num_pdu_bytes_with_segmentation; }); num_pdu_bytes_with_segmentation /= ue.second.size(); break; case rlc_mode::am: num_pdu_bytes_with_segmentation = std::accumulate(ue.second.begin(), ue.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.mode_specific.am.num_pdu_bytes_with_segmentation; + return sum + metric.tx.tx_low.mode_specific.am.num_pdu_bytes_with_segmentation; }); num_pdu_bytes_with_segmentation /= ue.second.size(); break; @@ -471,7 +472,7 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_mean_throughput(const asn1::e2sm } auto num_pdu_bytes_no_segmentation = std::accumulate(ue.second.begin(), ue.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_pdu_bytes_no_segmentation; + return sum + metric.tx.tx_low.num_pdu_bytes_no_segmentation; }); num_pdu_bytes_no_segmentation /= ue.second.size(); seconds = (float)std::chrono::duration_cast(ue.second.back().metrics_period).count() / @@ -661,11 +662,11 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_rlc_packet_drop_rate_dl( for (auto& rlc_metric : ue_aggr_rlc_metrics) { total_dropped_sdus += std::accumulate( rlc_metric.second.begin(), rlc_metric.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_dropped_sdus + metric.tx.num_discarded_sdus; + return sum + metric.tx.tx_high.num_dropped_sdus + metric.tx.tx_high.num_discarded_sdus; }); total_tx_num_sdus += std::accumulate( rlc_metric.second.begin(), rlc_metric.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_sdus; + return sum + metric.tx.tx_high.num_sdus; }); } if (total_tx_num_sdus) { @@ -693,13 +694,13 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_rlc_packet_drop_rate_dl( ue_aggr_rlc_metrics[ue_idx].end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_dropped_sdus + metric.tx.num_discarded_sdus; + return sum + metric.tx.tx_high.num_dropped_sdus + metric.tx.tx_high.num_discarded_sdus; }); uint32_t total_tx_num_sdus = std::accumulate(ue_aggr_rlc_metrics[ue_idx].begin(), ue_aggr_rlc_metrics[ue_idx].end(), 0, - [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.num_sdus; }); + [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.tx_high.num_sdus; }); if (total_tx_num_sdus) { drop_rate = 1.0 * total_dropped_sdus / total_tx_num_sdus; } @@ -737,7 +738,7 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_rlc_sdu_transmitted_volume_dl( for (auto& rlc_metric : ue_aggr_rlc_metrics) { total_tx_num_sdu_bytes += std::accumulate( rlc_metric.second.begin(), rlc_metric.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_sdu_bytes; + return sum + metric.tx.tx_high.num_sdu_bytes; }); } meas_record_item.set_integer() = total_tx_num_sdu_bytes * 8 / 1000; // unit is kbit @@ -759,7 +760,7 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_rlc_sdu_transmitted_volume_dl( std::accumulate(ue_aggr_rlc_metrics[ue_idx].begin(), ue_aggr_rlc_metrics[ue_idx].end(), 0, - [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.num_sdu_bytes; }); + [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.tx_high.num_sdu_bytes; }); meas_record_item.set_integer() = num_sdu_bytes * 8 / 1000; // unit is kbit items.push_back(meas_record_item); meas_collected = true; @@ -841,11 +842,11 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_rlc_sdu_latency(const asn1::e2sm for (auto& rlc_metric : ue_aggr_rlc_metrics) { int tot_num_of_pulled_sdus = std::accumulate( rlc_metric.second.begin(), rlc_metric.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.num_of_pulled_sdus; + return sum + metric.tx.tx_low.num_of_pulled_sdus; }); int tot_sum_sdu_latency_us = std::accumulate( rlc_metric.second.begin(), rlc_metric.second.end(), 0, [](size_t sum, const rlc_metrics& metric) { - return sum + metric.tx.sum_sdu_latency_us; + return sum + metric.tx.tx_low.sum_sdu_latency_us; }); if (tot_num_of_pulled_sdus && tot_sum_sdu_latency_us) { av_ue_sdu_latency_us += (float)tot_sum_sdu_latency_us / (float)tot_num_of_pulled_sdus; @@ -871,16 +872,16 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_rlc_sdu_latency(const asn1::e2sm meas_collected = true; continue; } - int tot_sdu_latency_us = - std::accumulate(ue_aggr_rlc_metrics[ue_idx].begin(), - ue_aggr_rlc_metrics[ue_idx].end(), - 0, - [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.sum_sdu_latency_us; }); + int tot_sdu_latency_us = std::accumulate( + ue_aggr_rlc_metrics[ue_idx].begin(), + ue_aggr_rlc_metrics[ue_idx].end(), + 0, + [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.tx_low.sum_sdu_latency_us; }); int tot_num_sdus = std::accumulate(ue_aggr_rlc_metrics[ue_idx].begin(), ue_aggr_rlc_metrics[ue_idx].end(), 0, - [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.num_sdus; }); + [](size_t sum, const rlc_metrics& metric) { return sum + metric.tx.tx_high.num_sdus; }); if (tot_sdu_latency_us) { meas_record_item.set_real(); meas_record_item.real().value = tot_sdu_latency_us / tot_num_sdus; diff --git a/lib/f1ap/cu_cp/f1ap_cu_impl.cpp b/lib/f1ap/cu_cp/f1ap_cu_impl.cpp index f43e234409..60ca14276b 100644 --- a/lib/f1ap/cu_cp/f1ap_cu_impl.cpp +++ b/lib/f1ap/cu_cp/f1ap_cu_impl.cpp @@ -120,7 +120,7 @@ async_task f1ap_cu_impl::handle_ue_context_release_command(const f1a }); } - return launch_async(msg, ue_ctxt_list[msg.ue_index], tx_pdu_notifier); + return launch_async(msg, ue_ctxt_list[msg.ue_index], tx_pdu_notifier, cfg.proc_timeout); } async_task diff --git a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp index debd3d0798..e74b3b90e7 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp +++ b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp @@ -30,12 +30,14 @@ using namespace srsran; using namespace srsran::srs_cu_cp; using namespace asn1::f1ap; -constexpr std::chrono::milliseconds ue_context_release_response_timeout{1000}; - ue_context_release_procedure::ue_context_release_procedure(const f1ap_ue_context_release_command& cmd_, f1ap_ue_context& ue_ctxt_, - f1ap_message_notifier& f1ap_notif_) : - ue_ctxt(ue_ctxt_), f1ap_notifier(f1ap_notif_), logger(srslog::fetch_basic_logger("CU-CP-F1")) + f1ap_message_notifier& f1ap_notif_, + std::chrono::milliseconds proc_timeout_) : + ue_ctxt(ue_ctxt_), + f1ap_notifier(f1ap_notif_), + proc_timeout(proc_timeout_), + logger(srslog::fetch_basic_logger("CU-CP-F1")) { command->gnb_cu_ue_f1ap_id = gnb_cu_ue_f1ap_id_to_uint(ue_ctxt.ue_ids.cu_ue_f1ap_id); command->gnb_du_ue_f1ap_id = gnb_du_ue_f1ap_id_to_uint(ue_ctxt.ue_ids.du_ue_f1ap_id); @@ -57,7 +59,7 @@ void ue_context_release_procedure::operator()(coro_contextgnb_du_ue_f1ap_id == gnb_du_ue_f1ap_id_to_uint(ue_ctxt.ue_ids.du_ue_f1ap_id)) { - ret = ue_ctxt.ue_ids.ue_index; - logger.info("{}: Procedure finished successfully.", f1ap_ue_log_prefix{ue_ctxt.ue_ids, name()}); - } else { - logger.warning("{}: Procedure failed.", f1ap_ue_log_prefix{ue_ctxt.ue_ids, name()}); + if (transaction_sink.successful()) { + gnb_du_ue_f1ap_id_t du_ue_id = int_to_gnb_du_ue_f1ap_id(transaction_sink.response()->gnb_du_ue_f1ap_id); + if (du_ue_id != ue_ctxt.ue_ids.du_ue_f1ap_id) { + logger.error("{}: Procedure failed. Cause: gNB-DU-UE-F1AP-ID mismatch.", + f1ap_ue_log_prefix{ue_ctxt.ue_ids, name()}); + return ue_index_t::invalid; + } + return ue_ctxt.ue_ids.ue_index; } - return ret; + logger.warning("{}: Procedure failed. Cause: {}", + f1ap_ue_log_prefix{ue_ctxt.ue_ids, name()}, + transaction_sink.timeout_expired() ? "Timeout" : "Transaction failed"); + + return ue_index_t::invalid; } diff --git a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h index 5e6dd1e82b..1446652cc3 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h +++ b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h @@ -38,7 +38,8 @@ class ue_context_release_procedure public: ue_context_release_procedure(const f1ap_ue_context_release_command& cmd_, f1ap_ue_context& ue_ctxt_, - f1ap_message_notifier& f1ap_notif_); + f1ap_message_notifier& f1ap_notif_, + std::chrono::milliseconds proc_timeout); void operator()(coro_context>& ctx); @@ -49,11 +50,12 @@ class ue_context_release_procedure void send_ue_context_release_command(); /// Creates procedure result to send back to procedure caller. - ue_index_t create_ue_context_release_complete(const asn1::f1ap::ue_context_release_complete_s& msg); + ue_index_t create_ue_context_release_complete(); f1ap_ue_context& ue_ctxt; asn1::f1ap::ue_context_release_cmd_s command; f1ap_message_notifier& f1ap_notifier; + const std::chrono::milliseconds proc_timeout; srslog::basic_logger& logger; protocol_transaction_outcome_observer transaction_sink; diff --git a/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp b/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp index a6abe72144..342560bc64 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp +++ b/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp @@ -83,7 +83,7 @@ void ue_context_setup_procedure::operator()(coro_contextev_mng.context_setup_outcome, f1ap_cfg.ue_context_setup_timeout); + transaction_sink.subscribe_to(ue_ctxt->ev_mng.context_setup_outcome, f1ap_cfg.proc_timeout); // Send command to DU. send_ue_context_setup_request(); diff --git a/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp b/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp index 1c92880c08..379baeb02e 100644 --- a/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp +++ b/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp @@ -113,6 +113,19 @@ void f1ap_du_setup_procedure::send_f1_setup_request() auto plmn_bytes = cell_cfg.nr_cgi.plmn_id.to_bytes(); f1ap_cell.served_cell_info.served_plmns[0].plmn_id = plmn_bytes; + // Fill slicing information. + f1ap_cell.served_cell_info.served_plmns[0].ie_exts_present = not cell_cfg.slices.empty(); + f1ap_cell.served_cell_info.served_plmns[0].ie_exts.tai_slice_support_list_present = not cell_cfg.slices.empty(); + for (const s_nssai_t& s_nssai : cell_cfg.slices) { + slice_support_item_s slice{}; + slice.snssai.sst.from_number(s_nssai.sst); + slice.snssai.sd_present = s_nssai.sd.has_value(); + if (slice.snssai.sd_present) { + slice.snssai.sd.from_number(*s_nssai.sd); + } + f1ap_cell.served_cell_info.served_plmns[0].ie_exts.tai_slice_support_list.push_back(slice); + } + // Fill Served Cell Information. f1ap_cell.served_cell_info.nr_pci = cell_cfg.pci; f1ap_cell.served_cell_info.nr_cgi.plmn_id = plmn_bytes; diff --git a/lib/fapi_adaptor/precoding_matrix_table_generator.cpp b/lib/fapi_adaptor/precoding_matrix_table_generator.cpp index 896e275ab2..e9670a3b40 100644 --- a/lib/fapi_adaptor/precoding_matrix_table_generator.cpp +++ b/lib/fapi_adaptor/precoding_matrix_table_generator.cpp @@ -149,15 +149,15 @@ static void generate_2_ports_table(precoding_matrix_mapper_codebook_offset_confi offset = generate_identity_matrix(offset, repo_builder, nof_ports); mapper_offsets.ssb_codebook_offsets.push_back(offset); - offset = generate_ssb(offset, nof_ports, repo_builder); + offset = generate_ssb(offset, nof_ports, repo_builder); + mapper_offsets.pdcch_codebook_offsets.push_back(offset); + offset = generate_pdcch(offset, nof_ports, repo_builder); mapper_offsets.pdsch_omni_offset = offset; offset = generate_pdsch_omnidirectional(offset, nof_ports, repo_builder); mapper_offsets.pdsch_codebook_offsets.push_back(offset); offset = generate_pdsch_2_ports_1_layer(offset, repo_builder); mapper_offsets.pdsch_codebook_offsets.push_back(offset); offset = generate_pdsch_2_ports_2_layers(offset, repo_builder); - mapper_offsets.pdcch_codebook_offsets.push_back(offset); - offset = generate_pdcch(offset, nof_ports, repo_builder); mapper_offsets.csi_rs_codebook_offsets.push_back(offset); generate_csi_rs(offset, nof_ports, repo_builder); } @@ -237,7 +237,9 @@ static void generate_4_ports_table(precoding_matrix_mapper_codebook_offset_confi offset = generate_identity_matrix(offset, repo_builder, nof_ports); mapper_offsets.ssb_codebook_offsets.push_back(offset); - offset = generate_ssb(offset, nof_ports, repo_builder); + offset = generate_ssb(offset, nof_ports, repo_builder); + mapper_offsets.pdcch_codebook_offsets.push_back(offset); + offset = generate_pdcch(offset, nof_ports, repo_builder); mapper_offsets.pdsch_omni_offset = offset; offset = generate_pdsch_omnidirectional(offset, nof_ports, repo_builder); mapper_offsets.pdsch_codebook_offsets.push_back(offset); @@ -248,8 +250,6 @@ static void generate_4_ports_table(precoding_matrix_mapper_codebook_offset_confi offset = generate_pdsch_4_ports_3_layers(offset, repo_builder); mapper_offsets.pdsch_codebook_offsets.push_back(offset); offset = generate_pdsch_4_ports_4_layers(offset, repo_builder); - mapper_offsets.pdcch_codebook_offsets.push_back(offset); - offset = generate_pdcch(offset, nof_ports, repo_builder); mapper_offsets.csi_rs_codebook_offsets.push_back(offset); generate_csi_rs(offset, nof_ports, repo_builder); } diff --git a/lib/mac/mac_dl/paging_pdu_assembler.cpp b/lib/mac/mac_dl/paging_pdu_assembler.cpp index a45e6fafbc..bde0f5b20e 100644 --- a/lib/mac/mac_dl/paging_pdu_assembler.cpp +++ b/lib/mac/mac_dl/paging_pdu_assembler.cpp @@ -51,7 +51,7 @@ static asn1::rrc_nr::paging_s make_asn1_rrc_cell_paging_msg(const dl_paging_allo /// \return byte buffer with packed cell PCCH-PCH message. static byte_buffer make_asn1_rrc_cell_pcch_pch_msg(const dl_paging_allocation& pg) { - byte_buffer buf; + byte_buffer buf{byte_buffer::fallback_allocation_tag{}}; asn1::bit_ref bref{buf}; asn1::rrc_nr::pcch_msg_s pcch_msg{}; diff --git a/lib/nru/nru_packing.cpp b/lib/nru/nru_packing.cpp index e377002854..3e687cfd13 100644 --- a/lib/nru/nru_packing.cpp +++ b/lib/nru/nru_packing.cpp @@ -87,14 +87,23 @@ bool nru_packing::unpack(nru_dl_user_data& dl_user_data, byte_buffer_view contai // Report polling VERIFY_READ(decoder.unpack(dl_user_data.report_polling, 1)); - // Spare (v15.2.0) + // Spare (v16.1.0) spare = {}; - VERIFY_READ(decoder.unpack(spare, 6)); + VERIFY_READ(decoder.unpack(spare, 3)); if (spare != 0) { logger.error("Failed to unpack DL user data: Spare bits set in second octet. value={:#x}", spare); return false; } + // Request OutOfSeq Report + decoder.unpack(dl_user_data.request_out_of_seq_report, 1); + + // Report Delivered + decoder.unpack(dl_user_data.report_delivered, 1); + + // User data existence flag + decoder.unpack(dl_user_data.user_data_existence_flag, 1); + // Assistance Info Report Polling Flag decoder.unpack(dl_user_data.assist_info_report_polling_flag, 1); @@ -133,6 +142,11 @@ bool nru_packing::unpack(nru_dl_user_data& dl_user_data, byte_buffer_view contai } } + // DL report NR PDCP PDU SN + if (dl_user_data.report_delivered) { + VERIFY_READ(decoder.unpack(dl_user_data.dl_report_pdcp_sn, 24)); + } + return true; }; @@ -157,8 +171,17 @@ bool nru_packing::pack(byte_buffer& out_buf, const nru_dl_user_data& dl_user_dat // Report polling VERIFY_WRITE(encoder.pack(dl_user_data.report_polling, 1)); - // Spare (v15.2.0) - VERIFY_WRITE(encoder.pack(0, 6)); + // Spare (v16.1.0) + VERIFY_WRITE(encoder.pack(0, 3)); + + // Request OutOfSeq Report + VERIFY_WRITE(encoder.pack(dl_user_data.request_out_of_seq_report, 1)); + + // Report Delivered + VERIFY_WRITE(encoder.pack(dl_user_data.report_delivered, 1)); + + // User data existence flag + VERIFY_WRITE(encoder.pack(dl_user_data.user_data_existence_flag, 1)); // Assistance Info Report Polling Flag VERIFY_WRITE(encoder.pack(dl_user_data.assist_info_report_polling_flag, 1)); @@ -186,6 +209,11 @@ bool nru_packing::pack(byte_buffer& out_buf, const nru_dl_user_data& dl_user_dat } } + // DL report NR PDCP PDU SN + if (dl_user_data.report_delivered) { + VERIFY_WRITE(encoder.pack(dl_user_data.dl_report_pdcp_sn, 24)); + } + // Add padding such that length is (n*4-2) octets, where n is a positive integer. while (((out_buf.length() - start_len) + 2) % 4) { VERIFY_WRITE(out_buf.append(0x0)); diff --git a/lib/phy/support/resource_grid_mapper_impl.cpp b/lib/phy/support/resource_grid_mapper_impl.cpp index f9f283c5d0..741893cf45 100644 --- a/lib/phy/support/resource_grid_mapper_impl.cpp +++ b/lib/phy/support/resource_grid_mapper_impl.cpp @@ -284,7 +284,7 @@ void resource_grid_mapper_impl::map(symbol_buffer& buffer, { // Temporary intermediate buffer for storing precoded symbols. static_re_buffer precoding_buffer_copy; - modular_re_buffer_writer precoding_buffer_view; + modular_re_buffer_writer precoding_buffer_view; // The number of layers is equal to the number of ports. unsigned nof_layers = precoding.get_nof_layers(); diff --git a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h index 2237253fc2..340ab9eded 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h @@ -58,7 +58,6 @@ class pusch_demodulator_impl : public pusch_demodulator evm_calc(std::move(evm_calc_)), descrambler(std::move(descrambler_)), ch_re_copy(MAX_PORTS, max_nof_rb * NRE), - ch_re_view(pusch_constants::MAX_NOF_RX_PORTS), temp_eq_re(max_nof_rb * NRE * pusch_constants::MAX_NOF_LAYERS), temp_eq_noise_vars(max_nof_rb * NRE * pusch_constants::MAX_NOF_LAYERS), ch_estimates_copy(max_nof_rb * NRE, pusch_constants::MAX_NOF_RX_PORTS, pusch_constants::MAX_NOF_LAYERS), @@ -227,7 +226,7 @@ class pusch_demodulator_impl : public pusch_demodulator /// Copy buffer used to transfer channel modulation symbols from the resource grid to the equalizer. dynamic_re_buffer ch_re_copy; /// View buffer used to transfer channel modulation symbols from the resource grid to the equalizer. - modular_re_buffer_reader ch_re_view; + modular_re_buffer_reader ch_re_view; /// Buffer used to store channel modulation resource elements at the equalizer output. std::vector temp_eq_re; /// Buffer used to transfer symbol noise variances at the equalizer output. @@ -235,7 +234,7 @@ class pusch_demodulator_impl : public pusch_demodulator /// Copy buffer used to transfer channel estimation coefficients from the channel estimate to the equalizer. dynamic_ch_est_list ch_estimates_copy; /// View buffer used to transfer channel estimation coefficients from the channel estimate to the equalizer. - modular_ch_est_list ch_estimates_view; + modular_ch_est_list ch_estimates_view; /// Buffer used to transfer noise variance estimates from the channel estimate to the equalizer. std::array noise_var_estimates; diff --git a/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp b/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp index 588d2254a3..36d01d83d8 100644 --- a/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp +++ b/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp @@ -28,6 +28,8 @@ #include "equalize_zf_1xn.h" #include "equalize_zf_2xn.h" #include "srsran/adt/interval.h" +#include "srsran/phy/support/re_buffer.h" +#include "srsran/phy/upper/equalization/modular_ch_est_list.h" using namespace srsran; @@ -128,6 +130,62 @@ void equalize_zf_single_tx_layer<1>(unsigned /**/, equalize_zf_1xn<1>(eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var, tx_scaling); } +template +void equalize_zf_single_tx_layer_reduction(span eq_symbols, + span eq_noise_vars, + const re_buffer_reader& ch_symbols, + const channel_equalizer::ch_est_list& ch_estimates, + span noise_var, + float tx_scaling) +{ + unsigned nof_ports = noise_var.size(); + + // Function for checking if a noise variance is valid. + const auto func_valid_noise_var = [](float nvar) { + return (nvar > 0) && (nvar < std::numeric_limits::infinity()); + }; + + // Count the number of valid noise variances. + unsigned nof_valid_noise_var = std::count_if(noise_var.begin(), noise_var.end(), func_valid_noise_var); + + // No valid noise variances, fill output with invalid data. + if (nof_valid_noise_var == 0) { + srsvec::zero(eq_symbols); + srsvec::fill(eq_noise_vars, std::numeric_limits::infinity()); + return; + } + + // Exclude the ports that are invalid. + if (nof_valid_noise_var != nof_ports) { + // Reduce ports. + static_vector reduced_noise_var(nof_valid_noise_var); + modular_re_buffer_reader reduced_ch_symbols(nof_ports, ch_symbols.get_nof_re()); + modular_ch_est_list reduced_ch_estimates(nof_ports, ch_symbols.get_nof_re()); + for (unsigned i_port = 0, i_reduced_port = 0; i_port != nof_ports; ++i_port) { + if (func_valid_noise_var(noise_var[i_port])) { + reduced_noise_var[i_reduced_port] = noise_var[i_port]; + reduced_ch_symbols.set_slice(i_reduced_port, ch_symbols.get_slice(i_port)); + reduced_ch_estimates.set_channel(ch_estimates.get_channel(i_port, 0), i_reduced_port, 0); + ++i_reduced_port; + } + } + + // Equalize. The number of ports must be at least one less than before. + equalize_zf_single_tx_layer(nof_valid_noise_var, + eq_symbols, + eq_noise_vars, + reduced_ch_symbols, + reduced_ch_estimates, + reduced_noise_var, + tx_scaling); + return; + } + + // Perform equalization for all ports. + equalize_zf_single_tx_layer( + nof_valid_noise_var, eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var, tx_scaling); +} + /// Calls the equalizer function for receive spatial diversity with the appropriate number of receive ports. template void equalize_mmse_single_tx_layer(unsigned nof_ports, @@ -185,8 +243,8 @@ void channel_equalizer_generic_impl::equalize(span e if (type == channel_equalizer_algorithm_type::zf) { // Single transmit layer and any number of receive ports. if (nof_tx_layers == 1) { - equalize_zf_single_tx_layer( - nof_rx_ports, eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var_estimates, tx_scaling); + equalize_zf_single_tx_layer_reduction( + eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var_estimates, tx_scaling); return; } diff --git a/lib/phy/upper/equalization/equalize_zf_1xn.h b/lib/phy/upper/equalization/equalize_zf_1xn.h index c816c36ebc..a3665a426c 100644 --- a/lib/phy/upper/equalization/equalize_zf_1xn.h +++ b/lib/phy/upper/equalization/equalize_zf_1xn.h @@ -86,12 +86,8 @@ void equalize_zf_1xn(span symbols_out, // Load noise variance in a SIMD register. simd_f_t port_noise_var_est = srsran_simd_f_set1(noise_var_est[i_port]); - // Detect abnormal computation parameters. This detects whether the channel estimate and the port noise variance - // estimation are negative, NaN or infinite. - simd_sel_t isnormal_mask = srsran_simd_f_max(ch_est_norm, zero); - isnormal_mask = srsran_simd_sel_and(isnormal_mask, srsran_simd_f_max(infinity, ch_est_norm)); - isnormal_mask = srsran_simd_sel_and(isnormal_mask, srsran_simd_f_max(port_noise_var_est, zero)); - isnormal_mask = srsran_simd_sel_and(isnormal_mask, srsran_simd_f_max(infinity, port_noise_var_est)); + // Detect an abnormal computation parameter. This detects whether the channel estimate is NaN or infinite. + simd_sel_t isnormal_mask = srsran_simd_f_max(infinity, ch_est_norm); // Compute the channel square norm, by accumulating the channel square absolute values. ch_mod_sq = srsran_simd_f_add_sel(ch_mod_sq, ch_est_norm, isnormal_mask); @@ -118,12 +114,6 @@ void equalize_zf_1xn(span symbols_out, // Calculate noise variances. simd_f_t vars_out = srsran_simd_f_mul(nvar_acc, srsran_simd_f_mul(d_pinv_rcp, d_pinv_rcp)); - // Detect whenever the post-equalization noise variances are zero, negative or NaN. - isnormal_mask = srsran_simd_sel_and(isnormal_mask, srsran_simd_f_max(vars_out, zero)); - - // Detect whenever the post-equalization noise variances are set to infinity. - isnormal_mask = srsran_simd_sel_and(isnormal_mask, srsran_simd_f_max(infinity, vars_out)); - // If abnormal calculation parameters are detected, the noise variances are set to infinity. srsran_simd_f_storeu(nvars_out.data() + i_re, srsran_simd_f_select(infinity, vars_out, isnormal_mask)); diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 73a21eed83..f7262eb1c0 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -350,7 +350,7 @@ static std::shared_ptr create_ul_processor_factory(con create_low_papr_sequence_generator_sw_factory(); report_fatal_error_if_not(sequence_factory, "Invalid sequence factory."); - std::shared_ptr dft_factory = create_dft_processor_factory_fftw_fast(); + std::shared_ptr dft_factory = create_dft_processor_factory_fftw_slow(); if (!dft_factory) { dft_factory = create_dft_processor_factory_generic(); report_fatal_error_if_not(dft_factory, "Invalid DFT factory."); diff --git a/lib/rlc/CMakeLists.txt b/lib/rlc/CMakeLists.txt index 2055998453..64f54c672f 100644 --- a/lib/rlc/CMakeLists.txt +++ b/lib/rlc/CMakeLists.txt @@ -27,6 +27,7 @@ set(SOURCES rlc_rx_am_entity.cpp rlc_rx_tm_entity.cpp rlc_rx_um_entity.cpp + rlc_metrics_aggregator.cpp ) add_library(srsran_rlc STATIC ${SOURCES}) diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index 892c1e57b8..f2195ad686 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -41,16 +41,11 @@ class rlc_am_entity : public rlc_base_entity rlc_tx_upper_layer_data_notifier& tx_upper_dn, rlc_tx_upper_layer_control_notifier& tx_upper_cn, rlc_tx_lower_layer_notifier& tx_lower_dn, - timer_manager& timers, + rlc_pcap& pcap, task_executor& pcell_executor, task_executor& ue_executor, - rlc_pcap& pcap) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + timer_manager& timers) : + rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor) { // Create AM entities std::unique_ptr tx_am = std::make_unique(gnb_du_id_, @@ -60,20 +55,22 @@ class rlc_am_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - timer_factory{timers, pcell_executor}, + metrics_agg, + metrics_period.count() != 0, + pcap, pcell_executor, ue_executor, - metrics_period.count() != 0, - pcap); + timers); std::unique_ptr rx_am = std::make_unique(gnb_du_id_, ue_index_, rb_id_, config.rx, rx_upper_dn, - timer_factory{timers, ue_executor}, - ue_executor, + metrics_agg, metrics_period.count() != 0, - pcap); + pcap, + ue_executor, + timers); // Tx/Rx interconnect tx_am->set_status_provider(rx_am.get()); diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index d089fae34e..6bb80db66a 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -44,18 +44,13 @@ class rlc_base_entity : public rlc_entity rb_id_t rb_id_, timer_duration metrics_period_, rlc_metrics_notifier* rlc_metrics_notifier_, - timer_factory timers) : + task_executor& ue_executor_) : logger("RLC", {gnb_du_id_, ue_index_, rb_id_, "DL/UL"}), ue_index(ue_index_), rb_id(rb_id_), metrics_period(metrics_period_), - metrics_timer(timers.create_timer()) + metrics_agg(gnb_du_id_, ue_index, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor_) { - rlc_metrics_notif = rlc_metrics_notifier_; - if (metrics_period.count() != 0) { - metrics_timer.set(metrics_period, [this](timer_id_t /*tid*/) { push_metrics(); }); - metrics_timer.run(); - } } ~rlc_base_entity() override = default; rlc_base_entity(const rlc_base_entity&) = delete; @@ -93,12 +88,6 @@ class rlc_base_entity : public rlc_entity return metrics; } - void reset_metrics() - { - tx->reset_metrics(); - rx->reset_metrics(); - } - protected: rlc_bearer_logger logger; du_ue_index_t ue_index; @@ -106,21 +95,7 @@ class rlc_base_entity : public rlc_entity std::unique_ptr tx; std::unique_ptr rx; timer_duration metrics_period; - -private: - unique_timer metrics_timer; - rlc_metrics_notifier* rlc_metrics_notif; - - void push_metrics() - { - rlc_metrics m = get_metrics(); - m.metrics_period = metrics_period; - if (rlc_metrics_notif) { - rlc_metrics_notif->report_metrics(m); - } - reset_metrics(); - metrics_timer.run(); - } + rlc_metrics_aggregator metrics_agg; }; } // namespace srsran diff --git a/lib/rlc/rlc_factory.cpp b/lib/rlc/rlc_factory.cpp index 55f0d19adf..01a776d688 100644 --- a/lib/rlc/rlc_factory.cpp +++ b/lib/rlc/rlc_factory.cpp @@ -41,10 +41,10 @@ std::unique_ptr srsran::create_rlc_entity(const rlc_entity_creation_ *msg.tx_upper_dn, *msg.tx_upper_cn, *msg.tx_lower_dn, - *msg.timers, + *msg.pcap_writer, *msg.pcell_executor, *msg.ue_executor, - *msg.pcap_writer); + *msg.timers); case rlc_mode::um_unidir_dl: case rlc_mode::um_unidir_ul: case rlc_mode::um_bidir: @@ -58,10 +58,10 @@ std::unique_ptr srsran::create_rlc_entity(const rlc_entity_creation_ *msg.tx_upper_dn, *msg.tx_upper_cn, *msg.tx_lower_dn, - *msg.timers, + *msg.pcap_writer, *msg.pcell_executor, *msg.ue_executor, - *msg.pcap_writer); + *msg.timers); case rlc_mode::am: return std::make_unique(msg.gnb_du_id, msg.ue_index, @@ -73,10 +73,10 @@ std::unique_ptr srsran::create_rlc_entity(const rlc_entity_creation_ *msg.tx_upper_dn, *msg.tx_upper_cn, *msg.tx_lower_dn, - *msg.timers, + *msg.pcap_writer, *msg.pcell_executor, *msg.ue_executor, - *msg.pcap_writer); + *msg.timers); default: srsran_terminate("RLC mode not supported."); } diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp new file mode 100644 index 0000000000..54cada0545 --- /dev/null +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -0,0 +1,91 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include "rlc_metrics_aggregator.h" + +using namespace srsran; + +rlc_metrics_aggregator::rlc_metrics_aggregator(gnb_du_id_t du_, + du_ue_index_t ue_, + rb_id_t rb_, + timer_duration metrics_period_, + rlc_metrics_notifier* rlc_metrics_notif_, + task_executor& ue_executor_) : + du(du_), + ue(ue_), + rb(rb_), + metrics_period(metrics_period_), + rlc_metrics_notif(rlc_metrics_notif_), + ue_executor(ue_executor_), + logger("RLC", {du_, ue_, rb_, "DL/UL"}) +{ + m_lower.counter = UINT32_MAX; + m_higher.counter = UINT32_MAX; + m_rx_high.counter = UINT32_MAX; +} + +void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) +{ + if (not ue_executor.execute([this, m_higher_]() { push_tx_high_metrics_impl(m_higher_); })) { + logger.log_error("Could not push TX high metrics"); + } +} + +void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) +{ + if (not ue_executor.execute([this, m_lower_]() { push_tx_low_metrics_impl(m_lower_); })) { + logger.log_error("Could not push TX low metrics"); + } +} + +void rlc_metrics_aggregator::push_rx_high_metrics(rlc_rx_metrics m_rx_high_) +{ + if (not ue_executor.execute([this, m_rx_high_]() { push_rx_high_metrics_impl(m_rx_high_); })) { + logger.log_error("Could not push RX high metrics"); + } +} + +void rlc_metrics_aggregator::push_tx_high_metrics_impl(rlc_tx_metrics_higher m_higher_) +{ + m_higher = m_higher_; + push_report(); +} + +void rlc_metrics_aggregator::push_tx_low_metrics_impl(rlc_tx_metrics_lower m_lower_) +{ + m_lower = m_lower_; + push_report(); +} + +void rlc_metrics_aggregator::push_rx_high_metrics_impl(rlc_rx_metrics m_rx_high_) +{ + m_rx_high = m_rx_high_; + push_report(); +} + +void rlc_metrics_aggregator::push_report() +{ + if (m_lower.counter != m_higher.counter || m_lower.counter != m_rx_high.counter) { + return; + } + rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, m_rx_high, 0, metrics_period}; + rlc_metrics_notif->report_metrics(report); +} diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h new file mode 100644 index 0000000000..c7f456188c --- /dev/null +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -0,0 +1,74 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "rlc_bearer_logger.h" +#include "srsran/ran/gnb_du_id.h" +#include "srsran/rlc/rlc_metrics.h" + +namespace srsran { +class rlc_metrics_aggregator +{ +public: + rlc_metrics_aggregator(gnb_du_id_t du, + du_ue_index_t ue, + rb_id_t rb, + timer_duration metrics_period_, + rlc_metrics_notifier* rlc_metrics_notif_, + task_executor& ue_executor_); + + // \brief push metrics from the lower RLC executor to the aggregator + // This will be called will transfer the execution by pushing a copy to + // ue executor + void push_tx_low_metrics(rlc_tx_metrics_lower m_lower_); + // \brief push metrics from the high RLC executors to the aggregator + // As these are called from the UE executor no execution transfer is required. + void push_tx_high_metrics(rlc_tx_metrics_higher m_higher_); + // \brief push metrics from the high RLC executors to the aggregator + // As these are called from the UE executor no execution transfer is required. + void push_rx_high_metrics(rlc_rx_metrics m_rx_high_); + +private: + // \brief build and push metrics report to the metrics notifier. + // Must be run from the UE executor. + void push_report(); + + void push_tx_high_metrics_impl(rlc_tx_metrics_higher m_higher_); + void push_tx_low_metrics_impl(rlc_tx_metrics_lower m_lower_); + void push_rx_high_metrics_impl(rlc_rx_metrics m_rx_high_); + + gnb_du_id_t du; + du_ue_index_t ue; + rb_id_t rb; + rlc_tx_metrics_lower m_lower; + rlc_tx_metrics_higher m_higher; + rlc_rx_metrics m_rx_high; + timer_duration metrics_period; + + rlc_metrics_notifier* rlc_metrics_notif; + + task_executor& ue_executor; + + rlc_bearer_logger logger; +}; +} // namespace srsran diff --git a/lib/rlc/rlc_rx_am_entity.cpp b/lib/rlc/rlc_rx_am_entity.cpp index a48bbf5d52..8afc94eee4 100644 --- a/lib/rlc/rlc_rx_am_entity.cpp +++ b/lib/rlc/rlc_rx_am_entity.cpp @@ -32,11 +32,12 @@ rlc_rx_am_entity::rlc_rx_am_entity(gnb_du_id_t gnb_du_id, rb_id_t rb_id, const rlc_rx_am_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - timer_factory timers, - task_executor& ue_executor_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_enabled, pcap_), + rlc_pcap& pcap_, + task_executor& ue_executor_, + timer_manager& timers) : + rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_agg_, metrics_enabled, pcap_, ue_executor_, timers), cfg(config), mod(cardinality(to_number(cfg.sn_field_length))), am_window_size(window_size(to_number(cfg.sn_field_length))), @@ -44,8 +45,8 @@ rlc_rx_am_entity::rlc_rx_am_entity(gnb_du_id_t gnb_du_id, status_buf({rlc_am_status_pdu(cfg.sn_field_length), rlc_am_status_pdu(cfg.sn_field_length), rlc_am_status_pdu(cfg.sn_field_length)}), - status_prohibit_timer(timers.create_timer()), - reassembly_timer(timers.create_timer()), + status_prohibit_timer(ue_timer_factory.create_timer()), + reassembly_timer(ue_timer_factory.create_timer()), ue_executor(ue_executor_), pcap_context(ue_index, rb_id, config) { diff --git a/lib/rlc/rlc_rx_am_entity.h b/lib/rlc/rlc_rx_am_entity.h index 93e5c749e2..7cecee0381 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -149,22 +149,28 @@ class rlc_rx_am_entity : public rlc_rx_entity, public rlc_rx_am_status_provider pcap_rlc_pdu_context pcap_context; + bool stopped = false; + public: rlc_rx_am_entity(gnb_du_id_t gnb_du_id, du_ue_index_t ue_index, rb_id_t rb_id, const rlc_rx_am_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - timer_factory timers, - task_executor& ue_executor, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor_, + timer_manager& timers); void stop() final { // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically - status_prohibit_timer.stop(); - reassembly_timer.stop(); + if (not stopped) { + status_prohibit_timer.stop(); + reassembly_timer.stop(); + stopped = true; + } }; // Rx/Tx interconnect @@ -325,21 +331,21 @@ namespace fmt { template <> struct formatter { template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + auto parse(ParseContext& ctx) { return ctx.begin(); } template auto format(const srsran::rlc_rx_am_sdu_info& info, FormatContext& ctx) - -> decltype(std::declval().out()) { if (std::holds_alternative(info.sdu_data)) { // full SDU const srsran::byte_buffer_slice& payload = std::get(info.sdu_data); return format_to( ctx.out(), "has_gap={} fully_received={} sdu_len={}", info.has_gap, info.fully_received, payload.length()); - } else if (std::holds_alternative(info.sdu_data)) { + } + if (std::holds_alternative(info.sdu_data)) { // segmented SDU const srsran::rlc_rx_am_sdu_info::segment_set_t& segments = std::get(info.sdu_data); @@ -357,13 +363,13 @@ struct formatter { template <> struct formatter { template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + auto parse(ParseContext& ctx) { return ctx.begin(); } template - auto format(const srsran::rlc_rx_am_state& st, FormatContext& ctx) -> decltype(std::declval().out()) + auto format(const srsran::rlc_rx_am_state& st, FormatContext& ctx) { return format_to(ctx.out(), "rx_next={} rx_next_status_trigger={} rx_highest_status={} rx_next_highest={}", diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index 3d33e5d791..16878c8715 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -23,6 +23,7 @@ #pragma once #include "rlc_bearer_logger.h" +#include "rlc_metrics_aggregator.h" #include "rlc_rx_metrics_container.h" #include "srsran/pcap/rlc_pcap.h" #include "srsran/rlc/rlc_rx.h" @@ -31,23 +32,45 @@ namespace srsran { /// Base class used for receiving RLC bearers. /// It provides interfaces for the RLC bearers, for the lower layers -class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics +class rlc_rx_entity : public rlc_rx_lower_layer_interface { protected: rlc_rx_entity(gnb_du_id_t gnb_du_id, du_ue_index_t ue_index, rb_id_t rb_id, rlc_rx_upper_layer_data_notifier& upper_dn_, - bool metrics_enable, - rlc_pcap& pcap_) : - logger("RLC", {gnb_du_id, ue_index, rb_id, "UL"}), upper_dn(upper_dn_), metrics(metrics_enable), pcap(pcap_) + rlc_metrics_aggregator& metrics_agg_, + bool metrics_enabled, + rlc_pcap& pcap_, + task_executor& ue_executor_, + timer_manager& timers) : + logger("RLC", {gnb_du_id, ue_index, rb_id, "UL"}), + upper_dn(upper_dn_), + metrics(metrics_enabled), + pcap(pcap_), + ue_timer_factory{timers, ue_executor_}, + high_metrics_timer(ue_timer_factory.create_timer()), + metrics_agg(metrics_agg_) { + if (metrics_enabled) { + high_metrics_timer.set(std::chrono::milliseconds(1000), [this](timer_id_t tid) { + metrics_agg.push_rx_high_metrics(metrics.get_and_reset_metrics()); + high_metrics_timer.run(); + }); + high_metrics_timer.run(); + } } rlc_bearer_logger logger; rlc_rx_upper_layer_data_notifier& upper_dn; rlc_rx_metrics_container metrics; rlc_pcap& pcap; + timer_factory ue_timer_factory; + + unique_timer high_metrics_timer; + +private: + rlc_metrics_aggregator& metrics_agg; public: /// \brief Stops all internal timers. @@ -61,7 +84,6 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics virtual void stop() = 0; rlc_rx_metrics get_metrics() { return metrics.get_metrics(); } - void reset_metrics() { return metrics.reset_metrics(); } }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index 98073d92ef..f4dbde0624 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -23,15 +23,12 @@ #pragma once #include "srsran/rlc/rlc_rx_metrics.h" -#include "srsran/srslog/srslog.h" -#include namespace srsran { class rlc_rx_metrics_container { rlc_rx_metrics metrics = {}; - std::mutex metrics_mutex; bool enabled = false; public: @@ -42,7 +39,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.mode = mode; } @@ -51,7 +47,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_sdus += num_sdus_; metrics.num_sdu_bytes += num_sdu_bytes_; } @@ -61,7 +56,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_pdus += num_pdus_; metrics.num_pdu_bytes += num_pdu_bytes_; } @@ -71,7 +65,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_lost_pdus += num_pdus_; } @@ -80,7 +73,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_malformed_pdus += num_pdus_; } @@ -89,7 +81,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.sdu_latency_us += sdu_latency_us_; } @@ -99,7 +90,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); srsran_assert(metrics.mode == rlc_mode::am, "Wrong mode for AM metrics."); metrics.mode_specific.am.num_ctrl_pdus += num_ctrl_; metrics.mode_specific.am.num_ctrl_pdu_bytes += num_ctrl_pdu_bytes_; @@ -111,8 +101,7 @@ class rlc_rx_metrics_container if (not enabled) { return {}; } - std::lock_guard lock(metrics_mutex); - return metrics; + return metrics.get(); } rlc_rx_metrics get_and_reset_metrics() @@ -121,10 +110,8 @@ class rlc_rx_metrics_container if (not enabled) { return {}; } - std::lock_guard lock(metrics_mutex); - rlc_rx_metrics ret = metrics; - metrics = {}; - metrics.mode = ret.mode; + rlc_rx_metrics ret = metrics.get(); + reset_metrics(); return ret; } @@ -134,10 +121,11 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); - rlc_mode tmp_mode = metrics.mode; - metrics = {}; - metrics.mode = tmp_mode; + rlc_mode tmp_mode = metrics.mode; + uint32_t tmp_counter = metrics.counter; + metrics = {}; + metrics.mode = tmp_mode; + metrics.counter = tmp_counter; } }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_tm_entity.cpp b/lib/rlc/rlc_rx_tm_entity.cpp index 2e16176aea..616b7141a2 100644 --- a/lib/rlc/rlc_rx_tm_entity.cpp +++ b/lib/rlc/rlc_rx_tm_entity.cpp @@ -29,9 +29,12 @@ rlc_rx_tm_entity::rlc_rx_tm_entity(gnb_du_id_t gnb_du_id, rb_id_t rb_id, const rlc_rx_tm_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_enabled, pcap_), + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers) : + rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_agg_, metrics_enabled, pcap_, ue_executor, timers), cfg(config), pcap_context(ue_index, rb_id, /* is_uplink */ true) { diff --git a/lib/rlc/rlc_rx_tm_entity.h b/lib/rlc/rlc_rx_tm_entity.h index 5deef19a17..5039c43473 100644 --- a/lib/rlc/rlc_rx_tm_entity.h +++ b/lib/rlc/rlc_rx_tm_entity.h @@ -23,25 +23,23 @@ #pragma once #include "rlc_rx_entity.h" +#include "srsran/rlc/rlc_metrics.h" namespace srsran { class rlc_rx_tm_entity : public rlc_rx_entity { -private: - // Config storage - const rlc_rx_tm_config cfg; - - pcap_rlc_pdu_context pcap_context; - public: rlc_rx_tm_entity(gnb_du_id_t gnb_du_id, du_ue_index_t ue_index, rb_id_t rb_id, const rlc_rx_tm_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers); void stop() final { @@ -50,6 +48,12 @@ class rlc_rx_tm_entity : public rlc_rx_entity // Interfaces for higher layers void handle_pdu(byte_buffer_slice buf) override; + +private: + // Config storage + const rlc_rx_tm_config cfg; + + pcap_rlc_pdu_context pcap_context; }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_um_entity.cpp b/lib/rlc/rlc_rx_um_entity.cpp index dec019ff9f..2de0432f4f 100644 --- a/lib/rlc/rlc_rx_um_entity.cpp +++ b/lib/rlc/rlc_rx_um_entity.cpp @@ -30,16 +30,17 @@ rlc_rx_um_entity::rlc_rx_um_entity(gnb_du_id_t gnb_du_id, rb_id_t rb_id, const rlc_rx_um_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - timer_factory timers, - task_executor& ue_executor, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enable, - rlc_pcap& pcap_) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_enable, pcap_), + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers) : + rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_agg_, metrics_enable, pcap_, ue_executor, timers), cfg(config), mod(cardinality(to_number(cfg.sn_field_length))), um_window_size(window_size(to_number(cfg.sn_field_length))), rx_window(create_rx_window(cfg.sn_field_length)), - reassembly_timer(timers.create_timer()), + reassembly_timer(ue_timer_factory.create_timer()), pcap_context(ue_index, rb_id, config) { metrics.metrics_set_mode(rlc_mode::um_bidir); diff --git a/lib/rlc/rlc_rx_um_entity.h b/lib/rlc/rlc_rx_um_entity.h index 7011fc23fc..f1bce3e356 100644 --- a/lib/rlc/rlc_rx_um_entity.h +++ b/lib/rlc/rlc_rx_um_entity.h @@ -25,6 +25,7 @@ #include "rlc_rx_entity.h" #include "rlc_um_pdu.h" #include "srsran/adt/expected.h" +#include "srsran/rlc/rlc_metrics.h" #include "srsran/support/executors/task_executor.h" #include "srsran/support/sdu_window.h" #include "srsran/support/timers.h" @@ -108,10 +109,11 @@ class rlc_rx_um_entity : public rlc_rx_entity rb_id_t rb_id, const rlc_rx_um_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - timer_factory timers, - task_executor& ue_executor, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers); void stop() final { @@ -178,14 +180,13 @@ namespace fmt { template <> struct formatter { template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + auto parse(ParseContext& ctx) { return ctx.begin(); } template auto format(const srsran::rlc_rx_um_sdu_info& info, FormatContext& ctx) - -> decltype(std::declval().out()) { return format_to(ctx.out(), "has_gap={} fully_received={} nof_segments={}", @@ -198,13 +199,13 @@ struct formatter { template <> struct formatter { template - auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + auto parse(ParseContext& ctx) { return ctx.begin(); } template - auto format(const srsran::rlc_rx_um_state& st, FormatContext& ctx) -> decltype(std::declval().out()) + auto format(const srsran::rlc_rx_um_state& st, FormatContext& ctx) { return format_to(ctx.out(), "rx_next_reassembly={} rx_timer_trigger={} rx_next_highest={}", diff --git a/lib/rlc/rlc_tm_entity.h b/lib/rlc/rlc_tm_entity.h index edaa2ca6d0..be8d5bc048 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -41,16 +41,11 @@ class rlc_tm_entity : public rlc_base_entity rlc_tx_upper_layer_data_notifier& tx_upper_dn, rlc_tx_upper_layer_control_notifier& tx_upper_cn, rlc_tx_lower_layer_notifier& tx_lower_dn, - timer_manager& timers, + rlc_pcap& pcap, task_executor& pcell_executor, task_executor& ue_executor, - rlc_pcap& pcap) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + timer_manager& timers) : + rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor) { tx = std::make_unique(gnb_du_id_, ue_index_, @@ -59,11 +54,22 @@ class rlc_tm_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, + metrics_agg, + metrics_period.count() != 0, + pcap, pcell_executor, + ue_executor, + timers); + rx = std::make_unique(gnb_du_id_, + ue_index_, + rb_id_, + config.rx, + rx_upper_dn, + metrics_agg, metrics_period.count() != 0, - pcap); - rx = std::make_unique( - gnb_du_id_, ue_index_, rb_id_, config.rx, rx_upper_dn, metrics_period.count() != 0, pcap); + pcap, + ue_executor, + timers); } }; diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index 3a5b6db88b..bf9905de1f 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -38,12 +38,24 @@ rlc_tx_am_entity::rlc_tx_am_entity(gnb_du_id_t gnb_du_i rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - timer_factory timers, + rlc_metrics_aggregator& metrics_agg_, + bool metrics_enabled_, + rlc_pcap& pcap_, task_executor& pcell_executor_, task_executor& ue_executor_, - bool metrics_enabled_, - rlc_pcap& pcap_) : - rlc_tx_entity(gnb_du_id, ue_index, rb_id_, upper_dn_, upper_cn_, lower_dn_, metrics_enabled_, pcap_), + timer_manager& timers) : + rlc_tx_entity(gnb_du_id, + ue_index, + rb_id_, + upper_dn_, + upper_cn_, + lower_dn_, + metrics_agg_, + metrics_enabled_, + pcap_, + pcell_executor_, + ue_executor_, + timers), cfg(config), sdu_queue(cfg.queue_size, logger), retx_queue(window_size(to_number(cfg.sn_field_length))), @@ -53,13 +65,13 @@ rlc_tx_am_entity::rlc_tx_am_entity(gnb_du_id_t gnb_du_i pdu_recycler(window_size(to_number(cfg.sn_field_length)), logger), head_min_size(rlc_am_pdu_header_min_size(cfg.sn_field_length)), head_max_size(rlc_am_pdu_header_max_size(cfg.sn_field_length)), - poll_retransmit_timer(timers.create_timer()), + poll_retransmit_timer(pcell_timer_factory.create_timer()), is_poll_retransmit_timer_expired(false), pcell_executor(pcell_executor_), ue_executor(ue_executor_), pcap_context(ue_index, rb_id_, config) { - metrics.metrics_set_mode(rlc_mode::am); + metrics_low.metrics_set_mode(rlc_mode::am); // check PDCP SN length srsran_assert(config.pdcp_sn_len == pdcp_sn_size::size12bits || config.pdcp_sn_len == pdcp_sn_size::size18bits, @@ -106,7 +118,7 @@ void rlc_tx_am_entity::handle_sdu(byte_buffer sdu_buf, bool is_retx) sdu.pdcp_sn, sdu.is_retx, sdu_queue.get_state()); - metrics.metrics_add_sdus(1, sdu_length); + metrics_high.metrics_add_sdus(1, sdu_length); handle_changed_buffer_state(); } else { logger.log_warning("Dropped SDU. sdu_len={} pdcp_sn={} is_retx={} {}", @@ -114,7 +126,7 @@ void rlc_tx_am_entity::handle_sdu(byte_buffer sdu_buf, bool is_retx) sdu.pdcp_sn, sdu.is_retx, sdu_queue.get_state()); - metrics.metrics_add_lost_sdus(1); + metrics_high.metrics_add_lost_sdus(1); } } @@ -123,11 +135,11 @@ void rlc_tx_am_entity::discard_sdu(uint32_t pdcp_sn) { if (sdu_queue.try_discard(pdcp_sn)) { logger.log_info("Discarded SDU. pdcp_sn={}", pdcp_sn); - metrics.metrics_add_discard(1); + metrics_high.metrics_add_discard(1); handle_changed_buffer_state(); } else { logger.log_info("Could not discard SDU. pdcp_sn={}", pdcp_sn); - metrics.metrics_add_discard_failure(1); + metrics_high.metrics_add_discard_failure(1); } } @@ -163,7 +175,7 @@ size_t rlc_tx_am_entity::pull_pdu(span rlc_pdu_buf) logger.log_info(rlc_pdu_buf.data(), pdu_len, "TX status PDU. pdu_len={} grant_len={}", pdu_len, grant_len); // Update metrics - metrics.metrics_add_ctrl_pdus(1, pdu_len); + metrics_low.metrics_add_ctrl_pdus(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -280,12 +292,12 @@ size_t rlc_tx_am_entity::build_new_pdu(span rlc_pdu_buf) // Update TX Next auto latency = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - sdu_info.time_of_arrival); - metrics.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics.metrics_add_pulled_sdus(1); + metrics_low.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_low.metrics_add_pulled_sdus(1); st.tx_next = (st.tx_next + 1) % mod; // Update metrics - metrics.metrics_add_pdus_no_segmentation(1, pdu_len); + metrics_low.metrics_add_pdus_no_segmentation(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -349,7 +361,7 @@ size_t rlc_tx_am_entity::build_first_sdu_segment(span rlc_pdu_buf, rlc_ sdu_info.next_so += segment_payload_len; // Update metrics - metrics.metrics_add_pdus_with_segmentation_am(1, pdu_len); + metrics_low.metrics_add_pdus_with_segmentation_am(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -442,13 +454,13 @@ size_t rlc_tx_am_entity::build_continued_sdu_segment(span rlc_pdu_buf, if (si == rlc_si_field::last_segment) { auto latency = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - sdu_info.time_of_arrival); - metrics.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics.metrics_add_pulled_sdus(1); + metrics_low.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_low.metrics_add_pulled_sdus(1); st.tx_next = (st.tx_next + 1) % mod; } // Update metrics - metrics.metrics_add_pdus_with_segmentation_am(1, pdu_len); + metrics_low.metrics_add_pdus_with_segmentation_am(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); @@ -584,7 +596,7 @@ size_t rlc_tx_am_entity::build_retx_pdu(span rlc_pdu_buf) sdu_info.retx_count); // Update metrics - metrics.metrics_add_retx_pdus(1, pdu_len); + metrics_low.metrics_add_retx_pdus(1, pdu_len); // Log state log_state(srslog::basic_levels::debug); diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index f0104fc722..4844765472 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -137,6 +137,8 @@ class rlc_tx_am_entity : public rlc_tx_entity, public rlc_tx_am_status_handler, /// latest buffer state upon execution. std::atomic_flag pending_buffer_state = ATOMIC_FLAG_INIT; + bool stopped = false; + public: rlc_tx_am_entity(gnb_du_id_t gnb_du_id, du_ue_index_t ue_index, @@ -145,16 +147,22 @@ class rlc_tx_am_entity : public rlc_tx_entity, public rlc_tx_am_status_handler, rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - timer_factory timers, + rlc_metrics_aggregator& metrics_aggregator_, + bool metrics_enabled_, + rlc_pcap& pcap_, task_executor& pcell_executor_, task_executor& ue_executor_, - bool metrics_enabled_, - rlc_pcap& pcap_); + timer_manager& timers); void stop() final { // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically - poll_retransmit_timer.stop(); + if (not stopped) { + poll_retransmit_timer.stop(); + high_metrics_timer.stop(); + low_metrics_timer.stop(); + stopped = true; + } }; // TX/RX interconnect diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index de5a06d930..ed7a851662 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -23,6 +23,7 @@ #pragma once #include "rlc_bearer_logger.h" +#include "rlc_metrics_aggregator.h" #include "rlc_tx_metrics_container.h" #include "srsran/pcap/rlc_pcap.h" #include "srsran/rlc/rlc_tx.h" @@ -44,25 +45,61 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_) : + rlc_pcap& pcap_, + task_executor& pcell_executor_, + task_executor& ue_executor_, + timer_manager& timers) : logger("RLC", {gnb_du_id, ue_index, rb_id_, "DL"}), - metrics(metrics_enabled), + metrics_high(metrics_enabled), + metrics_low(metrics_enabled), rb_id(rb_id_), upper_dn(upper_dn_), upper_cn(upper_cn_), lower_dn(lower_dn_), - pcap(pcap_) + pcap(pcap_), + pcell_executor{pcell_executor_}, + ue_executor{ue_executor_}, + pcell_timer_factory{timers, pcell_executor}, + ue_timer_factory{timers, ue_executor}, + high_metrics_timer(pcell_timer_factory.create_timer()), + low_metrics_timer(ue_timer_factory.create_timer()), + metrics_agg(metrics_agg_) { + if (metrics_enabled) { + high_metrics_timer.set(std::chrono::milliseconds(1000), [this](timer_id_t tid) { + metrics_agg.push_tx_high_metrics(metrics_high.get_and_reset_metrics()); + high_metrics_timer.run(); + }); + low_metrics_timer.set(std::chrono::milliseconds(1000), [this](timer_id_t tid) { + metrics_agg.push_tx_low_metrics(metrics_low.get_and_reset_metrics()); + low_metrics_timer.run(); + }); + + high_metrics_timer.run(); + low_metrics_timer.run(); + } } rlc_bearer_logger logger; - rlc_tx_metrics_container metrics; + rlc_tx_metrics_high_container metrics_high; + rlc_tx_metrics_low_container metrics_low; rb_id_t rb_id; rlc_tx_upper_layer_data_notifier& upper_dn; rlc_tx_upper_layer_control_notifier& upper_cn; rlc_tx_lower_layer_notifier& lower_dn; rlc_pcap& pcap; + task_executor& pcell_executor; + task_executor& ue_executor; + timer_factory pcell_timer_factory; + timer_factory ue_timer_factory; + + unique_timer high_metrics_timer; + unique_timer low_metrics_timer; + +private: + rlc_metrics_aggregator& metrics_agg; public: /// \brief Stops all internal timers. @@ -75,8 +112,13 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, /// Note: This function shall only be called from ue_executor. virtual void stop() = 0; - rlc_tx_metrics get_metrics() { return metrics.get_metrics(); } - void reset_metrics() { return metrics.reset_metrics(); } + rlc_tx_metrics get_metrics() + { + rlc_tx_metrics m; + m.tx_high = metrics_high.get_hi_metrics(); + m.tx_low = metrics_low.get_low_metrics(); + return m; + } }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index c52ef39253..f8f5959bdf 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -26,176 +26,117 @@ namespace srsran { -struct rlc_tx_metrics_atomic_higher { - std::atomic num_sdus; ///< Number of SDUs - std::atomic num_of_pulled_sdus; ///< Number of pulled SDUs - std::atomic num_sdu_bytes; ///< Number of SDU bytes - std::atomic num_dropped_sdus; ///< Number of dropped SDUs (due to full queue) - std::atomic num_discarded_sdus; ///< Number of discarded SDUs (instructed from higher layer) - std::atomic num_discard_failures; ///< Number of failed SDU discards (instructed from higher layer) - std::atomic sum_sdu_latency_us; ///< total SDU latency (in us)> - - void reset() - { - num_sdus.store(0, std::memory_order_relaxed); - num_of_pulled_sdus.store(0, std::memory_order_relaxed); - num_sdu_bytes.store(0, std::memory_order_relaxed); - num_dropped_sdus.store(0, std::memory_order_relaxed); - num_discarded_sdus.store(0, std::memory_order_relaxed); - num_discard_failures.store(0, std::memory_order_relaxed); - sum_sdu_latency_us.store(0, std::memory_order_relaxed); - } -}; - -struct rlc_tm_tx_metrics_atomic_lower { - std::atomic num_small_allocs; ///< Number of allocations that are too small to TX PDU - - void reset() { num_small_allocs.store(0, std::memory_order_relaxed); } -}; +class rlc_tx_metrics_high_container +{ + rlc_tx_metrics_higher metrics_hi = {}; + bool enabled = false; -struct rlc_um_tx_metrics_atomic_lower { - std::atomic num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation - std::atomic num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation +public: + rlc_tx_metrics_high_container(bool enabled_) : enabled(enabled_) {} - void reset() + void metrics_add_sdus(uint32_t num_sdus, size_t num_sdu_bytes) { - num_pdus_with_segmentation.store(0, std::memory_order_relaxed); - num_pdu_bytes_with_segmentation.store(0, std::memory_order_relaxed); + if (not enabled) { + return; + } + metrics_hi.num_sdus += num_sdus; + metrics_hi.num_sdu_bytes += num_sdu_bytes; } -}; -struct rlc_am_tx_metrics_atomic_lower { - std::atomic num_pdus_with_segmentation; ///< Number of transmitted PDUs with segmentation - std::atomic num_pdu_bytes_with_segmentation; ///< Number of transmitted PDU bytes with segmentation - std::atomic num_retx_pdus; ///< Number of retransmitted PDUs - std::atomic num_retx_pdu_bytes; ///< Number of retransmitted PDU bytes - std::atomic num_ctrl_pdus; ///< Number of control PDUs - std::atomic num_ctrl_pdu_bytes; ///< Number of control PDUs bytes - - void reset() + void metrics_add_lost_sdus(uint32_t num_sdus) { - num_pdus_with_segmentation.store(0, std::memory_order_relaxed); - num_pdu_bytes_with_segmentation.store(0, std::memory_order_relaxed); - num_retx_pdus.store(0, std::memory_order_relaxed); - num_retx_pdu_bytes.store(0, std::memory_order_relaxed); - num_ctrl_pdus.store(0, std::memory_order_relaxed); - num_ctrl_pdu_bytes.store(0, std::memory_order_relaxed); + if (not enabled) { + return; + } + metrics_hi.num_dropped_sdus += num_sdus; } -}; -struct rlc_tx_metrics_atomic_lower { - std::atomic num_pdus_no_segmentation; ///< Number of transmitted PDUs without segmentation - std::atomic num_pdu_bytes_no_segmentation; ///< Number of transmitted PDU bytes without segmentation - - /// RLC mode of the entity - std::atomic mode; - - /// Mode-specific metrics - /// - /// The associated union member is indicated by \c mode. - /// Contents of the other fields are undefined. - union { - rlc_tm_tx_metrics_atomic_lower tm; - rlc_um_tx_metrics_atomic_lower um; - rlc_am_tx_metrics_atomic_lower am; - } mode_specific; - - void reset() + void metrics_add_discard(uint32_t num_discarded_sdus) { - num_pdus_no_segmentation.store(0, std::memory_order_relaxed); - num_pdu_bytes_no_segmentation.store(0, std::memory_order_relaxed); - - // reset mode-specific values - switch (mode.load(std::memory_order_relaxed)) { - case rlc_mode::tm: - mode_specific.tm.reset(); - break; - case rlc_mode::um_bidir: - case rlc_mode::um_unidir_dl: - mode_specific.um.reset(); - break; - case rlc_mode::am: - mode_specific.am.reset(); - break; - default: - // nothing to do here - break; + if (not enabled) { + return; } + metrics_hi.num_discarded_sdus += num_discarded_sdus; } -}; - -class rlc_tx_metrics_container -{ - rlc_tx_metrics_atomic_higher metrics_hi = {}; - rlc_tx_metrics_atomic_lower metrics_lo = {}; - bool enabled = false; - -public: - rlc_tx_metrics_container(bool enabled_) : enabled(enabled_) {} - void metrics_set_mode(rlc_mode mode) + void metrics_add_discard_failure(uint32_t num_discard_failures) { if (not enabled) { return; } - metrics_lo.mode.store(mode, std::memory_order_relaxed); + metrics_hi.num_discard_failures += num_discard_failures; } - void metrics_add_sdus(uint32_t num_sdus, size_t num_sdu_bytes) + // Metrics getters and setters + rlc_tx_metrics_higher get_hi_metrics() { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { - return; + return {}; } - metrics_hi.num_sdus.fetch_add(num_sdus, std::memory_order_relaxed); - metrics_hi.num_sdu_bytes.fetch_add(num_sdu_bytes, std::memory_order_relaxed); + return metrics_hi.get(); } - void metrics_add_pulled_sdus(uint32_t num_sdus) + void reset_metrics() { + srsran_assert(enabled, "Trying to reset metrics, but metrics are disabled."); if (not enabled) { return; } - metrics_hi.num_of_pulled_sdus.fetch_add(num_sdus, std::memory_order_relaxed); + metrics_hi.reset(); // do not reset the counter } - void metrics_add_lost_sdus(uint32_t num_sdus) + rlc_tx_metrics_higher get_and_reset_metrics() { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { - return; + return {false}; } - metrics_hi.num_dropped_sdus.fetch_add(num_sdus, std::memory_order_relaxed); + rlc_tx_metrics_higher ret = get_hi_metrics(); + reset_metrics(); + return ret; } +}; - void metrics_add_discard(uint32_t num_discarded_sdus) +class rlc_tx_metrics_low_container +{ + rlc_tx_metrics_lower metrics_lo = {}; + bool enabled = false; + +public: + rlc_tx_metrics_low_container(bool enabled_) : enabled(enabled_) {} + + void metrics_set_mode(rlc_mode mode) { if (not enabled) { return; } - metrics_hi.num_discarded_sdus.fetch_add(num_discarded_sdus, std::memory_order_relaxed); + metrics_lo.mode = mode; } - void metrics_add_discard_failure(uint32_t num_discard_failures) + void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) { if (not enabled) { return; } - metrics_hi.num_discard_failures.fetch_add(num_discard_failures, std::memory_order_relaxed); + metrics_lo.num_pdus_no_segmentation += num_pdus; + metrics_lo.num_pdu_bytes_no_segmentation += num_pdu_bytes; } - void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) + void metrics_add_pulled_sdus(uint32_t num_sdus) { if (not enabled) { return; } - metrics_lo.num_pdus_no_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); - metrics_lo.num_pdu_bytes_no_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); + metrics_lo.num_of_pulled_sdus += num_sdus; } + void metrics_add_sdu_latency_us(uint32_t sdu_latency) { if (not enabled) { return; } - metrics_hi.sum_sdu_latency_us.fetch_add(sdu_latency, std::memory_order_relaxed); + metrics_lo.sum_sdu_latency_us += sdu_latency; } // TM specific metrics @@ -204,8 +145,8 @@ class rlc_tx_metrics_container if (not enabled) { return; } - srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::tm, "Wrong mode for TM metrics."); - metrics_lo.mode_specific.tm.num_small_allocs.fetch_add(num_allocs, std::memory_order_relaxed); + srsran_assert(metrics_lo.mode == rlc_mode::tm, "Wrong mode for TM metrics."); + metrics_lo.mode_specific.tm.num_small_allocs += num_allocs; } // UM specific metrics @@ -214,10 +155,10 @@ class rlc_tx_metrics_container if (not enabled) { return; } - rlc_mode mode = metrics_lo.mode.load(std::memory_order_relaxed); + rlc_mode mode = metrics_lo.mode; srsran_assert(mode == rlc_mode::um_bidir || mode == rlc_mode::um_unidir_dl, "Wrong mode for UM metrics."); - metrics_lo.mode_specific.um.num_pdus_with_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); - metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); + metrics_lo.mode_specific.um.num_pdus_with_segmentation += num_pdus; + metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation += num_pdu_bytes; } // AM specific metrics @@ -226,9 +167,9 @@ class rlc_tx_metrics_container if (not enabled) { return; } - srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); - metrics_lo.mode_specific.am.num_pdus_with_segmentation.fetch_add(num_pdus, std::memory_order_relaxed); - metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation.fetch_add(num_pdu_bytes, std::memory_order_relaxed); + srsran_assert(metrics_lo.mode == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_pdus_with_segmentation += num_pdus; + metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation += num_pdu_bytes; } void metrics_add_retx_pdus(uint32_t num_pdus, size_t num_pdu_bytes) @@ -236,9 +177,9 @@ class rlc_tx_metrics_container if (not enabled) { return; } - srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); - metrics_lo.mode_specific.am.num_retx_pdus.fetch_add(num_pdus, std::memory_order_relaxed); - metrics_lo.mode_specific.am.num_retx_pdu_bytes.fetch_add(num_pdu_bytes, std::memory_order_relaxed); + srsran_assert(metrics_lo.mode == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_retx_pdus += num_pdus; + metrics_lo.mode_specific.am.num_retx_pdu_bytes += num_pdu_bytes; } void metrics_add_ctrl_pdus(uint32_t num_pdus, size_t num_pdu_bytes) @@ -246,63 +187,22 @@ class rlc_tx_metrics_container if (not enabled) { return; } - srsran_assert(metrics_lo.mode.load(std::memory_order_relaxed) == rlc_mode::am, "Wrong mode for AM metrics."); - metrics_lo.mode_specific.am.num_ctrl_pdus.fetch_add(num_pdus, std::memory_order_relaxed); - metrics_lo.mode_specific.am.num_ctrl_pdu_bytes.fetch_add(num_pdu_bytes, std::memory_order_relaxed); + srsran_assert(metrics_lo.mode == rlc_mode::am, "Wrong mode for AM metrics."); + metrics_lo.mode_specific.am.num_ctrl_pdus += num_pdus; + metrics_lo.mode_specific.am.num_ctrl_pdu_bytes += num_pdu_bytes; } // Metrics getters and setters - rlc_tx_metrics get_metrics() + rlc_tx_metrics_lower get_low_metrics() { srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { return {}; } - rlc_tx_metrics ret; + rlc_tx_metrics_lower ret; // Metrics accessed from higher layer - ret.num_sdus = metrics_hi.num_sdus.load(std::memory_order_relaxed); - ret.num_of_pulled_sdus = metrics_hi.num_of_pulled_sdus.load(std::memory_order_relaxed); - ret.num_sdu_bytes = metrics_hi.num_sdu_bytes.load(std::memory_order_relaxed); - ret.num_dropped_sdus = metrics_hi.num_dropped_sdus.load(std::memory_order_relaxed); - ret.num_discarded_sdus = metrics_hi.num_discarded_sdus.load(std::memory_order_relaxed); - ret.num_discard_failures = metrics_hi.num_discard_failures.load(std::memory_order_relaxed); - ret.sum_sdu_latency_us = metrics_hi.sum_sdu_latency_us.load(std::memory_order_relaxed); - - // Metrics accessed from lower layer - ret.num_pdus_no_segmentation = metrics_lo.num_pdus_no_segmentation.load(std::memory_order_relaxed); - ret.num_pdu_bytes_no_segmentation = metrics_lo.num_pdu_bytes_no_segmentation.load(std::memory_order_relaxed); - ret.mode = metrics_lo.mode.load(std::memory_order_relaxed); - switch (ret.mode) { - case rlc_mode::tm: - ret.mode_specific.tm.num_small_allocs = - metrics_lo.mode_specific.tm.num_small_allocs.load(std::memory_order_relaxed); - break; - case rlc_mode::um_bidir: - case rlc_mode::um_unidir_dl: - ret.mode_specific.um.num_pdus_with_segmentation = - metrics_lo.mode_specific.um.num_pdus_with_segmentation.load(std::memory_order_relaxed); - ret.mode_specific.um.num_pdu_bytes_with_segmentation = - metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation.load(std::memory_order_relaxed); - break; - case rlc_mode::am: - ret.mode_specific.am.num_pdus_with_segmentation = - metrics_lo.mode_specific.am.num_pdus_with_segmentation.load(std::memory_order_relaxed); - ret.mode_specific.am.num_pdu_bytes_with_segmentation = - metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation.load(std::memory_order_relaxed); - ret.mode_specific.am.num_retx_pdus = metrics_lo.mode_specific.am.num_retx_pdus.load(std::memory_order_relaxed); - ret.mode_specific.am.num_retx_pdu_bytes = - metrics_lo.mode_specific.am.num_retx_pdu_bytes.load(std::memory_order_relaxed); - ret.mode_specific.am.num_ctrl_pdus = metrics_lo.mode_specific.am.num_ctrl_pdus.load(std::memory_order_relaxed); - ret.mode_specific.am.num_ctrl_pdu_bytes = - metrics_lo.mode_specific.am.num_ctrl_pdu_bytes.load(std::memory_order_relaxed); - break; - default: - // nothing to do here - break; - } - - return ret; + return metrics_lo.get(); } void reset_metrics() @@ -311,17 +211,16 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_hi.reset(); metrics_lo.reset(); } - rlc_tx_metrics get_and_reset_metrics() + rlc_tx_metrics_lower get_and_reset_metrics() { srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); if (not enabled) { return {}; } - rlc_tx_metrics ret = get_metrics(); + rlc_tx_metrics_lower ret = get_low_metrics(); reset_metrics(); return ret; } diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index ccd83e4e60..eff825dbac 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -31,16 +31,29 @@ rlc_tx_tm_entity::rlc_tx_tm_entity(gnb_du_id_t du_id, rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - task_executor& pcell_executor_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, - rlc_pcap& pcap_) : - rlc_tx_entity(du_id, ue_index, rb_id_, upper_dn_, upper_cn_, lower_dn_, metrics_enabled_, pcap_), + rlc_pcap& pcap_, + task_executor& pcell_executor_, + task_executor& ue_executor_, + timer_manager& timers) : + rlc_tx_entity(du_id, + ue_index, + rb_id_, + upper_dn_, + upper_cn_, + lower_dn_, + metrics_agg_, + metrics_enabled_, + pcap_, + pcell_executor_, + ue_executor_, + timers), cfg(config), sdu_queue(cfg.queue_size, logger), - pcell_executor(pcell_executor_), pcap_context(ue_index, rb_id_, /* is_uplink */ false) { - metrics.metrics_set_mode(rlc_mode::tm); + metrics_low.metrics_set_mode(rlc_mode::tm); logger.log_info("RLC TM created. {}", cfg); } @@ -59,11 +72,11 @@ void rlc_tx_tm_entity::handle_sdu(byte_buffer sdu_buf, bool is_retx) size_t sdu_len = sdu_.buf.length(); if (sdu_queue.write(sdu_)) { logger.log_info(sdu_.buf.begin(), sdu_.buf.end(), "TX SDU. sdu_len={} {}", sdu_len, sdu_queue.get_state()); - metrics.metrics_add_sdus(1, sdu_len); + metrics_high.metrics_add_sdus(1, sdu_len); handle_changed_buffer_state(); } else { logger.log_info("Dropped SDU. sdu_len={} {}", sdu_len, sdu_queue.get_state()); - metrics.metrics_add_lost_sdus(1); + metrics_high.metrics_add_lost_sdus(1); } } @@ -71,7 +84,7 @@ void rlc_tx_tm_entity::handle_sdu(byte_buffer sdu_buf, bool is_retx) void rlc_tx_tm_entity::discard_sdu(uint32_t pdcp_sn) { logger.log_warning("Ignoring invalid attempt to discard SDU in TM. pdcp_sn={}", pdcp_sn); - metrics.metrics_add_discard_failure(1); + metrics_high.metrics_add_discard_failure(1); } // TS 38.322 v16.2.0 Sec. 5.2.1.1 @@ -93,7 +106,7 @@ size_t rlc_tx_tm_entity::pull_pdu(span mac_sdu_buf) size_t sdu_len = sdu.buf.length(); if (sdu_len > grant_len) { logger.log_info("SDU exeeds provided space. front_len={} grant_len={}", sdu_len, grant_len); - metrics.metrics_add_small_alloc(1); + metrics_low.metrics_add_small_alloc(1); return 0; } @@ -114,7 +127,7 @@ size_t rlc_tx_tm_entity::pull_pdu(span mac_sdu_buf) sdu.buf.clear(); // Update metrics - metrics.metrics_add_pdus_no_segmentation(1, sdu_len); + metrics_low.metrics_add_pdus_no_segmentation(1, sdu_len); // Push PDU into PCAP. pcap.push_pdu(pcap_context, mac_sdu_buf.subspan(0, pdu_len)); diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index f05d014798..399a32c8bc 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -37,8 +37,6 @@ class rlc_tx_tm_entity : public rlc_tx_entity rlc_sdu_queue_lockfree sdu_queue; rlc_sdu sdu; - task_executor& pcell_executor; - pcap_rlc_pdu_context pcap_context; /// This atomic_flag indicates whether a buffer state update task has been queued but not yet run by pcell_executor. @@ -55,13 +53,24 @@ class rlc_tx_tm_entity : public rlc_tx_entity rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - task_executor& pcell_executor_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& pcell_executor_, + task_executor& ue_executor_, + timer_manager& timers); - void stop() final{ - // There are no timers to be stopped here. - }; + ~rlc_tx_tm_entity() override { stop(); } + + void stop() final + { + // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically + if (not stopped) { + high_metrics_timer.stop(); + low_metrics_timer.stop(); + stopped = true; + } + } // Interfaces for higher layers void handle_sdu(byte_buffer sdu_buf, bool is_retx) override; @@ -86,6 +95,8 @@ class rlc_tx_tm_entity : public rlc_tx_entity /// /// Safe execution from: pcell_executor void update_mac_buffer_state(); + + bool stopped = false; }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index e688652dc3..9f31d3b137 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -34,20 +34,33 @@ rlc_tx_um_entity::rlc_tx_um_entity(gnb_du_id_t du_id, rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - task_executor& pcell_executor_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_) : - rlc_tx_entity(du_id, ue_index, rb_id_, upper_dn_, upper_cn_, lower_dn_, metrics_enabled, pcap_), + rlc_pcap& pcap_, + task_executor& pcell_executor_, + task_executor& ue_executor_, + timer_manager& timers) : + rlc_tx_entity(du_id, + ue_index, + rb_id_, + upper_dn_, + upper_cn_, + lower_dn_, + metrics_agg_, + metrics_enabled, + pcap_, + pcell_executor_, + ue_executor_, + timers), cfg(config), sdu_queue(cfg.queue_size, logger), mod(cardinality(to_number(cfg.sn_field_length))), head_len_full(rlc_um_pdu_header_size_complete_sdu), head_len_first(rlc_um_pdu_header_size_no_so(cfg.sn_field_length)), head_len_not_first(rlc_um_pdu_header_size_with_so(cfg.sn_field_length)), - pcell_executor(pcell_executor_), pcap_context(ue_index, rb_id_, config) { - metrics.metrics_set_mode(rlc_mode::um_bidir); + metrics_low.metrics_set_mode(rlc_mode::um_bidir); // check PDCP SN length srsran_assert(config.pdcp_sn_len == pdcp_sn_size::size12bits || config.pdcp_sn_len == pdcp_sn_size::size18bits, @@ -82,11 +95,11 @@ void rlc_tx_um_entity::handle_sdu(byte_buffer sdu_buf, bool is_retx) sdu_.buf.length(), sdu_.pdcp_sn, sdu_queue.get_state()); - metrics.metrics_add_sdus(1, sdu_length); + metrics_high.metrics_add_sdus(1, sdu_length); handle_changed_buffer_state(); } else { logger.log_info("Dropped SDU. sdu_len={} pdcp_sn={} {}", sdu_length, sdu_.pdcp_sn, sdu_queue.get_state()); - metrics.metrics_add_lost_sdus(1); + metrics_high.metrics_add_lost_sdus(1); } } @@ -95,11 +108,11 @@ void rlc_tx_um_entity::discard_sdu(uint32_t pdcp_sn) { if (sdu_queue.try_discard(pdcp_sn)) { logger.log_info("Discarded SDU. pdcp_sn={}", pdcp_sn); - metrics.metrics_add_discard(1); + metrics_high.metrics_add_discard(1); handle_changed_buffer_state(); } else { logger.log_info("Could not discard SDU. pdcp_sn={}", pdcp_sn); - metrics.metrics_add_discard_failure(1); + metrics_high.metrics_add_discard_failure(1); } } @@ -186,8 +199,8 @@ size_t rlc_tx_um_entity::pull_pdu(span mac_sdu_buf) next_so = 0; auto latency = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - sdu.time_of_arrival); - metrics.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics.metrics_add_pulled_sdus(1); + metrics_low.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_low.metrics_add_pulled_sdus(1); } else { // advance SO offset next_so += payload_len; @@ -200,9 +213,9 @@ size_t rlc_tx_um_entity::pull_pdu(span mac_sdu_buf) // Update metrics if (header.si == rlc_si_field::full_sdu) { - metrics.metrics_add_pdus_no_segmentation(1, pdu_size); + metrics_low.metrics_add_pdus_no_segmentation(1, pdu_size); } else { - metrics.metrics_add_pdus_with_segmentation_um(1, pdu_size); + metrics_low.metrics_add_pdus_with_segmentation_um(1, pdu_size); } // Log state diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 22fa1be52b..7c994db074 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -68,8 +68,6 @@ class rlc_tx_um_entity : public rlc_tx_entity const uint32_t head_len_first; const uint32_t head_len_not_first; - task_executor& pcell_executor; - pcap_rlc_pdu_context pcap_context; // Storage for previous buffer state @@ -89,13 +87,22 @@ class rlc_tx_um_entity : public rlc_tx_entity rlc_tx_upper_layer_data_notifier& upper_dn_, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, - task_executor& pcell_executor_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& pcell_executor_, + task_executor& ue_executor_, + timer_manager& timers); - void stop() final{ - // There are no timers to be stopped here. - }; + void stop() final + { + // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically + if (not stopped) { + high_metrics_timer.stop(); + low_metrics_timer.stop(); + stopped = true; + } + } // Interfaces for higher layers void handle_sdu(byte_buffer sdu_buf, bool is_retx) override; @@ -128,6 +135,8 @@ class rlc_tx_um_entity : public rlc_tx_entity void update_mac_buffer_state(); void log_state(srslog::basic_levels level) { logger.log(level, "TX entity state. {} next_so={}", st, next_so); } + + bool stopped = false; }; } // namespace srsran diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index 97ce25debd..c9d06f3974 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -41,16 +41,11 @@ class rlc_um_entity : public rlc_base_entity rlc_tx_upper_layer_data_notifier& tx_upper_dn, rlc_tx_upper_layer_control_notifier& tx_upper_cn, rlc_tx_lower_layer_notifier& tx_lower_dn, - timer_manager& timers, + rlc_pcap& pcap, task_executor& pcell_executor, task_executor& ue_executor, - rlc_pcap& pcap) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + timer_manager& timers) : + rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor) { tx = std::make_unique(gnb_du_id_, ue_index_, @@ -59,18 +54,22 @@ class rlc_um_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - pcell_executor, + metrics_agg, metrics_period.count() != 0, - pcap); + pcap, + pcell_executor, + ue_executor, + timers); rx = std::make_unique(gnb_du_id_, ue_index_, rb_id_, config.rx, rx_upper_dn, - timer_factory{timers, ue_executor}, - ue_executor, + metrics_agg, metrics_period.count() != 0, - pcap); + pcap, + ue_executor, + timers); } }; diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 2fe33a39f5..d101ac865f 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -1823,9 +1823,10 @@ pucch_allocator_impl::merge_pucch_resources(spanformat == pucch_format::FORMAT_0) { + srsran_assert(r_harq_ptr != nullptr and r_sr_ptr != nullptr and r_csi_ptr != nullptr, + "The three resources must be present"); + if (r_sr_ptr->format == pucch_format::FORMAT_0) { srsran_assertion_failure("This case is not yet supported"); // SR and CSI are not supported on the same slot if SR uses Format 0. return std::nullopt; } - if (r_harq->format != pucch_format::FORMAT_0 and r_harq->format != pucch_format::FORMAT_1) { - new_resource = *r_harq; + if (r_harq_ptr->format != pucch_format::FORMAT_0 and r_harq_ptr->format != pucch_format::FORMAT_1) { + new_resource = *r_harq_ptr; } else { - const pucch_resource* pucch_res = resource_manager.reserve_set_1_res_by_res_indicator( - slot_harq, crnti, r_harq->harq_id.pucch_res_ind, pucch_cfg); + pucch_harq_resource_alloc_record res_alloc = + resource_manager.reserve_next_set_1_harq_res_available(slot_harq, crnti, pucch_cfg); resource_manager.set_new_resource_allocation(crnti, pucch_resource_usage::HARQ_SET_1); - if (pucch_res == nullptr) { + if (res_alloc.pucch_res == nullptr) { return std::nullopt; } new_resource.harq_id.pucch_set_idx = pucch_res_set_idx::set_1; - new_resource.harq_id.pucch_res_ind = r_harq->harq_id.pucch_res_ind; - new_resource.set_res_config(*pucch_res); + new_resource.harq_id.pucch_res_ind = res_alloc.pucch_res_indicator; + new_resource.set_res_config(*res_alloc.pucch_res); } - new_resource.bits.harq_ack_nof_bits = r_harq->bits.harq_ack_nof_bits; - new_resource.bits.sr_bits = r_sr->bits.sr_bits; - new_resource.bits.csi_part1_nof_bits = r_csi->bits.csi_part1_nof_bits; + new_resource.bits.harq_ack_nof_bits = r_harq_ptr->bits.harq_ack_nof_bits; + new_resource.bits.sr_bits = r_sr_ptr->bits.sr_bits; + new_resource.bits.csi_part1_nof_bits = r_csi_ptr->bits.csi_part1_nof_bits; // Check if the UCI payload fits in the PUCCH resource. if (new_resource.bits.get_total_bits() <= pucch_cfg.get_max_payload(new_resource.format)) { diff --git a/lib/security/CMakeLists.txt b/lib/security/CMakeLists.txt index ba71415091..d2ad4ea306 100644 --- a/lib/security/CMakeLists.txt +++ b/lib/security/CMakeLists.txt @@ -24,6 +24,8 @@ set(SOURCES ciphering_engine_nea2.cpp ciphering_engine_nea3.cpp integrity_engine_generic.cpp + integrity_engine_nia2_cmac.cpp + integrity_engine_nia2_non_cmac.cpp security.cpp security_engine_impl.cpp s3g.cpp diff --git a/lib/security/integrity_engine_nia2_cmac.cpp b/lib/security/integrity_engine_nia2_cmac.cpp new file mode 100644 index 0000000000..c4ecf5b9e2 --- /dev/null +++ b/lib/security/integrity_engine_nia2_cmac.cpp @@ -0,0 +1,124 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "integrity_engine_nia2_cmac.h" +#include "mbedtls/cmac.h" +#include "srsran/security/security.h" + +using namespace srsran; +using namespace security; + +#ifdef MBEDTLS_CMAC_C + +integrity_engine_nia2_cmac::integrity_engine_nia2_cmac(sec_128_key k_128_int_, + uint8_t bearer_id_, + security_direction direction_) : + k_128_int(k_128_int_), bearer_id(bearer_id_), direction(direction_) +{ + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + if (cipher_info == nullptr) { + srsran_assertion_failure("Failure in mbedtls_cipher_info_from_type"); + return; + } + mbedtls_cipher_init(&ctx); + + int ret; + ret = mbedtls_cipher_setup(&ctx, cipher_info); + if (ret != 0) { + srsran_assertion_failure("Failure in mbedtls_cipher_setup"); + return; + } + + ret = mbedtls_cipher_cmac_starts(&ctx, k_128_int.data(), 128); + if (ret != 0) { + srsran_assertion_failure("Failure in mbedtls_cipher_cmac_starts"); + return; + } +} + +integrity_engine_nia2_cmac::~integrity_engine_nia2_cmac() +{ + mbedtls_cipher_free(&ctx); +} + +security_result integrity_engine_nia2_cmac::protect_integrity(byte_buffer buf, uint32_t count) +{ + security_result result{.buf = std::move(buf), .count = count}; + security::sec_mac mac = {}; + + byte_buffer_view v{result.buf.value().begin(), result.buf.value().end()}; + + // reset state machine + int ret; + ret = mbedtls_cipher_cmac_reset(&ctx); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + + // process preamble + std::array preamble = {}; + preamble[0] = (count >> 24) & 0xff; + preamble[1] = (count >> 16) & 0xff; + preamble[2] = (count >> 8) & 0xff; + preamble[3] = count & 0xff; + preamble[4] = (bearer_id << 3) | (to_number(direction) << 2); + ret = mbedtls_cipher_cmac_update(&ctx, preamble.data(), preamble.size()); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + + // process PDU segments + const_byte_buffer_segment_span_range segments = v.segments(); + for (const auto& segment : segments) { + ret = mbedtls_cipher_cmac_update(&ctx, segment.data(), segment.size()); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + } + + // complete CMAC computation + std::array tmp_mac; + ret = mbedtls_cipher_cmac_finish(&ctx, tmp_mac.data()); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + + // copy first 4 bytes + std::copy(tmp_mac.begin(), tmp_mac.begin() + 4, mac.begin()); + + if (not result.buf->append(mac)) { + result.buf = make_unexpected(security_error::buffer_failure); + } + return result; +} + +security_result integrity_engine_nia2_cmac::verify_integrity(byte_buffer buf, uint32_t count) +{ + security_result result; + return result; +} + +#endif // MBEDTLS_CMAC_C diff --git a/lib/security/integrity_engine_nia2_cmac.h b/lib/security/integrity_engine_nia2_cmac.h new file mode 100644 index 0000000000..3cf36e666a --- /dev/null +++ b/lib/security/integrity_engine_nia2_cmac.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" // Nested include of MBEDTLS_CMAC_C from either config.h (v2) or mbedtls_config.h (v3) +#include "srsran/security/integrity_engine.h" +#include "srsran/security/security.h" + +namespace srsran { +namespace security { + +#ifdef MBEDTLS_CMAC_C + +class integrity_engine_nia2_cmac final : public integrity_engine +{ +public: + integrity_engine_nia2_cmac(sec_128_key k_128_int_, uint8_t bearer_id_, security_direction direction_); + ~integrity_engine_nia2_cmac(); + + security_result protect_integrity(byte_buffer buf, uint32_t count) override; + security_result verify_integrity(byte_buffer buf, uint32_t count) override; + +private: + sec_128_key k_128_int; + uint8_t bearer_id; + security_direction direction; + + const mbedtls_cipher_info_t* cipher_info; + mbedtls_cipher_context_t ctx; +}; + +#endif // MBEDTLS_CMAC_C + +} // namespace security +} // namespace srsran diff --git a/lib/security/integrity_engine_nia2_non_cmac.cpp b/lib/security/integrity_engine_nia2_non_cmac.cpp new file mode 100644 index 0000000000..4d8edb7c68 --- /dev/null +++ b/lib/security/integrity_engine_nia2_non_cmac.cpp @@ -0,0 +1,129 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "integrity_engine_nia2_non_cmac.h" +#include "srsran/security/security.h" +#include "srsran/security/ssl.h" + +using namespace srsran; +using namespace security; + +integrity_engine_nia2_non_cmac::integrity_engine_nia2_non_cmac(sec_128_key k_128_int_, + uint8_t bearer_id_, + security_direction direction_) : + k_128_int(k_128_int_), bearer_id(bearer_id_), direction(direction_) +{ + std::array l; + + // subkey L generation + aes_setkey_enc(&ctx, k_128_int.data(), 128); + aes_crypt_ecb(&ctx, aes_encrypt, zeros.data(), l.data()); + + // subkey K1 generation + for (uint32_t i = 0; i < 15; i++) { + k1[i] = (l[i] << 1) | ((l[i + 1] >> 7) & 0x01); + } + k1[15] = l[15] << 1; + if (l[0] & 0x80) { + k1[15] ^= 0x87; + } + + // subkey K2 generation + for (uint32_t i = 0; i < 15; i++) { + k2[i] = (k1[i] << 1) | ((k1[i + 1] >> 7) & 0x01); + } + k2[15] = k1[15] << 1; + if (k1[0] & 0x80) { + k2[15] ^= 0x87; + } +} + +security_result integrity_engine_nia2_non_cmac::protect_integrity(byte_buffer buf, uint32_t count) +{ + security_result result{.buf = std::move(buf), .count = count}; + security::sec_mac mac = {}; + + byte_buffer_view v{result.buf.value().begin(), result.buf.value().end()}; + + uint32_t len = v.length(); + uint32_t len_bits = len * 8; + + std::array tmp_mac; + std::array tmp; + + const uint32_t msg_len_block_8_with_padding = len + 8 + 16; + srsran_assert(msg_len_block_8_with_padding <= sec_max_pdu_size, + "{}: Maximum PDU length exceeded. len={} max_len={}", + __FUNCTION__, + msg_len_block_8_with_padding, + sec_max_pdu_size); + + span msg(msg_buf.data(), msg_len_block_8_with_padding); + + // construct msg from preample, PDU and padding + msg[0] = (count >> 24) & 0xff; + msg[1] = (count >> 16) & 0xff; + msg[2] = (count >> 8) & 0xff; + msg[3] = count & 0xff; + msg[4] = (bearer_id << 3) | (to_number(direction) << 2); + std::fill(msg.begin() + 5, msg.begin() + 8, 0); + std::copy(v.begin(), v.end(), msg.begin() + 8); + std::fill(msg.begin() + len + 8, msg.end(), 0); + + // MAC generation + const uint32_t n = ceilf((float)(len + 8) / (float)(16)); + std::fill(tmp_mac.begin(), tmp_mac.end(), 0); + for (uint32_t i = 0; i < (n - 1); i++) { + for (uint32_t j = 0; j < 16; j++) { + tmp[j] = tmp_mac[j] ^ msg[i * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); + } + uint32_t pad_bits = ((len_bits) + 64) % 128; + if (pad_bits == 0) { + for (uint32_t j = 0; j < 16; j++) { + tmp[j] = tmp_mac[j] ^ k1[j] ^ msg[(n - 1) * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); + } else { + pad_bits = (128 - pad_bits) - 1; + msg[(n - 1) * 16 + (15 - (pad_bits / 8))] |= 0x1 << (pad_bits % 8); + for (uint32_t j = 0; j < 16; j++) { + tmp[j] = tmp_mac[j] ^ k2[j] ^ msg[(n - 1) * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); + } + + // copy first 4 bytes + std::copy(tmp_mac.begin(), tmp_mac.begin() + 4, mac.begin()); + + if (not result.buf->append(mac)) { + result.buf = make_unexpected(security_error::buffer_failure); + } + return result; +} + +security_result integrity_engine_nia2_non_cmac::verify_integrity(byte_buffer buf, uint32_t count) +{ + security_result result; + return result; +} diff --git a/lib/security/integrity_engine_nia2_non_cmac.h b/lib/security/integrity_engine_nia2_non_cmac.h new file mode 100644 index 0000000000..c5d569666a --- /dev/null +++ b/lib/security/integrity_engine_nia2_non_cmac.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "mbedtls/aes.h" +#include "srsran/security/integrity_engine.h" +#include "srsran/security/security.h" + +namespace srsran { +namespace security { + +class integrity_engine_nia2_non_cmac final : public integrity_engine +{ +public: + integrity_engine_nia2_non_cmac(sec_128_key k_128_int_, uint8_t bearer_id_, security_direction direction_); + ~integrity_engine_nia2_non_cmac() = default; + + security_result protect_integrity(byte_buffer buf, uint32_t count) override; + security_result verify_integrity(byte_buffer buf, uint32_t count) override; + +private: + sec_128_key k_128_int; + uint8_t bearer_id; + security_direction direction; + + mbedtls_aes_context ctx; + uint8_t k1[16]; + uint8_t k2[16]; + + std::array msg_buf; + static constexpr std::array zeros = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +}; + +} // namespace security +} // namespace srsran diff --git a/lib/security/security_engine_impl.cpp b/lib/security/security_engine_impl.cpp index 36832276ad..5868e19e8e 100644 --- a/lib/security/security_engine_impl.cpp +++ b/lib/security/security_engine_impl.cpp @@ -25,6 +25,8 @@ #include "ciphering_engine_nea2.h" #include "ciphering_engine_nea3.h" #include "integrity_engine_generic.h" +#include "integrity_engine_nia2_cmac.h" +#include "integrity_engine_nia2_non_cmac.h" using namespace srsran; using namespace security; @@ -36,12 +38,20 @@ security_engine_impl::security_engine_impl(security::sec_128_as_config sec_cfg, security::ciphering_enabled ciphering_enabled) { if (integrity_enabled == security::integrity_enabled::on) { - if (sec_cfg.integ_algo.has_value() && sec_cfg.k_128_int.has_value()) { - integ_eng = std::make_unique( - sec_cfg.k_128_int.value(), bearer_id, direction, sec_cfg.integ_algo.value()); - } else { - srsran_assertion_failure( - "Cannot enable integrity protection. algo={} key={}", sec_cfg.integ_algo, sec_cfg.k_128_int); + srsran_assert(sec_cfg.integ_algo.has_value(), "Cannot enable integrity protection: No algorithm selected"); + srsran_assert(sec_cfg.k_128_int.has_value(), "Cannot enable integrity protection: No key"); + switch (sec_cfg.integ_algo.value()) { + case integrity_algorithm::nia2: +#ifdef MBEDTLS_CMAC_C + integ_eng = std::make_unique(sec_cfg.k_128_int.value(), bearer_id, direction); +#else + integ_eng = std::make_unique(sec_cfg.k_128_int.value(), bearer_id, direction); +#endif + break; + default: + integ_eng = std::make_unique( + sec_cfg.k_128_int.value(), bearer_id, direction, sec_cfg.integ_algo.value()); + break; } } if (ciphering_enabled == security::ciphering_enabled::on) { diff --git a/lib/support/byte_buffer.cpp b/lib/support/byte_buffer.cpp index 0de1f2deab..86bcead6da 100644 --- a/lib/support/byte_buffer.cpp +++ b/lib/support/byte_buffer.cpp @@ -53,6 +53,18 @@ void srsran::init_byte_buffer_segment_pool(std::size_t nof_segments, std::size_t report_fatal_error_if_not(memory_block_size > 64U, "memory blocks must be larger than the segment control header"); } +size_t srsran::get_byte_buffer_segment_pool_capacity() +{ + auto& pool = detail::byte_buffer_segment_pool::get_instance(); + return pool.nof_memory_blocks(); +} + +size_t srsran::get_byte_buffer_segment_pool_current_size_approx() +{ + auto& pool = detail::byte_buffer_segment_pool::get_instance(); + return pool.get_central_cache_approx_size() + pool.get_local_cache_size(); +} + // ------- byte_buffer class ------- void byte_buffer::control_block::destroy_node(node_t* node) const diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 8277d94416..765b093eb9 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -33,7 +33,8 @@ using namespace srsran; class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, public rlc_tx_upper_layer_control_notifier, public rlc_tx_lower_layer_notifier, - public rlc_rx_am_status_provider + public rlc_rx_am_status_provider, + public rlc_metrics_notifier { public: rlc_am_sn_size sn_size; @@ -62,12 +63,16 @@ class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, rlc_am_status_pdu& get_status_pdu() override { return status; } uint32_t get_status_pdu_length() override { return status.get_packed_size(); } bool status_report_required() override { return status_required; } + + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; /// Mocking class of the surrounding layers invoked by the RLC AM Rx entity. class rlc_rx_am_test_frame : public rlc_rx_upper_layer_data_notifier, public rlc_tx_am_status_handler, - public rlc_tx_am_status_notifier + public rlc_tx_am_status_notifier, + public rlc_metrics_notifier { public: rlc_rx_am_test_frame() {} @@ -76,9 +81,11 @@ class rlc_rx_am_test_frame : public rlc_rx_upper_layer_data_notifier, void on_new_sdu(byte_buffer_chain sdu) override {} // rlc_tx_am_status_handler interface - virtual void on_status_pdu(rlc_am_status_pdu status_) override {} + void on_status_pdu(rlc_am_status_pdu status_) override {} // rlc_tx_am_status_notifier interface - virtual void on_status_report_changed() override {} + void on_status_report_changed() override {} + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; struct bench_params { @@ -146,13 +153,17 @@ std::vector generate_pdus(bench_params params, rx_order order) manual_task_worker ue_worker{128}; // Create RLC AM TX entity - std::unique_ptr rlc_tx = nullptr; + std::unique_ptr rlc_tx = nullptr; + std::unique_ptr metrics_agg = nullptr; auto& logger = srslog::fetch_basic_logger("RLC"); logger.set_level(srslog::basic_levels::warning); null_rlc_pcap pcap; + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Make PDUs std::vector pdus; rlc_tx = std::make_unique(gnb_du_id_t::min, @@ -162,11 +173,12 @@ std::vector generate_pdus(bench_params params, rx_order order) *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + *metrics_agg, + false, + pcap, pcell_worker, ue_worker, - false, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc_tx->set_status_provider(tester.get()); @@ -237,16 +249,20 @@ void benchmark_rx_pdu(const bench_params& params, rx_order order) config.t_status_prohibit = 0; config.t_reassembly = 200; + auto metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Create RLC AM RX entity std::unique_ptr rlc_rx = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, drb_id_t::drb1, config, *tester, - timer_factory{timers, ue_worker}, - ue_worker, + *metrics_agg, false, - pcap); + pcap, + ue_worker, + timers); // Bind AM Rx/Tx interconnect rlc_rx->set_status_notifier(tester.get()); diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index 8a48a19fc7..5e956eae2e 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -32,7 +32,8 @@ using namespace srsran; class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, public rlc_tx_upper_layer_control_notifier, public rlc_tx_lower_layer_notifier, - public rlc_rx_am_status_provider + public rlc_rx_am_status_provider, + public rlc_metrics_notifier { public: rlc_am_sn_size sn_size; @@ -61,6 +62,9 @@ class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, rlc_am_status_pdu& get_status_pdu() override { return status; } uint32_t get_status_pdu_length() override { return status.get_packed_size(); } bool status_report_required() override { return status_required; } + + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; struct bench_params { @@ -122,8 +126,11 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& null_rlc_pcap pcap; + auto metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Run benchmark - auto context = [&rlc, &tester, config, &timers, &pcell_worker, &ue_worker, &pcap]() { + auto context = [&rlc, &tester, &metrics_agg, config, &timers, &pcell_worker, &ue_worker, &pcap]() { rlc = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, drb_id_t::drb1, @@ -131,11 +138,12 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + *metrics_agg, + false, + pcap, pcell_worker, ue_worker, - false, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc->set_status_provider(tester.get()); diff --git a/tests/e2e/pyproject.toml b/tests/e2e/pyproject.toml index 33cc8057bb..f23b47714d 100644 --- a/tests/e2e/pyproject.toml +++ b/tests/e2e/pyproject.toml @@ -46,6 +46,7 @@ markers = [ "rf_not_crash", "reattach", "test", + "zmq_2x2_mimo", "zmq_4x4_mimo", "zmq_srsue", "test_mode", diff --git a/tests/e2e/tests/iperf.py b/tests/e2e/tests/iperf.py index a55a21209e..7f10dead89 100644 --- a/tests/e2e/tests/iperf.py +++ b/tests/e2e/tests/iperf.py @@ -347,6 +347,59 @@ def test_android_hp( ) +@mark.parametrize( + "direction", + (param(IPerfDir.BIDIRECTIONAL, id="bidirectional", marks=mark.bidirectional),), +) +@mark.parametrize( + "protocol", + (param(IPerfProto.UDP, id="udp", marks=mark.udp),), +) +@mark.parametrize( + "band, common_scs, bandwidth", + (param(41, 30, 20, id="band:%s-scs:%s-bandwidth:%s"),), +) +@mark.zmq_2x2_mimo +@mark.flaky(reruns=2, only_rerun=["failed to start", "Attach timeout reached", "5GC crashed"]) +# pylint: disable=too-many-arguments +def test_zmq_2x2_mimo( + retina_manager: RetinaTestManager, + retina_data: RetinaTestData, + ue_32: Tuple[UEStub, ...], + fivegc: FiveGCStub, + gnb: GNBStub, + band: int, + common_scs: int, + bandwidth: int, + protocol: IPerfProto, + direction: IPerfDir, +): + """ + ZMQ 4x4 mimo IPerfs + """ + + _iperf( + retina_manager=retina_manager, + retina_data=retina_data, + ue_array=ue_32, + gnb=gnb, + fivegc=fivegc, + band=band, + common_scs=common_scs, + bandwidth=bandwidth, + sample_rate=None, + iperf_duration=SHORT_DURATION, + protocol=protocol, + bitrate=MEDIUM_BITRATE, + direction=direction, + global_timing_advance=-1, + time_alignment_calibration=0, + always_download_artifacts=True, + rx_to_tx_latency=2, + enable_dddsu=True, + ) + + @mark.parametrize( "direction", ( @@ -629,6 +682,8 @@ def _iperf( common_search_space_enable: bool = False, prach_config_index=-1, ue_stop_timeout: int = 0, + rx_to_tx_latency: int = -1, + enable_dddsu: bool = False, ): wait_before_power_off = 5 @@ -645,6 +700,8 @@ def _iperf( time_alignment_calibration=time_alignment_calibration, common_search_space_enable=common_search_space_enable, prach_config_index=prach_config_index, + rx_to_tx_latency=rx_to_tx_latency, + enable_dddsu=enable_dddsu, ) configure_artifacts( retina_data=retina_data, diff --git a/tests/e2e/tests/steps/configuration.py b/tests/e2e/tests/steps/configuration.py index d1ade6b794..5260566993 100644 --- a/tests/e2e/tests/steps/configuration.py +++ b/tests/e2e/tests/steps/configuration.py @@ -52,6 +52,8 @@ def configure_test_parameters( num_cells: int = 1, cell_position_offset: Tuple[float, float, float] = (1000, 0, 0), enable_security_mode: bool = False, + rx_to_tx_latency: int = -1, + enable_dddsu: bool = False, ): """ Configure test parameters @@ -70,6 +72,7 @@ def configure_test_parameters( "noise_spd": noise_spd, "num_cells": num_cells, "cell_position_offset": cell_position_offset, + "rx_to_tx_latency": rx_to_tx_latency, }, }, "gnb": { @@ -85,6 +88,7 @@ def configure_test_parameters( "enable_qos_reestablishment": enable_qos_reestablishment, "num_cells": num_cells, "enable_security_mode": enable_security_mode, + "enable_dddsu": enable_dddsu, }, }, } diff --git a/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp b/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp index 93e981355c..dbed90d144 100644 --- a/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp +++ b/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp @@ -65,7 +65,7 @@ std::shared_ptr srsran::create_sw_pusch_processor_facto unsigned nof_ldpc_iterations, bool dec_enable_early_stop) { - std::shared_ptr dft_proc_factory = create_dft_processor_factory_fftw_fast(); + std::shared_ptr dft_proc_factory = create_dft_processor_factory_fftw_slow(); report_fatal_error_if_not(dft_proc_factory, "Failed to create factory."); std::shared_ptr crc_calc_factory = create_crc_calculator_factory_sw("auto"); diff --git a/tests/unittests/cu_up/ue_manager_test.cpp b/tests/unittests/cu_up/ue_manager_test.cpp index c0525d0698..d7d5bdc3cd 100644 --- a/tests/unittests/cu_up/ue_manager_test.cpp +++ b/tests/unittests/cu_up/ue_manager_test.cpp @@ -23,6 +23,7 @@ #include "cu_up_test_helpers.h" #include "lib/cu_up/ue_manager.h" #include "srsran/cu_up/cu_up_types.h" +#include "srsran/support/async/async_test_utils.h" #include "srsran/support/executors/manual_task_worker.h" #include @@ -62,6 +63,7 @@ class ue_manager_test : public ::testing::Test *gtpu_n3_allocator, *gtpu_f1u_allocator, *cu_up_exec_mapper, + worker, gtpu_pcap, test_logger); } @@ -89,6 +91,9 @@ class ue_manager_test : public ::testing::Test cu_up_test_mode_config test_mode_config{}; srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST", false); manual_task_worker worker{64}; + + async_task t; + std::optional> t_launcher; }; /// UE object handling tests (creation/deletion) @@ -125,7 +130,8 @@ TEST_F(ue_manager_test, when_ue_are_deleted_ue_db_is_empty) // delete all UE objects for (uint32_t i = 0; i < MAX_NOF_UES; i++) { - ue_mng->remove_ue(int_to_ue_index(i)); + t = ue_mng->remove_ue(int_to_ue_index(i)); + t_launcher.emplace(t); } ASSERT_EQ(ue_mng->get_nof_ues(), 0); } diff --git a/tests/unittests/e1ap/common/test_helpers.h b/tests/unittests/e1ap/common/test_helpers.h index 5754498af3..e47f5d6ec6 100644 --- a/tests/unittests/e1ap/common/test_helpers.h +++ b/tests/unittests/e1ap/common/test_helpers.h @@ -161,10 +161,15 @@ class dummy_e1ap_cu_up_notifier : public srs_cu_up::e1ap_cu_up_manager_notifier }); } - void on_bearer_context_release_command_received(const srs_cu_up::e1ap_bearer_context_release_command& msg) override + async_task + on_bearer_context_release_command_received(const srs_cu_up::e1ap_bearer_context_release_command& msg) override { logger.info("Received BearerContextReleaseCommand"); last_bearer_context_release_command = msg; + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + CORO_RETURN(); + }); } void on_schedule_ue_async_task(srs_cu_up::ue_index_t ue_index_, async_task task) override diff --git a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp index 3103620535..7666d3dbf0 100644 --- a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp +++ b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp @@ -138,17 +138,17 @@ rlc_metrics generate_rlc_metrics(uint32_t ue_idx, uint32_t bearer_id) rlc_metric.rx.num_lost_pdus = 1; rlc_metric.rx.num_malformed_pdus = 0; - rlc_metric.tx.mode = rlc_mode::am; - rlc_metric.tx.num_sdus = 10; - rlc_metric.tx.num_sdu_bytes = rlc_metric.tx.num_sdus * 1000; - rlc_metric.tx.num_dropped_sdus = 1; - rlc_metric.tx.num_discarded_sdus = 0; - rlc_metric.tx.num_discard_failures = 0; - rlc_metric.tx.num_pdus_no_segmentation = 8; - rlc_metric.tx.num_pdu_bytes_no_segmentation = rlc_metric.tx.num_pdus_no_segmentation * 1000; - rlc_metric.tx.mode_specific.am.num_pdus_with_segmentation = 2; - rlc_metric.tx.mode_specific.am.num_pdu_bytes_with_segmentation = - rlc_metric.tx.mode_specific.am.num_pdus_with_segmentation * 1000; + rlc_metric.tx.tx_low.mode = rlc_mode::am; + rlc_metric.tx.tx_high.num_sdus = 10; + rlc_metric.tx.tx_high.num_sdu_bytes = rlc_metric.tx.tx_high.num_sdus * 1000; + rlc_metric.tx.tx_high.num_dropped_sdus = 1; + rlc_metric.tx.tx_high.num_discarded_sdus = 0; + rlc_metric.tx.tx_high.num_discard_failures = 0; + rlc_metric.tx.tx_low.num_pdus_no_segmentation = 8; + rlc_metric.tx.tx_low.num_pdu_bytes_no_segmentation = rlc_metric.tx.tx_low.num_pdus_no_segmentation * 1000; + rlc_metric.tx.tx_low.mode_specific.am.num_pdus_with_segmentation = 2; + rlc_metric.tx.tx_low.mode_specific.am.num_pdu_bytes_with_segmentation = + rlc_metric.tx.tx_low.mode_specific.am.num_pdus_with_segmentation * 1000; return rlc_metric; } diff --git a/tests/unittests/f1ap/cu_cp/f1ap_cu_ue_context_setup_procedure_test.cpp b/tests/unittests/f1ap/cu_cp/f1ap_cu_ue_context_setup_procedure_test.cpp index 61a3587977..d98acb0d75 100644 --- a/tests/unittests/f1ap/cu_cp/f1ap_cu_ue_context_setup_procedure_test.cpp +++ b/tests/unittests/f1ap/cu_cp/f1ap_cu_ue_context_setup_procedure_test.cpp @@ -34,7 +34,7 @@ const std::chrono::milliseconds procedure_timeout{100}; class f1ap_cu_ue_context_setup_test : public f1ap_cu_test { protected: - f1ap_cu_ue_context_setup_test() : f1ap_cu_test(f1ap_configuration{.ue_context_setup_timeout = procedure_timeout}) {} + f1ap_cu_ue_context_setup_test() : f1ap_cu_test(f1ap_configuration{.proc_timeout = procedure_timeout}) {} void start_procedure(const f1ap_ue_context_setup_request& req) { diff --git a/tests/unittests/nru/nru_packing_test.cpp b/tests/unittests/nru/nru_packing_test.cpp index 38b0df7b4a..396ca0ca56 100644 --- a/tests/unittests/nru/nru_packing_test.cpp +++ b/tests/unittests/nru/nru_packing_test.cpp @@ -65,7 +65,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_smallest) { const uint8_t packed_vec[] = { 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -90,7 +90,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_dl_flush) { const uint8_t packed_vec[] = { 0x02, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -120,7 +120,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_report_polling) { const uint8_t packed_vec[] = { 0x01, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -142,11 +142,94 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_report_polling) EXPECT_EQ(out_buf, packed_buf); } +TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_request_out_of_sequence_report) +{ + const uint8_t packed_vec[] = { + 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling + 0x10, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag + 0x11, // NR-U Sequence Number (upper byte) + 0x22, // NR-U Sequence Number (mid byte) + 0x33, // NR-U Sequence Number (lower byte) + // No further fields + 0x00, // Padding + }; + + byte_buffer packed_buf = byte_buffer::create(packed_vec).value(); + nru_dl_user_data out_data; + EXPECT_TRUE(packer->unpack(out_data, packed_buf)); + nru_dl_user_data exp_data{}; + exp_data.nru_sn = 0x112233; + exp_data.request_out_of_seq_report = true; + EXPECT_EQ(out_data, exp_data); + + // Test packing + byte_buffer out_buf; + EXPECT_TRUE(packer->pack(out_buf, exp_data)); + EXPECT_EQ(out_buf, packed_buf); +} + +TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_report_delivered) +{ + const uint8_t packed_vec[] = { + 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling + 0x08, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag + 0x11, // NR-U Sequence Number (upper byte) + 0x22, // NR-U Sequence Number (mid byte) + 0x33, // NR-U Sequence Number (lower byte) + 0xee, // DL report NR PDCP PDU SN (upper byte) + 0xdd, // DL report NR PDCP PDU SN (mid byte) + 0xcc, // DL report NR PDCP PDU SN (lower byte) + // No further fields + 0x00, // Padding + 0x00, // Padding + }; + + byte_buffer packed_buf = byte_buffer::create(packed_vec).value(); + nru_dl_user_data out_data; + EXPECT_TRUE(packer->unpack(out_data, packed_buf)); + nru_dl_user_data exp_data{}; + exp_data.nru_sn = 0x112233; + exp_data.report_delivered = true; + exp_data.dl_report_pdcp_sn = 0xeeddcc; + EXPECT_EQ(out_data, exp_data); + + // Test packing + byte_buffer out_buf; + EXPECT_TRUE(packer->pack(out_buf, exp_data)); + EXPECT_EQ(out_buf, packed_buf); +} + +TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_user_data_existence_flag) +{ + const uint8_t packed_vec[] = { + 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling + 0x04, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag + 0x11, // NR-U Sequence Number (upper byte) + 0x22, // NR-U Sequence Number (mid byte) + 0x33, // NR-U Sequence Number (lower byte) + // No further fields + 0x00, // Padding + }; + + byte_buffer packed_buf = byte_buffer::create(packed_vec).value(); + nru_dl_user_data out_data; + EXPECT_TRUE(packer->unpack(out_data, packed_buf)); + nru_dl_user_data exp_data{}; + exp_data.nru_sn = 0x112233; + exp_data.user_data_existence_flag = true; + EXPECT_EQ(out_data, exp_data); + + // Test packing + byte_buffer out_buf; + EXPECT_TRUE(packer->pack(out_buf, exp_data)); + EXPECT_EQ(out_buf, packed_buf); +} + TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_assist_info_flag) { const uint8_t packed_vec[] = { 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x02, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x02, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -172,7 +255,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_retransmission_flag) { const uint8_t packed_vec[] = { 0x00, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x01, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x01, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -198,7 +281,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_discard_blocks) { const uint8_t packed_vec[] = { 0x04, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -240,7 +323,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_invalid_pdu_type) { const uint8_t packed_vec[] = { 0xe0, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -257,7 +340,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_missing_padding) { const uint8_t packed_vec[] = { 0xe0, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -274,7 +357,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_excessive_padding) { const uint8_t packed_vec[] = { 0xe0, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) @@ -292,7 +375,7 @@ TEST_F(nru_packing_test, unpack_nru_dl_user_data_with_too_large_nof_discard_bloc { const uint8_t packed_vec[] = { 0x04, // 4PDU Type | Spare | DL Discard Blocks | DL Flush | Report polling - 0x00, // 6Spare | Assist Info Rep Poll Flag | Retransmission flag + 0x00, // 3Spare | Req OoS Rep | Rep Deliv | User Data Ex | Assist Info Rep Poll Flag | Retransmission flag 0x11, // NR-U Sequence Number (upper byte) 0x22, // NR-U Sequence Number (mid byte) 0x33, // NR-U Sequence Number (lower byte) diff --git a/tests/unittests/phy/support/resource_grid_test_doubles.h b/tests/unittests/phy/support/resource_grid_test_doubles.h index 07f9272a41..7770bdd035 100644 --- a/tests/unittests/phy/support/resource_grid_test_doubles.h +++ b/tests/unittests/phy/support/resource_grid_test_doubles.h @@ -221,7 +221,7 @@ class resource_grid_writer_spy : public resource_grid_writer /// Defines the maximum allowed error when asserting the resource grid. static constexpr float ASSERT_MAX_ERROR = 1e-6; /// Counts the number of times a \c put method is called. - unsigned count = 0; + std::atomic count = {0}; /// Maximum number of ports. unsigned max_ports; /// Maximum number of OFDM symbols. diff --git a/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.h b/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.h index aa90998d2e..e22dab0a33 100644 --- a/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.h +++ b/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 09-11-2023 (seed 0): +// This file was generated using the following MATLAB class on 29-07-2024 (seed 0): // + "srsPRACHDetectorUnittest.m" #include "../../support/prach_buffer_test_doubles.h" @@ -65,60 +65,48 @@ static const std::vector prach_detector_test_data = { {{{990, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(1.80206e-06), {3.0482, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{46, phy_time_unit::from_seconds(1.45262e-06), 2.2128}}}}, {"test_data/prach_detector_test_input15.dat", {839, 4, 1, 1, 1}}}, {{{45, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(4.3313e-06), {1.7766, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{43, phy_time_unit::from_seconds(4.10924e-06), 14.5683}}}}, {"test_data/prach_detector_test_input16.dat", {839, 4, 1, 1, 2}}}, {{{335, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(2.14265e-06), {0.9954, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{34, phy_time_unit::from_seconds(1.92286e-06), 37.2443}}}}, {"test_data/prach_detector_test_input17.dat", {839, 4, 1, 1, 4}}}, - {{{269, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 1}, phy_time_unit::from_seconds(2.26122e-07), {3.0273, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{10, phy_time_unit::from_seconds(1.95312e-07), 87.3121}}}}, {"test_data/prach_detector_test_input18.dat", {839, 4, 1, 1, 1}}}, - {{{678, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 2}, phy_time_unit::from_seconds(1.3373e-06), {1.8312, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{27, phy_time_unit::from_seconds(1.36719e-06), 27.2666}}}}, {"test_data/prach_detector_test_input19.dat", {839, 4, 1, 1, 2}}}, - {{{267, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 4}, phy_time_unit::from_seconds(2.47093e-07), {0.95659, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{30, phy_time_unit::from_seconds(1.95312e-07), 458.7982}}}}, {"test_data/prach_detector_test_input20.dat", {839, 4, 1, 1, 4}}}, - {{{483, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 1}, phy_time_unit::from_seconds(2.25689e-07), {2.9928, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{6, phy_time_unit::from_seconds(2.34189e-07), 112.0901}}}}, {"test_data/prach_detector_test_input21.dat", {839, 4, 1, 1, 1}}}, - {{{231, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 2}, phy_time_unit::from_seconds(2.10239e-07), {1.692, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{23, phy_time_unit::from_seconds(1.81578e-07), 3948.1598}}}}, {"test_data/prach_detector_test_input22.dat", {839, 4, 1, 1, 2}}}, - {{{726, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 4}, phy_time_unit::from_seconds(4.0373e-07), {0.94302, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{41, phy_time_unit::from_seconds(2.98207e-07), 14.8967}}}}, {"test_data/prach_detector_test_input23.dat", {839, 4, 1, 1, 4}}}, - {{{228, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(4.7059e-07), {2.9535, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{37, phy_time_unit::from_seconds(5.20833e-07), 11.2805}}}}, {"test_data/prach_detector_test_input24.dat", {139, 2, 1, 1, 1}}}, - {{{831, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(7.6313e-08), {1.5666, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{46, phy_time_unit::from_seconds(0), 24.8573}}}}, {"test_data/prach_detector_test_input25.dat", {139, 2, 1, 1, 2}}}, - {{{401, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(3.23354e-07), {1.0689, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{46, phy_time_unit::from_seconds(2.60417e-07), 277.4997}}}}, {"test_data/prach_detector_test_input26.dat", {139, 2, 1, 1, 4}}}, - {{{524, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(3.86371e-07), {3.2353, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{52, phy_time_unit::from_seconds(3.747e-07), 13.0962}}}}, {"test_data/prach_detector_test_input27.dat", {139, 2, 1, 1, 1}}}, - {{{189, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(1.32722e-07), {1.7662, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{50, phy_time_unit::from_seconds(1.8735e-07), 29.4785}}}}, {"test_data/prach_detector_test_input28.dat", {139, 2, 1, 1, 2}}}, - {{{400, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(1.72021e-07), {0.95346, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{62, phy_time_unit::from_seconds(1.8735e-07), 81.5616}}}}, {"test_data/prach_detector_test_input29.dat", {139, 2, 1, 1, 4}}}, - {{{239, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(4.67894e-07), {2.8937, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{10, phy_time_unit::from_seconds(5.20833e-07), 42.4742}}}}, {"test_data/prach_detector_test_input30.dat", {139, 12, 1, 1, 1}}}, - {{{356, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(4.2583e-07), {1.7831, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{2, phy_time_unit::from_seconds(5.20833e-07), 26.1607}}}}, {"test_data/prach_detector_test_input31.dat", {139, 12, 1, 1, 2}}}, - {{{595, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(4.85045e-07), {0.94761, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{62, phy_time_unit::from_seconds(5.20833e-07), 183.9362}}}}, {"test_data/prach_detector_test_input32.dat", {139, 12, 1, 1, 4}}}, - {{{896, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(2.80792e-07), {3.1749, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{17, phy_time_unit::from_seconds(2.07959e-07), 40.2873}}}}, {"test_data/prach_detector_test_input33.dat", {139, 12, 1, 1, 1}}}, - {{{160, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(3.76684e-07), {1.7804, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{18, phy_time_unit::from_seconds(2.60417e-07), 55.9275}}}}, {"test_data/prach_detector_test_input34.dat", {139, 12, 1, 1, 2}}}, - {{{201, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(3.72804e-07), {0.89666, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{52, phy_time_unit::from_seconds(3.747e-07), 167.153}}}}, {"test_data/prach_detector_test_input35.dat", {139, 12, 1, 1, 4}}}, - {{{311, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(4.91103e-06), {2.954, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{27, phy_time_unit::from_seconds(4.6875e-06), 19.4872}}}}, {"test_data/prach_detector_test_input36.dat", {839, 1, 1, 1, 1}}}, - {{{674, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.09155e-06), {1.8685, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{36, phy_time_unit::from_seconds(7.8125e-07), 28.5282}}}}, {"test_data/prach_detector_test_input37.dat", {839, 1, 1, 1, 2}}}, - {{{848, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(1.59729e-06), {0.92615, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{44, phy_time_unit::from_seconds(1.5625e-06), 618.0755}}}}, {"test_data/prach_detector_test_input38.dat", {839, 1, 1, 1, 4}}}, - {{{442, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(5.56976e-06), {2.9366, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{19, phy_time_unit::from_seconds(5.83097e-06), 3.2245}}}}, {"test_data/prach_detector_test_input39.dat", {839, 1, 1, 1, 1}}}, - {{{440, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(2.34588e-06), {1.7461, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{32, phy_time_unit::from_seconds(2.13144e-06), 10.9334}}}}, {"test_data/prach_detector_test_input40.dat", {839, 1, 1, 1, 2}}}, - {{{976, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(4.19843e-06), {1.0114, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{22, phy_time_unit::from_seconds(3.9556e-06), 17.4823}}}}, {"test_data/prach_detector_test_input41.dat", {839, 1, 1, 1, 4}}}, - {{{385, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(1.78247e-06), {3.0976, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{52, phy_time_unit::from_seconds(1.5625e-06), 68.6962}}}}, {"test_data/prach_detector_test_input42.dat", {839, 2, 1, 1, 1}}}, - {{{195, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(5.80727e-06), {1.7551, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{53, phy_time_unit::from_seconds(5.46875e-06), 89.774}}}}, {"test_data/prach_detector_test_input43.dat", {839, 2, 1, 1, 2}}}, - {{{249, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(8.059e-07), {0.97047, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{59, phy_time_unit::from_seconds(7.8125e-07), 1097.4813}}}}, {"test_data/prach_detector_test_input44.dat", {839, 2, 1, 1, 4}}}, - {{{432, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(4.92108e-06), {3.1084, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{61, phy_time_unit::from_seconds(4.57576e-06), 1.7486}}}}, {"test_data/prach_detector_test_input45.dat", {839, 2, 1, 1, 1}}}, - {{{481, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.22736e-06), {1.7283, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{55, phy_time_unit::from_seconds(1.29525e-06), 99.4677}}}}, {"test_data/prach_detector_test_input46.dat", {839, 2, 1, 1, 2}}}, - {{{505, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(9.6783e-07), {0.90095, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{36, phy_time_unit::from_seconds(9.3303e-07), 325.4728}}}}, {"test_data/prach_detector_test_input47.dat", {839, 2, 1, 1, 4}}}, - {{{90, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(2.14159e-06), {2.9593, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{53, phy_time_unit::from_seconds(2.34375e-06), 40.7685}}}}, {"test_data/prach_detector_test_input48.dat", {839, 4, 1, 1, 1}}}, - {{{37, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.41626e-06), {1.7503, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{54, phy_time_unit::from_seconds(1.5625e-06), 145.8211}}}}, {"test_data/prach_detector_test_input49.dat", {839, 4, 1, 1, 2}}}, - {{{27, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(3.17864e-06), {0.99185, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{58, phy_time_unit::from_seconds(3.125e-06), 2746.0559}}}}, {"test_data/prach_detector_test_input50.dat", {839, 4, 1, 1, 4}}}, - {{{740, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(1.05566e-06), {3.0645, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{17, phy_time_unit::from_seconds(1.35206e-06), 2.3461}}}}, {"test_data/prach_detector_test_input51.dat", {839, 4, 1, 1, 1}}}, - {{{482, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.99355e-06), {1.7296, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{44, phy_time_unit::from_seconds(1.6612e-06), 4.0316}}}}, {"test_data/prach_detector_test_input52.dat", {839, 4, 1, 1, 2}}}, - {{{58, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(9.59126e-07), {0.96055, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{30, phy_time_unit::from_seconds(7.77525e-07), 34.7426}}}}, {"test_data/prach_detector_test_input53.dat", {839, 4, 1, 1, 4}}}, - {{{557, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 1}, phy_time_unit::from_seconds(1.22246e-06), {2.8947, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{1, phy_time_unit::from_seconds(1.17187e-06), 50.0256}}}}, {"test_data/prach_detector_test_input54.dat", {839, 4, 1, 1, 1}}}, - {{{288, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 2}, phy_time_unit::from_seconds(8.20894e-07), {1.7084, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{15, phy_time_unit::from_seconds(7.8125e-07), 79.2291}}}}, {"test_data/prach_detector_test_input55.dat", {839, 4, 1, 1, 2}}}, - {{{137, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 4}, phy_time_unit::from_seconds(7.03698e-07), {0.90301, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{39, phy_time_unit::from_seconds(7.8125e-07), 11.7427}}}}, {"test_data/prach_detector_test_input56.dat", {839, 4, 1, 1, 4}}}, - {{{188, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 1}, phy_time_unit::from_seconds(1.22059e-06), {2.9436, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{15, phy_time_unit::from_seconds(1.17141e-06), 147.0242}}}}, {"test_data/prach_detector_test_input57.dat", {839, 4, 1, 1, 1}}}, - {{{788, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 2}, phy_time_unit::from_seconds(1.0324e-06), {1.7953, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{35, phy_time_unit::from_seconds(1.04058e-06), 211.642}}}}, {"test_data/prach_detector_test_input58.dat", {839, 4, 1, 1, 2}}}, - {{{37, to_prach_format_type("3"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("5.000000kHz"), 4}, phy_time_unit::from_seconds(1.4355e-06), {0.96045, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{7, phy_time_unit::from_seconds(1.37999e-06), 62.3377}}}}, {"test_data/prach_detector_test_input59.dat", {839, 4, 1, 1, 4}}}, - {{{807, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(2.42585e-07), {2.9819, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{9, phy_time_unit::from_seconds(2.60417e-07), 12.7403}}}}, {"test_data/prach_detector_test_input60.dat", {139, 2, 1, 1, 1}}}, - {{{394, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(1.39275e-07), {1.7082, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{53, phy_time_unit::from_seconds(1.30208e-07), 51.4245}}}}, {"test_data/prach_detector_test_input61.dat", {139, 2, 1, 1, 2}}}, - {{{8, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(1.30652e-07), {0.99926, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{17, phy_time_unit::from_seconds(1.30208e-07), 242.0786}}}}, {"test_data/prach_detector_test_input62.dat", {139, 2, 1, 1, 4}}}, - {{{850, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(6.29431e-08), {3.2777, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{43, phy_time_unit::from_seconds(9.36751e-08), 3.8543}}}}, {"test_data/prach_detector_test_input63.dat", {139, 2, 1, 1, 1}}}, - {{{936, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(2.01744e-07), {1.6994, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{6, phy_time_unit::from_seconds(1.30208e-07), 9.2102}}}}, {"test_data/prach_detector_test_input64.dat", {139, 2, 1, 1, 2}}}, - {{{983, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(1.61024e-07), {0.94435, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{27, phy_time_unit::from_seconds(1.30208e-07), 278.4946}}}}, {"test_data/prach_detector_test_input65.dat", {139, 2, 1, 1, 4}}}, - {{{772, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(3.51621e-08), {3.0906, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{7, phy_time_unit::from_seconds(0), 42.8417}}}}, {"test_data/prach_detector_test_input66.dat", {139, 12, 1, 1, 1}}}, - {{{355, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(2.19284e-07), {1.7311, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{0, phy_time_unit::from_seconds(2.60417e-07), 26.9174}}}}, {"test_data/prach_detector_test_input67.dat", {139, 12, 1, 1, 2}}}, - {{{929, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(2.59074e-07), {0.93263, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{63, phy_time_unit::from_seconds(2.60417e-07), 182.0978}}}}, {"test_data/prach_detector_test_input68.dat", {139, 12, 1, 1, 4}}}, - {{{549, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(9.3693e-08), {2.9279, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{17, phy_time_unit::from_seconds(5.71418e-08), 145.8479}}}}, {"test_data/prach_detector_test_input69.dat", {139, 12, 1, 1, 1}}}, - {{{736, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(4.84376e-08), {1.8268, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{7, phy_time_unit::from_seconds(9.36751e-08), 24.2136}}}}, {"test_data/prach_detector_test_input70.dat", {139, 12, 1, 1, 2}}}, - {{{561, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(1.39581e-07), {1.0216, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{54, phy_time_unit::from_seconds(1.30208e-07), 38294.0311}}}}, {"test_data/prach_detector_test_input71.dat", {139, 12, 1, 1, 4}}}, + {{{269, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(7.53741e-08), {3.3314, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{10, phy_time_unit::from_seconds(0), 12.2107}}}}, {"test_data/prach_detector_test_input18.dat", {139, 2, 1, 1, 1}}}, + {{{762, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(3.4892e-07), {1.8626, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{38, phy_time_unit::from_seconds(2.60417e-07), 27.2052}}}}, {"test_data/prach_detector_test_input19.dat", {139, 2, 1, 1, 2}}}, + {{{884, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(5.01088e-07), {0.87204, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{24, phy_time_unit::from_seconds(5.20833e-07), 57.7059}}}}, {"test_data/prach_detector_test_input20.dat", {139, 2, 1, 1, 4}}}, + {{{909, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(2.89576e-07), {3.1198, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{46, phy_time_unit::from_seconds(3.747e-07), 4.4382}}}}, {"test_data/prach_detector_test_input21.dat", {139, 2, 1, 1, 1}}}, + {{{860, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(3.80335e-07), {1.7254, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{54, phy_time_unit::from_seconds(2.60417e-07), 27.8017}}}}, {"test_data/prach_detector_test_input22.dat", {139, 2, 1, 1, 2}}}, + {{{663, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(1.54359e-07), {0.96142, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{28, phy_time_unit::from_seconds(1.14284e-07), 257.9638}}}}, {"test_data/prach_detector_test_input23.dat", {139, 2, 1, 1, 4}}}, + {{{882, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(1.88878e-07), {3.049, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{30, phy_time_unit::from_seconds(2.60417e-07), 13.8189}}}}, {"test_data/prach_detector_test_input24.dat", {139, 12, 1, 1, 1}}}, + {{{892, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(2.48336e-07), {1.6622, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{1, phy_time_unit::from_seconds(2.60417e-07), 100.2025}}}}, {"test_data/prach_detector_test_input25.dat", {139, 12, 1, 1, 2}}}, + {{{336, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(1.8366e-07), {1.0084, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{26, phy_time_unit::from_seconds(2.60417e-07), 44.9428}}}}, {"test_data/prach_detector_test_input26.dat", {139, 12, 1, 1, 4}}}, + {{{721, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 1}, phy_time_unit::from_seconds(3.46008e-07), {3.1141, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{48, phy_time_unit::from_seconds(2.60417e-07), 22.8806}}}}, {"test_data/prach_detector_test_input27.dat", {139, 12, 1, 1, 1}}}, + {{{284, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 2}, phy_time_unit::from_seconds(1.51704e-07), {1.746, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{43, phy_time_unit::from_seconds(9.36751e-08), 133.2069}}}}, {"test_data/prach_detector_test_input28.dat", {139, 12, 1, 1, 2}}}, + {{{878, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 11, 0, 64, to_ra_subcarrier_spacing("15.000000kHz"), 4}, phy_time_unit::from_seconds(1.90884e-07), {0.93393, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{55, phy_time_unit::from_seconds(9.36751e-08), 373.1459}}}}, {"test_data/prach_detector_test_input29.dat", {139, 12, 1, 1, 4}}}, + {{{940, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(3.92305e-06), {2.9047, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{19, phy_time_unit::from_seconds(3.90625e-06), 59.6046}}}}, {"test_data/prach_detector_test_input30.dat", {839, 1, 1, 1, 1}}}, + {{{423, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(3.4279e-06), {1.8551, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{42, phy_time_unit::from_seconds(3.125e-06), 27.0012}}}}, {"test_data/prach_detector_test_input31.dat", {839, 1, 1, 1, 2}}}, + {{{211, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(4.77557e-06), {1.015, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{63, phy_time_unit::from_seconds(4.6875e-06), 492.0505}}}}, {"test_data/prach_detector_test_input32.dat", {839, 1, 1, 1, 4}}}, + {{{417, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(4.70331e-06), {3.0997, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{17, phy_time_unit::from_seconds(4.47706e-06), 4.9539}}}}, {"test_data/prach_detector_test_input33.dat", {839, 1, 1, 1, 1}}}, + {{{563, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.81515e-06), {1.709, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{9, phy_time_unit::from_seconds(2.18638e-06), 2.4957}}}}, {"test_data/prach_detector_test_input34.dat", {839, 1, 1, 1, 2}}}, + {{{405, to_prach_format_type("0"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(1.68315e-06), {0.95498, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{40, phy_time_unit::from_seconds(1.29712e-06), 4.9223}}}}, {"test_data/prach_detector_test_input35.dat", {839, 1, 1, 1, 4}}}, + {{{542, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(3.02407e-06), {2.9802, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{56, phy_time_unit::from_seconds(3.125e-06), 78.1047}}}}, {"test_data/prach_detector_test_input36.dat", {839, 2, 1, 1, 1}}}, + {{{480, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(5.09242e-06), {1.7313, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{63, phy_time_unit::from_seconds(4.6875e-06), 63.4309}}}}, {"test_data/prach_detector_test_input37.dat", {839, 2, 1, 1, 2}}}, + {{{167, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(3.33323e-06), {0.93009, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{7, phy_time_unit::from_seconds(3.125e-06), 419.4244}}}}, {"test_data/prach_detector_test_input38.dat", {839, 2, 1, 1, 4}}}, + {{{318, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(2.51789e-06), {2.9888, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{14, phy_time_unit::from_seconds(2.44618e-06), 82.9174}}}}, {"test_data/prach_detector_test_input39.dat", {839, 2, 1, 1, 1}}}, + {{{148, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(4.85817e-06), {1.8239, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{12, phy_time_unit::from_seconds(4.99851e-06), 26.5783}}}}, {"test_data/prach_detector_test_input40.dat", {839, 2, 1, 1, 2}}}, + {{{134, to_prach_format_type("1"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(3.45314e-06), {0.98064, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{10, phy_time_unit::from_seconds(3.64459e-06), 24.4122}}}}, {"test_data/prach_detector_test_input41.dat", {839, 2, 1, 1, 4}}}, + {{{784, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(1.78058e-06), {3.0944, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{32, phy_time_unit::from_seconds(1.5625e-06), 50.2402}}}}, {"test_data/prach_detector_test_input42.dat", {839, 4, 1, 1, 1}}}, + {{{134, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(5.96646e-06), {1.718, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{57, phy_time_unit::from_seconds(6.25e-06), 43.0227}}}}, {"test_data/prach_detector_test_input43.dat", {839, 4, 1, 1, 2}}}, + {{{826, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(3.16711e-06), {0.95947, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{61, phy_time_unit::from_seconds(3.125e-06), 2431.9438}}}}, {"test_data/prach_detector_test_input44.dat", {839, 4, 1, 1, 4}}}, + {{{1014, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 1}, phy_time_unit::from_seconds(4.8839e-06), {2.9026, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{33, phy_time_unit::from_seconds(5.15215e-06), 3.5987}}}}, {"test_data/prach_detector_test_input45.dat", {839, 4, 1, 1, 1}}}, + {{{874, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 2}, phy_time_unit::from_seconds(1.01676e-06), {1.6998, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{22, phy_time_unit::from_seconds(8.30602e-07), 17.2942}}}}, {"test_data/prach_detector_test_input46.dat", {839, 4, 1, 1, 2}}}, + {{{502, to_prach_format_type("2"), restricted_set_config::UNRESTRICTED, 1, 0, 64, to_ra_subcarrier_spacing("1.250000kHz"), 4}, phy_time_unit::from_seconds(4.85444e-06), {0.89345, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{30, phy_time_unit::from_seconds(4.68378e-06), 34.0405}}}}, {"test_data/prach_detector_test_input47.dat", {839, 4, 1, 1, 4}}}, + {{{960, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(1.68939e-07), {2.8579, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{37, phy_time_unit::from_seconds(1.30208e-07), 11.0451}}}}, {"test_data/prach_detector_test_input48.dat", {139, 2, 1, 1, 1}}}, + {{{863, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(9.63119e-08), {1.7037, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{13, phy_time_unit::from_seconds(0), 8.9557}}}}, {"test_data/prach_detector_test_input49.dat", {139, 2, 1, 1, 2}}}, + {{{335, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(2.01395e-07), {0.89367, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{20, phy_time_unit::from_seconds(2.60417e-07), 17.2511}}}}, {"test_data/prach_detector_test_input50.dat", {139, 2, 1, 1, 4}}}, + {{{877, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(1.76636e-07), {3.0686, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{26, phy_time_unit::from_seconds(1.8735e-07), 10.1308}}}}, {"test_data/prach_detector_test_input51.dat", {139, 2, 1, 1, 1}}}, + {{{929, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(5.78441e-08), {1.8183, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{45, phy_time_unit::from_seconds(0), 29.6237}}}}, {"test_data/prach_detector_test_input52.dat", {139, 2, 1, 1, 2}}}, + {{{647, to_prach_format_type("A1"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(2.48151e-07), {0.90542, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{7, phy_time_unit::from_seconds(2.23883e-07), 254.3656}}}}, {"test_data/prach_detector_test_input53.dat", {139, 2, 1, 1, 4}}}, + {{{761, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(2.06914e-07), {2.9984, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{33, phy_time_unit::from_seconds(1.30208e-07), 6.6053}}}}, {"test_data/prach_detector_test_input54.dat", {139, 12, 1, 1, 1}}}, + {{{707, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(1.61625e-07), {1.7704, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{16, phy_time_unit::from_seconds(1.30208e-07), 480.9759}}}}, {"test_data/prach_detector_test_input55.dat", {139, 12, 1, 1, 2}}}, + {{{509, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 0, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(4.9831e-08), {0.95787, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{26, phy_time_unit::from_seconds(0), 181.137}}}}, {"test_data/prach_detector_test_input56.dat", {139, 12, 1, 1, 4}}}, + {{{460, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 1}, phy_time_unit::from_seconds(1.21563e-07), {2.9912, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{57, phy_time_unit::from_seconds(1.30208e-07), 34.2572}}}}, {"test_data/prach_detector_test_input57.dat", {139, 12, 1, 1, 1}}}, + {{{505, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 2}, phy_time_unit::from_seconds(9.65488e-08), {1.739, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{53, phy_time_unit::from_seconds(5.71418e-08), 379.2634}}}}, {"test_data/prach_detector_test_input58.dat", {139, 12, 1, 1, 2}}}, + {{{517, to_prach_format_type("B4"), restricted_set_config::UNRESTRICTED, 14, 0, 64, to_ra_subcarrier_spacing("30.000000kHz"), 4}, phy_time_unit::from_seconds(1.29143e-07), {0.93407, phy_time_unit::from_seconds(0.0), phy_time_unit::from_seconds(0.0), {{15, phy_time_unit::from_seconds(1.30208e-07), 140.9862}}}}, {"test_data/prach_detector_test_input59.dat", {139, 12, 1, 1, 4}}}, // clang-format on }; diff --git a/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.h b/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.h index 4bcfabdd34..6e02b7492d 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.h +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 22-05-2024 (seed 0): +// This file was generated using the following MATLAB class on 24-07-2024 (seed 0): // + "srsPUCCHProcessorFormat0Unittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -44,96 +44,96 @@ struct test_case_t { static const std::vector pucch_processor_format0_test_data = { // clang-format off - {{{std::nullopt, {0, 999}, cyclic_prefix::NORMAL, 51, 1, 6, {}, 12, 1, 7, 821, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols0.dat"}}, - {{{std::nullopt, {0, 4307}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 13, 1, 3, 256, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols1.dat"}}, - {{{std::nullopt, {0, 4717}, cyclic_prefix::NORMAL, 51, 1, 35, {}, 10, 1, 3, 5, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols2.dat"}}, - {{{std::nullopt, {0, 7750}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 3, 1, 8, 214, 1, 1, {0,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols3.dat"}}, - {{{std::nullopt, {0, 1757}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 7, 1, 0, 993, 1, 1, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols4.dat"}}, - {{{std::nullopt, {0, 4302}, cyclic_prefix::NORMAL, 51, 1, 22, {}, 12, 1, 1, 596, 1, 1, {0,1,2,3,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols5.dat"}}, - {{{std::nullopt, {0, 4847}, cyclic_prefix::NORMAL, 51, 1, 0, {}, 11, 1, 8, 379, 2, 1, {0,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols6.dat"}}, - {{{std::nullopt, {0, 6635}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 8, 1, 7, 627, 2, 1, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols7.dat"}}, - {{{std::nullopt, {0, 4521}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 1, 1, 5, 836, 2, 1, {0,1,2,3,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols8.dat"}}, - {{{std::nullopt, {0, 9573}, cyclic_prefix::NORMAL, 51, 1, 11, {}, 3, 1, 1, 727, 1, 0, {0,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols9.dat"}}, - {{{std::nullopt, {0, 3370}, cyclic_prefix::NORMAL, 51, 1, 25, {}, 12, 1, 0, 425, 1, 0, {0,1,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols10.dat"}}, - {{{std::nullopt, {0, 154}, cyclic_prefix::NORMAL, 51, 1, 7, {}, 4, 1, 3, 272, 1, 0, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols11.dat"}}, - {{{std::nullopt, {0, 7636}, cyclic_prefix::NORMAL, 51, 1, 45, {}, 0, 1, 0, 152, 2, 0, {0,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols12.dat"}}, - {{{std::nullopt, {0, 2333}, cyclic_prefix::NORMAL, 51, 1, 18, {}, 10, 1, 9, 816, 2, 0, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols13.dat"}}, - {{{std::nullopt, {0, 7914}, cyclic_prefix::NORMAL, 51, 1, 8, {}, 8, 1, 6, 646, 2, 0, {0,1,2,3,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols14.dat"}}, - {{{std::nullopt, {0, 9634}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 6, 2, 9, 631, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols15.dat"}}, - {{{std::nullopt, {0, 1489}, cyclic_prefix::NORMAL, 51, 1, 50, {}, 11, 2, 8, 527, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols16.dat"}}, - {{{std::nullopt, {0, 8182}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 3, 2, 2, 1007, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols17.dat"}}, - {{{std::nullopt, {0, 4745}, cyclic_prefix::NORMAL, 51, 1, 1, {}, 0, 2, 9, 525, 1, 1, {0,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols18.dat"}}, - {{{std::nullopt, {0, 3781}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 8, 2, 4, 38, 1, 1, {0,1,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols19.dat"}}, - {{{std::nullopt, {0, 2014}, cyclic_prefix::NORMAL, 51, 1, 47, {}, 8, 2, 10, 938, 1, 1, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols20.dat"}}, - {{{std::nullopt, {0, 2900}, cyclic_prefix::NORMAL, 51, 1, 12, {}, 2, 2, 9, 624, 2, 1, {0,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols21.dat"}}, - {{{std::nullopt, {0, 5526}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 7, 2, 10, 46, 2, 1, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols22.dat"}}, - {{{std::nullopt, {0, 5982}, cyclic_prefix::NORMAL, 51, 1, 28, {}, 3, 2, 4, 226, 2, 1, {0,1,2,3,}}, {1, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols23.dat"}}, - {{{std::nullopt, {0, 967}, cyclic_prefix::NORMAL, 51, 1, 20, {}, 10, 2, 4, 746, 1, 0, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols24.dat"}}, - {{{std::nullopt, {0, 3223}, cyclic_prefix::NORMAL, 51, 1, 15, {}, 4, 2, 5, 887, 1, 0, {0,1,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols25.dat"}}, - {{{std::nullopt, {0, 5384}, cyclic_prefix::NORMAL, 51, 1, 3, {}, 12, 2, 0, 63, 1, 0, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols26.dat"}}, - {{{std::nullopt, {0, 3801}, cyclic_prefix::NORMAL, 51, 1, 50, {}, 10, 2, 9, 84, 2, 0, {0,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols27.dat"}}, - {{{std::nullopt, {0, 1080}, cyclic_prefix::NORMAL, 51, 1, 43, {}, 0, 2, 7, 447, 2, 0, {0,1,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols28.dat"}}, - {{{std::nullopt, {0, 1704}, cyclic_prefix::NORMAL, 51, 1, 37, {}, 3, 2, 7, 691, 2, 0, {0,1,2,3,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols29.dat"}}, - {{{std::nullopt, {0, 2838}, cyclic_prefix::NORMAL, 51, 1, 38, {41}, 7, 2, 9, 195, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols30.dat"}}, - {{{std::nullopt, {0, 4643}, cyclic_prefix::NORMAL, 51, 1, 20, {28}, 5, 2, 3, 984, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols31.dat"}}, - {{{std::nullopt, {0, 7840}, cyclic_prefix::NORMAL, 51, 1, 0, {47}, 10, 2, 1, 719, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols32.dat"}}, - {{{std::nullopt, {0, 379}, cyclic_prefix::NORMAL, 51, 1, 3, {50}, 9, 2, 2, 394, 1, 1, {0,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols33.dat"}}, - {{{std::nullopt, {0, 9807}, cyclic_prefix::NORMAL, 51, 1, 22, {13}, 3, 2, 5, 811, 1, 1, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols34.dat"}}, - {{{std::nullopt, {0, 8793}, cyclic_prefix::NORMAL, 51, 1, 15, {35}, 8, 2, 4, 638, 1, 1, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols35.dat"}}, - {{{std::nullopt, {0, 2375}, cyclic_prefix::NORMAL, 51, 1, 49, {25}, 8, 2, 4, 390, 2, 1, {0,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols36.dat"}}, - {{{std::nullopt, {0, 3654}, cyclic_prefix::NORMAL, 51, 1, 18, {37}, 9, 2, 11, 200, 2, 1, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols37.dat"}}, - {{{std::nullopt, {0, 2807}, cyclic_prefix::NORMAL, 51, 1, 44, {43}, 11, 2, 3, 379, 2, 1, {0,1,2,3,}}, {0, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols38.dat"}}, - {{{std::nullopt, {0, 1443}, cyclic_prefix::NORMAL, 51, 1, 45, {21}, 0, 2, 10, 105, 1, 0, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols39.dat"}}, - {{{std::nullopt, {0, 9501}, cyclic_prefix::NORMAL, 51, 1, 11, {9}, 1, 2, 10, 188, 1, 0, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols40.dat"}}, - {{{std::nullopt, {0, 2234}, cyclic_prefix::NORMAL, 51, 1, 31, {18}, 9, 2, 1, 483, 1, 0, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols41.dat"}}, - {{{std::nullopt, {0, 6443}, cyclic_prefix::NORMAL, 51, 1, 35, {8}, 10, 2, 8, 768, 2, 0, {0,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols42.dat"}}, - {{{std::nullopt, {0, 6690}, cyclic_prefix::NORMAL, 51, 1, 49, {14}, 10, 2, 10, 747, 2, 0, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols43.dat"}}, - {{{std::nullopt, {0, 6257}, cyclic_prefix::NORMAL, 51, 1, 28, {36}, 7, 2, 5, 385, 2, 0, {0,1,2,3,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols44.dat"}}, - {{{std::nullopt, {1, 17146}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 4, 1, 0, 798, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols45.dat"}}, - {{{std::nullopt, {1, 18241}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 12, 1, 10, 709, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols46.dat"}}, - {{{std::nullopt, {1, 861}, cyclic_prefix::NORMAL, 51, 1, 8, {}, 9, 1, 2, 847, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols47.dat"}}, - {{{std::nullopt, {1, 12746}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 11, 1, 8, 622, 1, 1, {0,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols48.dat"}}, - {{{std::nullopt, {1, 15747}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 2, 1, 0, 641, 1, 1, {0,1,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols49.dat"}}, - {{{std::nullopt, {1, 3093}, cyclic_prefix::NORMAL, 51, 1, 4, {}, 4, 1, 1, 209, 1, 1, {0,1,2,3,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols50.dat"}}, - {{{std::nullopt, {1, 10210}, cyclic_prefix::NORMAL, 51, 1, 41, {}, 0, 1, 7, 91, 2, 1, {0,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols51.dat"}}, - {{{std::nullopt, {1, 19008}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 9, 1, 6, 977, 2, 1, {0,1,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols52.dat"}}, - {{{std::nullopt, {1, 10774}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 9, 1, 0, 655, 2, 1, {0,1,2,3,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols53.dat"}}, - {{{std::nullopt, {1, 2319}, cyclic_prefix::NORMAL, 51, 1, 42, {}, 8, 1, 4, 2, 1, 0, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols54.dat"}}, - {{{std::nullopt, {1, 5068}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 12, 1, 7, 643, 1, 0, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols55.dat"}}, - {{{std::nullopt, {1, 2865}, cyclic_prefix::NORMAL, 51, 1, 3, {}, 1, 1, 4, 653, 1, 0, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols56.dat"}}, - {{{std::nullopt, {1, 10312}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 9, 1, 6, 450, 2, 0, {0,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols57.dat"}}, - {{{std::nullopt, {1, 16333}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 1, 1, 10, 217, 2, 0, {0,1,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols58.dat"}}, - {{{std::nullopt, {1, 7225}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 10, 1, 10, 451, 2, 0, {0,1,2,3,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols59.dat"}}, - {{{std::nullopt, {1, 4932}, cyclic_prefix::NORMAL, 51, 1, 17, {}, 2, 2, 1, 526, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols60.dat"}}, - {{{std::nullopt, {1, 6922}, cyclic_prefix::NORMAL, 51, 1, 31, {}, 5, 2, 5, 676, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols61.dat"}}, - {{{std::nullopt, {1, 6630}, cyclic_prefix::NORMAL, 51, 1, 31, {}, 3, 2, 11, 447, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols62.dat"}}, - {{{std::nullopt, {1, 18420}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 6, 2, 7, 381, 1, 1, {0,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols63.dat"}}, - {{{std::nullopt, {1, 9510}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 9, 2, 7, 498, 1, 1, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols64.dat"}}, - {{{std::nullopt, {1, 19269}, cyclic_prefix::NORMAL, 51, 1, 28, {}, 3, 2, 0, 819, 1, 1, {0,1,2,3,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols65.dat"}}, - {{{std::nullopt, {1, 11524}, cyclic_prefix::NORMAL, 51, 1, 23, {}, 10, 2, 9, 474, 2, 1, {0,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols66.dat"}}, - {{{std::nullopt, {1, 3786}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 6, 2, 3, 570, 2, 1, {0,1,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols67.dat"}}, - {{{std::nullopt, {1, 8986}, cyclic_prefix::NORMAL, 51, 1, 26, {}, 1, 2, 3, 862, 2, 1, {0,1,2,3,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols68.dat"}}, - {{{std::nullopt, {1, 15387}, cyclic_prefix::NORMAL, 51, 1, 46, {}, 8, 2, 2, 822, 1, 0, {0,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols69.dat"}}, - {{{std::nullopt, {1, 17097}, cyclic_prefix::NORMAL, 51, 1, 5, {}, 4, 2, 5, 662, 1, 0, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols70.dat"}}, - {{{std::nullopt, {1, 4473}, cyclic_prefix::NORMAL, 51, 1, 46, {}, 7, 2, 9, 35, 1, 0, {0,1,2,3,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols71.dat"}}, - {{{std::nullopt, {1, 14792}, cyclic_prefix::NORMAL, 51, 1, 22, {}, 6, 2, 0, 451, 2, 0, {0,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols72.dat"}}, - {{{std::nullopt, {1, 16115}, cyclic_prefix::NORMAL, 51, 1, 4, {}, 12, 2, 6, 31, 2, 0, {0,1,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols73.dat"}}, - {{{std::nullopt, {1, 4329}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 0, 2, 9, 795, 2, 0, {0,1,2,3,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols74.dat"}}, - {{{std::nullopt, {1, 12202}, cyclic_prefix::NORMAL, 51, 1, 28, {11}, 1, 2, 7, 344, 0, 1, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols75.dat"}}, - {{{std::nullopt, {1, 5694}, cyclic_prefix::NORMAL, 51, 1, 7, {18}, 9, 2, 10, 261, 0, 1, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols76.dat"}}, - {{{std::nullopt, {1, 19064}, cyclic_prefix::NORMAL, 51, 1, 20, {30}, 1, 2, 5, 456, 0, 1, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols77.dat"}}, - {{{std::nullopt, {1, 19137}, cyclic_prefix::NORMAL, 51, 1, 28, {49}, 0, 2, 11, 23, 1, 1, {0,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols78.dat"}}, - {{{std::nullopt, {1, 18417}, cyclic_prefix::NORMAL, 51, 1, 11, {37}, 0, 2, 2, 603, 1, 1, {0,1,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols79.dat"}}, - {{{std::nullopt, {1, 8608}, cyclic_prefix::NORMAL, 51, 1, 10, {32}, 1, 2, 11, 943, 1, 1, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols80.dat"}}, - {{{std::nullopt, {1, 136}, cyclic_prefix::NORMAL, 51, 1, 9, {10}, 4, 2, 4, 82, 2, 1, {0,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols81.dat"}}, - {{{std::nullopt, {1, 11273}, cyclic_prefix::NORMAL, 51, 1, 32, {12}, 5, 2, 1, 806, 2, 1, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols82.dat"}}, - {{{std::nullopt, {1, 17130}, cyclic_prefix::NORMAL, 51, 1, 31, {23}, 1, 2, 2, 376, 2, 1, {0,1,2,3,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols83.dat"}}, - {{{std::nullopt, {1, 3841}, cyclic_prefix::NORMAL, 51, 1, 36, {33}, 11, 2, 3, 359, 1, 0, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols84.dat"}}, - {{{std::nullopt, {1, 15557}, cyclic_prefix::NORMAL, 51, 1, 42, {23}, 1, 2, 5, 79, 1, 0, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols85.dat"}}, - {{{std::nullopt, {1, 19928}, cyclic_prefix::NORMAL, 51, 1, 0, {36}, 8, 2, 3, 98, 1, 0, {0,1,2,3,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols86.dat"}}, - {{{std::nullopt, {1, 13669}, cyclic_prefix::NORMAL, 51, 1, 29, {16}, 9, 2, 10, 96, 2, 0, {0,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols87.dat"}}, - {{{std::nullopt, {1, 14472}, cyclic_prefix::NORMAL, 51, 1, 19, {9}, 10, 2, 5, 237, 2, 0, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols88.dat"}}, - {{{std::nullopt, {1, 3181}, cyclic_prefix::NORMAL, 51, 1, 33, {32}, 4, 2, 1, 21, 2, 0, {0,1,2,3,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols89.dat"}}, + {{{std::nullopt, {0, 999}, cyclic_prefix::NORMAL, 51, 1, 6, {}, 12, 1, 7, 821, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols0.dat"}}, + {{{std::nullopt, {0, 4307}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 13, 1, 3, 256, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols1.dat"}}, + {{{std::nullopt, {0, 4717}, cyclic_prefix::NORMAL, 51, 1, 35, {}, 10, 1, 3, 5, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols2.dat"}}, + {{{std::nullopt, {0, 7750}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 3, 1, 8, 214, 1, true, {0,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols3.dat"}}, + {{{std::nullopt, {0, 1757}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 7, 1, 0, 993, 1, true, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols4.dat"}}, + {{{std::nullopt, {0, 4302}, cyclic_prefix::NORMAL, 51, 1, 22, {}, 12, 1, 1, 596, 1, true, {0,1,2,3,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols5.dat"}}, + {{{std::nullopt, {0, 4847}, cyclic_prefix::NORMAL, 51, 1, 0, {}, 11, 1, 8, 379, 2, true, {0,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols6.dat"}}, + {{{std::nullopt, {0, 6635}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 8, 1, 7, 627, 2, true, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols7.dat"}}, + {{{std::nullopt, {0, 4521}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 1, 1, 5, 836, 2, true, {0,1,2,3,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols8.dat"}}, + {{{std::nullopt, {0, 9573}, cyclic_prefix::NORMAL, 51, 1, 11, {}, 3, 1, 1, 727, 1, false, {0,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols9.dat"}}, + {{{std::nullopt, {0, 3370}, cyclic_prefix::NORMAL, 51, 1, 25, {}, 12, 1, 0, 425, 1, false, {0,1,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols10.dat"}}, + {{{std::nullopt, {0, 154}, cyclic_prefix::NORMAL, 51, 1, 7, {}, 4, 1, 3, 272, 1, false, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols11.dat"}}, + {{{std::nullopt, {0, 7636}, cyclic_prefix::NORMAL, 51, 1, 45, {}, 0, 1, 0, 152, 2, false, {0,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols12.dat"}}, + {{{std::nullopt, {0, 2333}, cyclic_prefix::NORMAL, 51, 1, 18, {}, 10, 1, 9, 816, 2, false, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols13.dat"}}, + {{{std::nullopt, {0, 7914}, cyclic_prefix::NORMAL, 51, 1, 8, {}, 8, 1, 6, 646, 2, false, {0,1,2,3,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols14.dat"}}, + {{{std::nullopt, {0, 9634}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 6, 2, 9, 631, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols15.dat"}}, + {{{std::nullopt, {0, 1489}, cyclic_prefix::NORMAL, 51, 1, 50, {}, 11, 2, 8, 527, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols16.dat"}}, + {{{std::nullopt, {0, 8182}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 3, 2, 2, 1007, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols17.dat"}}, + {{{std::nullopt, {0, 4745}, cyclic_prefix::NORMAL, 51, 1, 1, {}, 0, 2, 9, 525, 1, true, {0,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols18.dat"}}, + {{{std::nullopt, {0, 3781}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 8, 2, 4, 38, 1, true, {0,1,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols19.dat"}}, + {{{std::nullopt, {0, 2014}, cyclic_prefix::NORMAL, 51, 1, 47, {}, 8, 2, 10, 938, 1, true, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols20.dat"}}, + {{{std::nullopt, {0, 2900}, cyclic_prefix::NORMAL, 51, 1, 12, {}, 2, 2, 9, 624, 2, true, {0,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols21.dat"}}, + {{{std::nullopt, {0, 5526}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 7, 2, 10, 46, 2, true, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols22.dat"}}, + {{{std::nullopt, {0, 5982}, cyclic_prefix::NORMAL, 51, 1, 28, {}, 3, 2, 4, 226, 2, true, {0,1,2,3,}}, {1, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols23.dat"}}, + {{{std::nullopt, {0, 967}, cyclic_prefix::NORMAL, 51, 1, 20, {}, 10, 2, 4, 746, 1, false, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols24.dat"}}, + {{{std::nullopt, {0, 3223}, cyclic_prefix::NORMAL, 51, 1, 15, {}, 4, 2, 5, 887, 1, false, {0,1,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols25.dat"}}, + {{{std::nullopt, {0, 5384}, cyclic_prefix::NORMAL, 51, 1, 3, {}, 12, 2, 0, 63, 1, false, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols26.dat"}}, + {{{std::nullopt, {0, 3801}, cyclic_prefix::NORMAL, 51, 1, 50, {}, 10, 2, 9, 84, 2, false, {0,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols27.dat"}}, + {{{std::nullopt, {0, 1080}, cyclic_prefix::NORMAL, 51, 1, 43, {}, 0, 2, 7, 447, 2, false, {0,1,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols28.dat"}}, + {{{std::nullopt, {0, 1704}, cyclic_prefix::NORMAL, 51, 1, 37, {}, 3, 2, 7, 691, 2, false, {0,1,2,3,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols29.dat"}}, + {{{std::nullopt, {0, 2838}, cyclic_prefix::NORMAL, 51, 1, 38, {41}, 7, 2, 9, 195, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols30.dat"}}, + {{{std::nullopt, {0, 4643}, cyclic_prefix::NORMAL, 51, 1, 20, {28}, 5, 2, 3, 984, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols31.dat"}}, + {{{std::nullopt, {0, 7840}, cyclic_prefix::NORMAL, 51, 1, 0, {47}, 10, 2, 1, 719, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols32.dat"}}, + {{{std::nullopt, {0, 379}, cyclic_prefix::NORMAL, 51, 1, 3, {50}, 9, 2, 2, 394, 1, true, {0,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols33.dat"}}, + {{{std::nullopt, {0, 9807}, cyclic_prefix::NORMAL, 51, 1, 22, {13}, 3, 2, 5, 811, 1, true, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols34.dat"}}, + {{{std::nullopt, {0, 8793}, cyclic_prefix::NORMAL, 51, 1, 15, {35}, 8, 2, 4, 638, 1, true, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols35.dat"}}, + {{{std::nullopt, {0, 2375}, cyclic_prefix::NORMAL, 51, 1, 49, {25}, 8, 2, 4, 390, 2, true, {0,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols36.dat"}}, + {{{std::nullopt, {0, 3654}, cyclic_prefix::NORMAL, 51, 1, 18, {37}, 9, 2, 11, 200, 2, true, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols37.dat"}}, + {{{std::nullopt, {0, 2807}, cyclic_prefix::NORMAL, 51, 1, 44, {43}, 11, 2, 3, 379, 2, true, {0,1,2,3,}}, {0, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols38.dat"}}, + {{{std::nullopt, {0, 1443}, cyclic_prefix::NORMAL, 51, 1, 45, {21}, 0, 2, 10, 105, 1, false, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols39.dat"}}, + {{{std::nullopt, {0, 9501}, cyclic_prefix::NORMAL, 51, 1, 11, {9}, 1, 2, 10, 188, 1, false, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols40.dat"}}, + {{{std::nullopt, {0, 2234}, cyclic_prefix::NORMAL, 51, 1, 31, {18}, 9, 2, 1, 483, 1, false, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols41.dat"}}, + {{{std::nullopt, {0, 6443}, cyclic_prefix::NORMAL, 51, 1, 35, {8}, 10, 2, 8, 768, 2, false, {0,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols42.dat"}}, + {{{std::nullopt, {0, 6690}, cyclic_prefix::NORMAL, 51, 1, 49, {14}, 10, 2, 10, 747, 2, false, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols43.dat"}}, + {{{std::nullopt, {0, 6257}, cyclic_prefix::NORMAL, 51, 1, 28, {36}, 7, 2, 5, 385, 2, false, {0,1,2,3,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols44.dat"}}, + {{{std::nullopt, {1, 17146}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 4, 1, 0, 798, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols45.dat"}}, + {{{std::nullopt, {1, 18241}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 12, 1, 10, 709, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols46.dat"}}, + {{{std::nullopt, {1, 861}, cyclic_prefix::NORMAL, 51, 1, 8, {}, 9, 1, 2, 847, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols47.dat"}}, + {{{std::nullopt, {1, 12746}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 11, 1, 8, 622, 1, true, {0,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols48.dat"}}, + {{{std::nullopt, {1, 15747}, cyclic_prefix::NORMAL, 51, 1, 2, {}, 2, 1, 0, 641, 1, true, {0,1,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols49.dat"}}, + {{{std::nullopt, {1, 3093}, cyclic_prefix::NORMAL, 51, 1, 4, {}, 4, 1, 1, 209, 1, true, {0,1,2,3,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols50.dat"}}, + {{{std::nullopt, {1, 10210}, cyclic_prefix::NORMAL, 51, 1, 41, {}, 0, 1, 7, 91, 2, true, {0,}}, {1, 1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols51.dat"}}, + {{{std::nullopt, {1, 19008}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 9, 1, 6, 977, 2, true, {0,1,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols52.dat"}}, + {{{std::nullopt, {1, 10774}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 9, 1, 0, 655, 2, true, {0,1,2,3,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols53.dat"}}, + {{{std::nullopt, {1, 2319}, cyclic_prefix::NORMAL, 51, 1, 42, {}, 8, 1, 4, 2, 1, false, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols54.dat"}}, + {{{std::nullopt, {1, 5068}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 12, 1, 7, 643, 1, false, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols55.dat"}}, + {{{std::nullopt, {1, 2865}, cyclic_prefix::NORMAL, 51, 1, 3, {}, 1, 1, 4, 653, 1, false, {0,1,2,3,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols56.dat"}}, + {{{std::nullopt, {1, 10312}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 9, 1, 6, 450, 2, false, {0,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols57.dat"}}, + {{{std::nullopt, {1, 16333}, cyclic_prefix::NORMAL, 51, 1, 49, {}, 1, 1, 10, 217, 2, false, {0,1,}}, {1, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols58.dat"}}, + {{{std::nullopt, {1, 7225}, cyclic_prefix::NORMAL, 51, 1, 16, {}, 10, 1, 10, 451, 2, false, {0,1,2,3,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols59.dat"}}, + {{{std::nullopt, {1, 4932}, cyclic_prefix::NORMAL, 51, 1, 17, {}, 2, 2, 1, 526, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols60.dat"}}, + {{{std::nullopt, {1, 6922}, cyclic_prefix::NORMAL, 51, 1, 31, {}, 5, 2, 5, 676, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols61.dat"}}, + {{{std::nullopt, {1, 6630}, cyclic_prefix::NORMAL, 51, 1, 31, {}, 3, 2, 11, 447, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols62.dat"}}, + {{{std::nullopt, {1, 18420}, cyclic_prefix::NORMAL, 51, 1, 40, {}, 6, 2, 7, 381, 1, true, {0,}}, {1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols63.dat"}}, + {{{std::nullopt, {1, 9510}, cyclic_prefix::NORMAL, 51, 1, 27, {}, 9, 2, 7, 498, 1, true, {0,1,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols64.dat"}}, + {{{std::nullopt, {1, 19269}, cyclic_prefix::NORMAL, 51, 1, 28, {}, 3, 2, 0, 819, 1, true, {0,1,2,3,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols65.dat"}}, + {{{std::nullopt, {1, 11524}, cyclic_prefix::NORMAL, 51, 1, 23, {}, 10, 2, 9, 474, 2, true, {0,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols66.dat"}}, + {{{std::nullopt, {1, 3786}, cyclic_prefix::NORMAL, 51, 1, 32, {}, 6, 2, 3, 570, 2, true, {0,1,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols67.dat"}}, + {{{std::nullopt, {1, 8986}, cyclic_prefix::NORMAL, 51, 1, 26, {}, 1, 2, 3, 862, 2, true, {0,1,2,3,}}, {0, 0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols68.dat"}}, + {{{std::nullopt, {1, 15387}, cyclic_prefix::NORMAL, 51, 1, 46, {}, 8, 2, 2, 822, 1, false, {0,}}, {1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols69.dat"}}, + {{{std::nullopt, {1, 17097}, cyclic_prefix::NORMAL, 51, 1, 5, {}, 4, 2, 5, 662, 1, false, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols70.dat"}}, + {{{std::nullopt, {1, 4473}, cyclic_prefix::NORMAL, 51, 1, 46, {}, 7, 2, 9, 35, 1, false, {0,1,2,3,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols71.dat"}}, + {{{std::nullopt, {1, 14792}, cyclic_prefix::NORMAL, 51, 1, 22, {}, 6, 2, 0, 451, 2, false, {0,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols72.dat"}}, + {{{std::nullopt, {1, 16115}, cyclic_prefix::NORMAL, 51, 1, 4, {}, 12, 2, 6, 31, 2, false, {0,1,}}, {0, 1}, {}}, {"test_data/pucch_processor_format0_test_input_symbols73.dat"}}, + {{{std::nullopt, {1, 4329}, cyclic_prefix::NORMAL, 51, 1, 44, {}, 0, 2, 9, 795, 2, false, {0,1,2,3,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols74.dat"}}, + {{{std::nullopt, {1, 12202}, cyclic_prefix::NORMAL, 51, 1, 28, {11}, 1, 2, 7, 344, 0, true, {0,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols75.dat"}}, + {{{std::nullopt, {1, 5694}, cyclic_prefix::NORMAL, 51, 1, 7, {18}, 9, 2, 10, 261, 0, true, {0,1,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols76.dat"}}, + {{{std::nullopt, {1, 19064}, cyclic_prefix::NORMAL, 51, 1, 20, {30}, 1, 2, 5, 456, 0, true, {0,1,2,3,}}, {}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols77.dat"}}, + {{{std::nullopt, {1, 19137}, cyclic_prefix::NORMAL, 51, 1, 28, {49}, 0, 2, 11, 23, 1, true, {0,}}, {0}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols78.dat"}}, + {{{std::nullopt, {1, 18417}, cyclic_prefix::NORMAL, 51, 1, 11, {37}, 0, 2, 2, 603, 1, true, {0,1,}}, {0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols79.dat"}}, + {{{std::nullopt, {1, 8608}, cyclic_prefix::NORMAL, 51, 1, 10, {32}, 1, 2, 11, 943, 1, true, {0,1,2,3,}}, {1}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols80.dat"}}, + {{{std::nullopt, {1, 136}, cyclic_prefix::NORMAL, 51, 1, 9, {10}, 4, 2, 4, 82, 2, true, {0,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols81.dat"}}, + {{{std::nullopt, {1, 11273}, cyclic_prefix::NORMAL, 51, 1, 32, {12}, 5, 2, 1, 806, 2, true, {0,1,}}, {0, 0}, {1}}, {"test_data/pucch_processor_format0_test_input_symbols82.dat"}}, + {{{std::nullopt, {1, 17130}, cyclic_prefix::NORMAL, 51, 1, 31, {23}, 1, 2, 2, 376, 2, true, {0,1,2,3,}}, {0, 1}, {0}}, {"test_data/pucch_processor_format0_test_input_symbols83.dat"}}, + {{{std::nullopt, {1, 3841}, cyclic_prefix::NORMAL, 51, 1, 36, {33}, 11, 2, 3, 359, 1, false, {0,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols84.dat"}}, + {{{std::nullopt, {1, 15557}, cyclic_prefix::NORMAL, 51, 1, 42, {23}, 1, 2, 5, 79, 1, false, {0,1,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols85.dat"}}, + {{{std::nullopt, {1, 19928}, cyclic_prefix::NORMAL, 51, 1, 0, {36}, 8, 2, 3, 98, 1, false, {0,1,2,3,}}, {0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols86.dat"}}, + {{{std::nullopt, {1, 13669}, cyclic_prefix::NORMAL, 51, 1, 29, {16}, 9, 2, 10, 96, 2, false, {0,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols87.dat"}}, + {{{std::nullopt, {1, 14472}, cyclic_prefix::NORMAL, 51, 1, 19, {9}, 10, 2, 5, 237, 2, false, {0,1,}}, {1, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols88.dat"}}, + {{{std::nullopt, {1, 3181}, cyclic_prefix::NORMAL, 51, 1, 33, {32}, 4, 2, 1, 21, 2, false, {0,1,2,3,}}, {0, 0}, {}}, {"test_data/pucch_processor_format0_test_input_symbols89.dat"}}, // clang-format on }; diff --git a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h index 652c819e0d..71245d4644 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 26-06-2024 (seed 0): +// This file was generated using the following MATLAB class on 24-07-2024 (seed 0): // + "srsChEstimatorUnittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -53,118 +53,118 @@ struct test_case_t { static const std::vector port_channel_estimator_test_data = { // clang-format off - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0143, 2.0227, 20, 20.3467, 0.0093207, 0, 0, -4.4087, {"test_data/port_channel_estimator_test_input_rg0.dat"}, {"test_data/port_channel_estimator_test_pilots0.dat"}, {"test_data/port_channel_estimator_test_output_ch_est0.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0635, 2.0306, 20, 20.6993, 0.0088038, 0.84635, 105, 116.1222, {"test_data/port_channel_estimator_test_input_rg1.dat"}, {"test_data/port_channel_estimator_test_pilots1.dat"}, {"test_data/port_channel_estimator_test_output_ch_est1.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0791, 2.0503, 20, 19.9146, 0.010627, 1.0742, -195, -204.9691, {"test_data/port_channel_estimator_test_input_rg2.dat"}, {"test_data/port_channel_estimator_test_pilots2.dat"}, {"test_data/port_channel_estimator_test_output_ch_est2.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.024, 1.9914, 20, 20.2424, 0.0095935, 0.86263, 405, 398.004, {"test_data/port_channel_estimator_test_input_rg3.dat"}, {"test_data/port_channel_estimator_test_pilots3.dat"}, {"test_data/port_channel_estimator_test_output_ch_est3.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0157, 2.0239, 20, 20.0101, 0.010079, 0.097656, 0, -8.9659, {"test_data/port_channel_estimator_test_input_rg4.dat"}, {"test_data/port_channel_estimator_test_pilots4.dat"}, {"test_data/port_channel_estimator_test_output_ch_est4.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0578, 2.0249, 20, 20.3531, 0.0095082, 0.84635, 105, 105.5152, {"test_data/port_channel_estimator_test_input_rg5.dat"}, {"test_data/port_channel_estimator_test_pilots5.dat"}, {"test_data/port_channel_estimator_test_output_ch_est5.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0202, 2.0275, 20, 20.9718, 0.0080948, 0.10579, -195, -188.1324, {"test_data/port_channel_estimator_test_input_rg6.dat"}, {"test_data/port_channel_estimator_test_pilots6.dat"}, {"test_data/port_channel_estimator_test_output_ch_est6.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0204, 1.9896, 20, 19.556, 0.011216, 0.96842, 405, 407.0491, {"test_data/port_channel_estimator_test_input_rg7.dat"}, {"test_data/port_channel_estimator_test_pilots7.dat"}, {"test_data/port_channel_estimator_test_output_ch_est7.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9704, 1.9827, 20, 18.5265, 0.013865, 0.10579, 0, -30.0356, {"test_data/port_channel_estimator_test_input_rg8.dat"}, {"test_data/port_channel_estimator_test_pilots8.dat"}, {"test_data/port_channel_estimator_test_output_ch_est8.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0094, 2.0225, 20, 19.267, 0.011922, 0.056966, 210, 198.7048, {"test_data/port_channel_estimator_test_input_rg9.dat"}, {"test_data/port_channel_estimator_test_pilots9.dat"}, {"test_data/port_channel_estimator_test_output_ch_est9.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9805, 1.9845, 20, 19.2363, 0.011834, 0.15462, -390, -403.9435, {"test_data/port_channel_estimator_test_input_rg10.dat"}, {"test_data/port_channel_estimator_test_pilots10.dat"}, {"test_data/port_channel_estimator_test_output_ch_est10.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9975, 2.0086, 20, 19.7488, 0.010607, 0.048828, 810, 809.7705, {"test_data/port_channel_estimator_test_input_rg11.dat"}, {"test_data/port_channel_estimator_test_pilots11.dat"}, {"test_data/port_channel_estimator_test_output_ch_est11.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0093, 1.9907, 20, 19.7619, 0.010638, 0.31738, 0, 2.851, {"test_data/port_channel_estimator_test_input_rg12.dat"}, {"test_data/port_channel_estimator_test_pilots12.dat"}, {"test_data/port_channel_estimator_test_output_ch_est12.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0158, 1.9875, 20, 19.7113, 0.010797, 0.42318, 210, 211.648, {"test_data/port_channel_estimator_test_input_rg13.dat"}, {"test_data/port_channel_estimator_test_pilots13.dat"}, {"test_data/port_channel_estimator_test_output_ch_est13.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.999, 2.0061, 20, 20.1501, 0.0096786, 0.052897, -390, -395.3968, {"test_data/port_channel_estimator_test_input_rg14.dat"}, {"test_data/port_channel_estimator_test_pilots14.dat"}, {"test_data/port_channel_estimator_test_output_ch_est14.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0153, 2.0098, 20, 21.0956, 0.0078485, 0.20752, 810, 812.19, {"test_data/port_channel_estimator_test_input_rg15.dat"}, {"test_data/port_channel_estimator_test_pilots15.dat"}, {"test_data/port_channel_estimator_test_output_ch_est15.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0487, 2.0175, 20, 19.9447, 0.0104, 1.0742, 0, -1.6279, {"test_data/port_channel_estimator_test_input_rg16.dat"}, {"test_data/port_channel_estimator_test_pilots16.dat"}, {"test_data/port_channel_estimator_test_output_ch_est16.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9887, 1.997, 20, 20.2945, 0.0093135, 0.11393, 105, 108.8448, {"test_data/port_channel_estimator_test_input_rg17.dat"}, {"test_data/port_channel_estimator_test_pilots17.dat"}, {"test_data/port_channel_estimator_test_output_ch_est17.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0118, 2.0174, 20, 20.4065, 0.0091819, 0.21159, -195, -195.2135, {"test_data/port_channel_estimator_test_input_rg18.dat"}, {"test_data/port_channel_estimator_test_pilots18.dat"}, {"test_data/port_channel_estimator_test_output_ch_est18.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9995, 2.0009, 20, 20.2794, 0.009397, 0.32552, 405, 398.3487, {"test_data/port_channel_estimator_test_input_rg19.dat"}, {"test_data/port_channel_estimator_test_pilots19.dat"}, {"test_data/port_channel_estimator_test_output_ch_est19.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9938, 2.002, 20, 20.6591, 0.0085859, 0.11393, 0, -4.2054, {"test_data/port_channel_estimator_test_input_rg20.dat"}, {"test_data/port_channel_estimator_test_pilots20.dat"}, {"test_data/port_channel_estimator_test_output_ch_est20.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0121, 2.0199, 20, 20.6436, 0.0086956, 0.11393, 105, 101.7418, {"test_data/port_channel_estimator_test_input_rg21.dat"}, {"test_data/port_channel_estimator_test_pilots21.dat"}, {"test_data/port_channel_estimator_test_output_ch_est21.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0016, 2.0079, 20, 20.2485, 0.0094738, 0.21159, -195, -191.3504, {"test_data/port_channel_estimator_test_input_rg22.dat"}, {"test_data/port_channel_estimator_test_pilots22.dat"}, {"test_data/port_channel_estimator_test_output_ch_est22.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9904, 1.9954, 20, 20.7301, 0.0084319, 0.21159, 405, 407.3559, {"test_data/port_channel_estimator_test_input_rg23.dat"}, {"test_data/port_channel_estimator_test_pilots23.dat"}, {"test_data/port_channel_estimator_test_output_ch_est23.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0173, 2.0124, 20, 20.5619, 0.0088834, 0.21159, 0, -5.2553, {"test_data/port_channel_estimator_test_input_rg24.dat"}, {"test_data/port_channel_estimator_test_pilots24.dat"}, {"test_data/port_channel_estimator_test_output_ch_est24.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9931, 2.0024, 20, 20.4725, 0.0089595, 0, 210, 208.5308, {"test_data/port_channel_estimator_test_input_rg25.dat"}, {"test_data/port_channel_estimator_test_pilots25.dat"}, {"test_data/port_channel_estimator_test_output_ch_est25.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0053, 2.0069, 20, 19.996, 0.01006, 0.16276, -390, -398.8123, {"test_data/port_channel_estimator_test_input_rg26.dat"}, {"test_data/port_channel_estimator_test_pilots26.dat"}, {"test_data/port_channel_estimator_test_output_ch_est26.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9906, 1.9964, 20, 20.3591, 0.0091848, 0.10579, 810, 815.9771, {"test_data/port_channel_estimator_test_input_rg27.dat"}, {"test_data/port_channel_estimator_test_pilots27.dat"}, {"test_data/port_channel_estimator_test_output_ch_est27.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0057, 1.9941, 20, 20.4467, 0.0090697, 0.26855, 0, -4.5018, {"test_data/port_channel_estimator_test_input_rg28.dat"}, {"test_data/port_channel_estimator_test_pilots28.dat"}, {"test_data/port_channel_estimator_test_output_ch_est28.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9988, 2.0073, 20, 20.2114, 0.0095419, 0.056966, 210, 217.2379, {"test_data/port_channel_estimator_test_input_rg29.dat"}, {"test_data/port_channel_estimator_test_pilots29.dat"}, {"test_data/port_channel_estimator_test_output_ch_est29.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0232, 1.9908, 20, 20.3972, 0.009254, 0.48014, -390, -385.5204, {"test_data/port_channel_estimator_test_input_rg30.dat"}, {"test_data/port_channel_estimator_test_pilots30.dat"}, {"test_data/port_channel_estimator_test_output_ch_est30.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0372, 2.0042, 20, 20.3757, 0.0093638, 0.53711, 810, 804.2148, {"test_data/port_channel_estimator_test_input_rg31.dat"}, {"test_data/port_channel_estimator_test_pilots31.dat"}, {"test_data/port_channel_estimator_test_output_ch_est31.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0435, 2.0119, 20, 20.0575, 0.010107, 1.0742, 0, 1.5958, {"test_data/port_channel_estimator_test_input_rg32.dat"}, {"test_data/port_channel_estimator_test_pilots32.dat"}, {"test_data/port_channel_estimator_test_output_ch_est32.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0382, 2.0085, 20, 20.3778, 0.0093638, 0.86263, 105, 109.0055, {"test_data/port_channel_estimator_test_input_rg33.dat"}, {"test_data/port_channel_estimator_test_pilots33.dat"}, {"test_data/port_channel_estimator_test_output_ch_est33.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.9939, 2.0033, 20, 20.2794, 0.0093706, 0, -195, -197.4148, {"test_data/port_channel_estimator_test_input_rg34.dat"}, {"test_data/port_channel_estimator_test_pilots34.dat"}, {"test_data/port_channel_estimator_test_output_ch_est34.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0325, 2.0007, 20, 20.0591, 0.010049, 0.96029, 405, 403.5268, {"test_data/port_channel_estimator_test_input_rg35.dat"}, {"test_data/port_channel_estimator_test_pilots35.dat"}, {"test_data/port_channel_estimator_test_output_ch_est35.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0004, 2.0085, 20, 20.4074, 0.009128, 0.056966, 0, 2.6347, {"test_data/port_channel_estimator_test_input_rg36.dat"}, {"test_data/port_channel_estimator_test_pilots36.dat"}, {"test_data/port_channel_estimator_test_output_ch_est36.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0414, 2.0092, 20, 20.2677, 0.0096194, 0.48014, 210, 204.1927, {"test_data/port_channel_estimator_test_input_rg37.dat"}, {"test_data/port_channel_estimator_test_pilots37.dat"}, {"test_data/port_channel_estimator_test_output_ch_est37.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0187, 2.0139, 20, 20.4222, 0.00918, 0.21159, -390, -391.2151, {"test_data/port_channel_estimator_test_input_rg38.dat"}, {"test_data/port_channel_estimator_test_pilots38.dat"}, {"test_data/port_channel_estimator_test_output_ch_est38.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 2.0187, 2.0142, 20, 20.2277, 0.0096007, 0.21159, 810, 809.1345, {"test_data/port_channel_estimator_test_input_rg39.dat"}, {"test_data/port_channel_estimator_test_pilots39.dat"}, {"test_data/port_channel_estimator_test_output_ch_est39.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.92667, 1.0079, 20, 10.3881, 0.084744, 0, 0, 17.8793, {"test_data/port_channel_estimator_test_input_rg40.dat"}, {"test_data/port_channel_estimator_test_pilots40.dat"}, {"test_data/port_channel_estimator_test_output_ch_est40.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.98288, 0.99546, 20, 18.7455, 0.013121, 0, 105, 100.1957, {"test_data/port_channel_estimator_test_input_rg41.dat"}, {"test_data/port_channel_estimator_test_pilots41.dat"}, {"test_data/port_channel_estimator_test_output_ch_est41.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.98872, 1.0176, 20, 15.163, 0.030114, 0, -195, -249.8832, {"test_data/port_channel_estimator_test_input_rg42.dat"}, {"test_data/port_channel_estimator_test_pilots42.dat"}, {"test_data/port_channel_estimator_test_output_ch_est42.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.8379, 0.99569, 20, 7.0663, 0.16465, 0, 405, 458.8566, {"test_data/port_channel_estimator_test_input_rg43.dat"}, {"test_data/port_channel_estimator_test_pilots43.dat"}, {"test_data/port_channel_estimator_test_output_ch_est43.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.92702, 0.97098, 20, 13.0561, 0.045865, 0, 0, {}, {"test_data/port_channel_estimator_test_input_rg44.dat"}, {"test_data/port_channel_estimator_test_pilots44.dat"}, {"test_data/port_channel_estimator_test_output_ch_est44.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.96481, 0.97192, 20, 21.1381, 0.0074239, 0, 105, {}, {"test_data/port_channel_estimator_test_input_rg45.dat"}, {"test_data/port_channel_estimator_test_pilots45.dat"}, {"test_data/port_channel_estimator_test_output_ch_est45.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.98636, 1.0385, 20, 12.5825, 0.054424, 0, -195, {}, {"test_data/port_channel_estimator_test_input_rg46.dat"}, {"test_data/port_channel_estimator_test_pilots46.dat"}, {"test_data/port_channel_estimator_test_output_ch_est46.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 1.0025, 1.0136, 20, 19.3678, 0.011596, 0, 405, {}, {"test_data/port_channel_estimator_test_input_rg47.dat"}, {"test_data/port_channel_estimator_test_pilots47.dat"}, {"test_data/port_channel_estimator_test_output_ch_est47.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.9379, 1.009, 20, 11.0155, 0.074234, 0, 0, 141.6522, {"test_data/port_channel_estimator_test_input_rg48.dat"}, {"test_data/port_channel_estimator_test_pilots48.dat"}, {"test_data/port_channel_estimator_test_output_ch_est48.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.90768, 1.0274, 20, 8.614, 0.12489, 0, 210, 162.3948, {"test_data/port_channel_estimator_test_input_rg49.dat"}, {"test_data/port_channel_estimator_test_pilots49.dat"}, {"test_data/port_channel_estimator_test_output_ch_est49.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.99797, 1.0129, 20, 18.0514, 0.015631, 0, -390, -371.8697, {"test_data/port_channel_estimator_test_input_rg50.dat"}, {"test_data/port_channel_estimator_test_pilots50.dat"}, {"test_data/port_channel_estimator_test_output_ch_est50.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.9157, 1.0035, 20, 9.9976, 0.091621, 0, 810, 785.3555, {"test_data/port_channel_estimator_test_input_rg51.dat"}, {"test_data/port_channel_estimator_test_pilots51.dat"}, {"test_data/port_channel_estimator_test_output_ch_est51.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.94304, 1.0386, 20, 9.7579, 0.09971, 0, 0, {}, {"test_data/port_channel_estimator_test_input_rg52.dat"}, {"test_data/port_channel_estimator_test_pilots52.dat"}, {"test_data/port_channel_estimator_test_output_ch_est52.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.9393, 0.99071, 20, 12.4326, 0.053647, 0, 210, {}, {"test_data/port_channel_estimator_test_input_rg53.dat"}, {"test_data/port_channel_estimator_test_pilots53.dat"}, {"test_data/port_channel_estimator_test_output_ch_est53.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.90854, 1.0178, 20, 9.0127, 0.11404, 0, -390, {}, {"test_data/port_channel_estimator_test_input_rg54.dat"}, {"test_data/port_channel_estimator_test_pilots54.dat"}, {"test_data/port_channel_estimator_test_output_ch_est54.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 1.0539, 1.0641, 20, 19.957, 0.010643, 0, 810, {}, {"test_data/port_channel_estimator_test_input_rg55.dat"}, {"test_data/port_channel_estimator_test_pilots55.dat"}, {"test_data/port_channel_estimator_test_output_ch_est55.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.96191, 1.0109, 20, 12.8743, 0.049626, 0, 0, 60.4937, {"test_data/port_channel_estimator_test_input_rg56.dat"}, {"test_data/port_channel_estimator_test_pilots56.dat"}, {"test_data/port_channel_estimator_test_output_ch_est56.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.92806, 0.97217, 20, 13.1785, 0.04464, 0, 105, 133.8908, {"test_data/port_channel_estimator_test_input_rg57.dat"}, {"test_data/port_channel_estimator_test_pilots57.dat"}, {"test_data/port_channel_estimator_test_output_ch_est57.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.8481, 0.97469, 20, 8.2085, 0.12811, 0, -195, -157.735, {"test_data/port_channel_estimator_test_input_rg58.dat"}, {"test_data/port_channel_estimator_test_pilots58.dat"}, {"test_data/port_channel_estimator_test_output_ch_est58.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.5525, 1.0007, 20, 0.85624, 0.45364, 0, 405, 423.366, {"test_data/port_channel_estimator_test_input_rg59.dat"}, {"test_data/port_channel_estimator_test_pilots59.dat"}, {"test_data/port_channel_estimator_test_output_ch_est59.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.99336, 1.0019, 20, 20.587, 0.0086778, 0, 0, -0.86513, {"test_data/port_channel_estimator_test_input_rg60.dat"}, {"test_data/port_channel_estimator_test_pilots60.dat"}, {"test_data/port_channel_estimator_test_output_ch_est60.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.97749, 1.0007, 20, 16.1878, 0.023515, 0, 105, 116.191, {"test_data/port_channel_estimator_test_input_rg61.dat"}, {"test_data/port_channel_estimator_test_pilots61.dat"}, {"test_data/port_channel_estimator_test_output_ch_est61.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.90884, 1.0059, 20, 9.6636, 0.098204, 0, -195, -195.3017, {"test_data/port_channel_estimator_test_input_rg62.dat"}, {"test_data/port_channel_estimator_test_pilots62.dat"}, {"test_data/port_channel_estimator_test_output_ch_est62.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.79189, 1.0323, 20, 5.1249, 0.24332, 0, 405, 436.0944, {"test_data/port_channel_estimator_test_input_rg63.dat"}, {"test_data/port_channel_estimator_test_pilots63.dat"}, {"test_data/port_channel_estimator_test_output_ch_est63.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.98671, 1.0077, 20, 16.6618, 0.021282, 0, 0, 38.8966, {"test_data/port_channel_estimator_test_input_rg64.dat"}, {"test_data/port_channel_estimator_test_pilots64.dat"}, {"test_data/port_channel_estimator_test_output_ch_est64.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.92538, 1.0131, 20, 10.1789, 0.088803, 0, 210, 261.8987, {"test_data/port_channel_estimator_test_input_rg65.dat"}, {"test_data/port_channel_estimator_test_pilots65.dat"}, {"test_data/port_channel_estimator_test_output_ch_est65.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.86183, 1.0104, 20, 7.583, 0.15036, 0, -390, -338.1823, {"test_data/port_channel_estimator_test_input_rg66.dat"}, {"test_data/port_channel_estimator_test_pilots66.dat"}, {"test_data/port_channel_estimator_test_output_ch_est66.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.51508, 1.011, 20, 0.11269, 0.50189, 0, 810, 778.57, {"test_data/port_channel_estimator_test_input_rg67.dat"}, {"test_data/port_channel_estimator_test_pilots67.dat"}, {"test_data/port_channel_estimator_test_output_ch_est67.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.9677, 1.022, 20, 12.4575, 0.054953, 0, 0, 36.887, {"test_data/port_channel_estimator_test_input_rg68.dat"}, {"test_data/port_channel_estimator_test_pilots68.dat"}, {"test_data/port_channel_estimator_test_output_ch_est68.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.97489, 1.001, 20, 15.6744, 0.026394, 0, 210, 201.1862, {"test_data/port_channel_estimator_test_input_rg69.dat"}, {"test_data/port_channel_estimator_test_pilots69.dat"}, {"test_data/port_channel_estimator_test_output_ch_est69.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.95291, 1.0053, 20, 12.5452, 0.053031, 0, -390, -471.9865, {"test_data/port_channel_estimator_test_input_rg70.dat"}, {"test_data/port_channel_estimator_test_pilots70.dat"}, {"test_data/port_channel_estimator_test_output_ch_est70.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, 0, 52, 0.78307, 1.0071, 20, 5.3828, 0.22673, 0, 810, 739.4834, {"test_data/port_channel_estimator_test_input_rg71.dat"}, {"test_data/port_channel_estimator_test_pilots71.dat"}, {"test_data/port_channel_estimator_test_output_ch_est71.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.90818, 0.96077, 20, 23.4291, 0.0041235, 1.0905, 0, -77.8652, {"test_data/port_channel_estimator_test_input_rg72.dat"}, {"test_data/port_channel_estimator_test_pilots72.dat"}, {"test_data/port_channel_estimator_test_output_ch_est72.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.9917, 1.0279, 20, 18.6853, 0.013423, 0.87891, 105, -21.1131, {"test_data/port_channel_estimator_test_input_rg73.dat"}, {"test_data/port_channel_estimator_test_pilots73.dat"}, {"test_data/port_channel_estimator_test_output_ch_est73.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.99378, 1.0461, 20, 21.8448, 0.0064984, 1.0091, -195, -185.0026, {"test_data/port_channel_estimator_test_input_rg74.dat"}, {"test_data/port_channel_estimator_test_pilots74.dat"}, {"test_data/port_channel_estimator_test_output_ch_est74.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.91883, 0.91961, 20, 20.3598, 0.0084578, 0.11393, 405, 261.1756, {"test_data/port_channel_estimator_test_input_rg75.dat"}, {"test_data/port_channel_estimator_test_pilots75.dat"}, {"test_data/port_channel_estimator_test_output_ch_est75.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.89601, 0.94902, 20, 21.6617, 0.0061114, 1.001, 0, {}, {"test_data/port_channel_estimator_test_input_rg76.dat"}, {"test_data/port_channel_estimator_test_pilots76.dat"}, {"test_data/port_channel_estimator_test_output_ch_est76.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0014, 1.0106, 20, 22.8022, 0.0052526, 0.08138, 105, {}, {"test_data/port_channel_estimator_test_input_rg77.dat"}, {"test_data/port_channel_estimator_test_pilots77.dat"}, {"test_data/port_channel_estimator_test_output_ch_est77.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0065, 1.0107, 20, 25.2981, 0.0029716, 0.04069, -195, {}, {"test_data/port_channel_estimator_test_input_rg78.dat"}, {"test_data/port_channel_estimator_test_pilots78.dat"}, {"test_data/port_channel_estimator_test_output_ch_est78.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.9985, 1.052, 20, 21.1924, 0.0075877, 0.93587, 405, {}, {"test_data/port_channel_estimator_test_input_rg79.dat"}, {"test_data/port_channel_estimator_test_pilots79.dat"}, {"test_data/port_channel_estimator_test_output_ch_est79.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.94751, 0.98757, 20, 18.0578, 0.014818, 0.39062, 0, 328.1227, {"test_data/port_channel_estimator_test_input_rg80.dat"}, {"test_data/port_channel_estimator_test_pilots80.dat"}, {"test_data/port_channel_estimator_test_output_ch_est80.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0419, 1.0425, 20, 21.1019, 0.0080841, 0.048828, 210, 161.7025, {"test_data/port_channel_estimator_test_input_rg81.dat"}, {"test_data/port_channel_estimator_test_pilots81.dat"}, {"test_data/port_channel_estimator_test_output_ch_est81.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.94052, 0.9704, 20, 17.2206, 0.017836, 0.21973, -390, -386.9386, {"test_data/port_channel_estimator_test_input_rg82.dat"}, {"test_data/port_channel_estimator_test_pilots82.dat"}, {"test_data/port_channel_estimator_test_output_ch_est82.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.99352, 1.0204, 20, 19.0758, 0.012291, 0.19531, 810, 1327.7275, {"test_data/port_channel_estimator_test_input_rg83.dat"}, {"test_data/port_channel_estimator_test_pilots83.dat"}, {"test_data/port_channel_estimator_test_output_ch_est83.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0474, 1.1004, 20, 22.5891, 0.0057701, 0.49235, 0, {}, {"test_data/port_channel_estimator_test_input_rg84.dat"}, {"test_data/port_channel_estimator_test_pilots84.dat"}, {"test_data/port_channel_estimator_test_output_ch_est84.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.955, 0.96624, 20, 20.4317, 0.0086464, -0.012207, 210, {}, {"test_data/port_channel_estimator_test_input_rg85.dat"}, {"test_data/port_channel_estimator_test_pilots85.dat"}, {"test_data/port_channel_estimator_test_output_ch_est85.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.98178, 0.97926, 20, 23.2012, 0.0046978, 0.073242, -390, {}, {"test_data/port_channel_estimator_test_input_rg86.dat"}, {"test_data/port_channel_estimator_test_pilots86.dat"}, {"test_data/port_channel_estimator_test_output_ch_est86.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.9291, 0.935, 20, 22.2528, 0.0055307, 0.24007, 810, {}, {"test_data/port_channel_estimator_test_input_rg87.dat"}, {"test_data/port_channel_estimator_test_pilots87.dat"}, {"test_data/port_channel_estimator_test_output_ch_est87.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.1114, 1.0514, 20, 22.0965, 0.0068587, 0.65104, 0, {}, {"test_data/port_channel_estimator_test_input_rg88.dat"}, {"test_data/port_channel_estimator_test_pilots88.dat"}, {"test_data/port_channel_estimator_test_output_ch_est88.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0805, 0.97166, 20, 20.2555, 0.010187, 0.96029, 105, {}, {"test_data/port_channel_estimator_test_input_rg89.dat"}, {"test_data/port_channel_estimator_test_pilots89.dat"}, {"test_data/port_channel_estimator_test_output_ch_est89.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.1009, 1.076, 20, 23.5785, 0.0048292, 0.42318, -195, {}, {"test_data/port_channel_estimator_test_input_rg90.dat"}, {"test_data/port_channel_estimator_test_pilots90.dat"}, {"test_data/port_channel_estimator_test_output_ch_est90.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.98669, 0.9906, 20, 23.144, 0.0047839, 0.11393, 405, {}, {"test_data/port_channel_estimator_test_input_rg91.dat"}, {"test_data/port_channel_estimator_test_pilots91.dat"}, {"test_data/port_channel_estimator_test_output_ch_est91.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0078, 0.99632, 20, 22.5326, 0.005625, 0.15462, 0, {}, {"test_data/port_channel_estimator_test_input_rg92.dat"}, {"test_data/port_channel_estimator_test_pilots92.dat"}, {"test_data/port_channel_estimator_test_output_ch_est92.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0113, 1.0185, 20, 20.553, 0.008904, 0, 210, {}, {"test_data/port_channel_estimator_test_input_rg93.dat"}, {"test_data/port_channel_estimator_test_pilots93.dat"}, {"test_data/port_channel_estimator_test_output_ch_est93.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0376, 1.0327, 20, 22.4415, 0.005914, 0.10579, -390, {}, {"test_data/port_channel_estimator_test_input_rg94.dat"}, {"test_data/port_channel_estimator_test_pilots94.dat"}, {"test_data/port_channel_estimator_test_output_ch_est94.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0591, 0.98466, 20, 20.4074, 0.009643, 0.37435, 810, {}, {"test_data/port_channel_estimator_test_input_rg95.dat"}, {"test_data/port_channel_estimator_test_pilots95.dat"}, {"test_data/port_channel_estimator_test_output_ch_est95.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0153, 1.0161, 20, 20.4588, 0.0091356, 0.21159, 0, 37.2051, {"test_data/port_channel_estimator_test_input_rg96.dat"}, {"test_data/port_channel_estimator_test_pilots96.dat"}, {"test_data/port_channel_estimator_test_output_ch_est96.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0143, 1.0215, 20, 20.2096, 0.0096654, 0.11393, 105, 114.1783, {"test_data/port_channel_estimator_test_input_rg97.dat"}, {"test_data/port_channel_estimator_test_pilots97.dat"}, {"test_data/port_channel_estimator_test_output_ch_est97.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.1163, 1.0205, 20, 20.1495, 0.010785, 0.86263, -195, -146.8239, {"test_data/port_channel_estimator_test_input_rg98.dat"}, {"test_data/port_channel_estimator_test_pilots98.dat"}, {"test_data/port_channel_estimator_test_output_ch_est98.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0155, 1.0217, 20, 20.8441, 0.0083614, 0.11393, 405, 448.619, {"test_data/port_channel_estimator_test_input_rg99.dat"}, {"test_data/port_channel_estimator_test_pilots99.dat"}, {"test_data/port_channel_estimator_test_output_ch_est99.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0445, 0.98772, 20, 21.9494, 0.0066673, 0.6429, 0, {}, {"test_data/port_channel_estimator_test_input_rg100.dat"}, {"test_data/port_channel_estimator_test_pilots100.dat"}, {"test_data/port_channel_estimator_test_output_ch_est100.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0608, 1.0055, 20, 21.2982, 0.0078669, 0.63477, 105, {}, {"test_data/port_channel_estimator_test_input_rg101.dat"}, {"test_data/port_channel_estimator_test_pilots101.dat"}, {"test_data/port_channel_estimator_test_output_ch_est101.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0566, 1.0007, 20, 21.4424, 0.0075803, 0.6429, -195, {}, {"test_data/port_channel_estimator_test_input_rg102.dat"}, {"test_data/port_channel_estimator_test_pilots102.dat"}, {"test_data/port_channel_estimator_test_output_ch_est102.dat"}}, - {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0666, 1.01, 20, 21.8603, 0.0069497, 0.63477, 405, {}, {"test_data/port_channel_estimator_test_input_rg103.dat"}, {"test_data/port_channel_estimator_test_pilots103.dat"}, {"test_data/port_channel_estimator_test_output_ch_est103.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0762, 1.0027, 20, 20.9423, 0.0086632, 0.37435, 0, -36.5569, {"test_data/port_channel_estimator_test_input_rg104.dat"}, {"test_data/port_channel_estimator_test_pilots104.dat"}, {"test_data/port_channel_estimator_test_output_ch_est104.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.104, 1.0099, 20, 20.0255, 0.010975, 0.43132, 210, 78.3938, {"test_data/port_channel_estimator_test_input_rg105.dat"}, {"test_data/port_channel_estimator_test_pilots105.dat"}, {"test_data/port_channel_estimator_test_output_ch_est105.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.98938, 0.99864, 20, 20.3087, 0.0092149, 0, -390, -494.4192, {"test_data/port_channel_estimator_test_input_rg106.dat"}, {"test_data/port_channel_estimator_test_pilots106.dat"}, {"test_data/port_channel_estimator_test_output_ch_est106.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0075, 1.0135, 20, 21.1577, 0.0077172, 0.056966, 810, 743.568, {"test_data/port_channel_estimator_test_input_rg107.dat"}, {"test_data/port_channel_estimator_test_pilots107.dat"}, {"test_data/port_channel_estimator_test_output_ch_est107.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.99234, 0.9942, 20, 20.9477, 0.007978, 0.10579, 0, {}, {"test_data/port_channel_estimator_test_input_rg108.dat"}, {"test_data/port_channel_estimator_test_pilots108.dat"}, {"test_data/port_channel_estimator_test_output_ch_est108.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0422, 1.0038, 20, 21.3842, 0.0075773, 0.26855, 210, {}, {"test_data/port_channel_estimator_test_input_rg109.dat"}, {"test_data/port_channel_estimator_test_pilots109.dat"}, {"test_data/port_channel_estimator_test_output_ch_est109.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 0.97966, 0.98446, 20, 22.2941, 0.0057765, 0.052897, -390, {}, {"test_data/port_channel_estimator_test_input_rg110.dat"}, {"test_data/port_channel_estimator_test_pilots110.dat"}, {"test_data/port_channel_estimator_test_output_ch_est110.dat"}}, - {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, 1, 52, 1.0467, 1.0077, 20, 22.0156, 0.0065804, 0.26855, 810, {}, {"test_data/port_channel_estimator_test_input_rg111.dat"}, {"test_data/port_channel_estimator_test_pilots111.dat"}, {"test_data/port_channel_estimator_test_output_ch_est111.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0143, 2.0227, 20, 20.3467, 0.0093207, 0, 0, -4.4087, {"test_data/port_channel_estimator_test_input_rg0.dat"}, {"test_data/port_channel_estimator_test_pilots0.dat"}, {"test_data/port_channel_estimator_test_output_ch_est0.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0635, 2.0306, 20, 20.6993, 0.0088038, 0.84635, 105, 116.1222, {"test_data/port_channel_estimator_test_input_rg1.dat"}, {"test_data/port_channel_estimator_test_pilots1.dat"}, {"test_data/port_channel_estimator_test_output_ch_est1.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0791, 2.0503, 20, 19.9146, 0.010627, 1.0742, -195, -204.9691, {"test_data/port_channel_estimator_test_input_rg2.dat"}, {"test_data/port_channel_estimator_test_pilots2.dat"}, {"test_data/port_channel_estimator_test_output_ch_est2.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.024, 1.9914, 20, 20.2424, 0.0095935, 0.86263, 405, 398.004, {"test_data/port_channel_estimator_test_input_rg3.dat"}, {"test_data/port_channel_estimator_test_pilots3.dat"}, {"test_data/port_channel_estimator_test_output_ch_est3.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0157, 2.0239, 20, 20.0101, 0.010079, 0.097656, 0, -8.9659, {"test_data/port_channel_estimator_test_input_rg4.dat"}, {"test_data/port_channel_estimator_test_pilots4.dat"}, {"test_data/port_channel_estimator_test_output_ch_est4.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0578, 2.0249, 20, 20.3531, 0.0095082, 0.84635, 105, 105.5152, {"test_data/port_channel_estimator_test_input_rg5.dat"}, {"test_data/port_channel_estimator_test_pilots5.dat"}, {"test_data/port_channel_estimator_test_output_ch_est5.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0202, 2.0275, 20, 20.9718, 0.0080948, 0.10579, -195, -188.1324, {"test_data/port_channel_estimator_test_input_rg6.dat"}, {"test_data/port_channel_estimator_test_pilots6.dat"}, {"test_data/port_channel_estimator_test_output_ch_est6.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0204, 1.9896, 20, 19.556, 0.011216, 0.96842, 405, 407.0491, {"test_data/port_channel_estimator_test_input_rg7.dat"}, {"test_data/port_channel_estimator_test_pilots7.dat"}, {"test_data/port_channel_estimator_test_output_ch_est7.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9704, 1.9827, 20, 18.5265, 0.013865, 0.10579, 0, -30.0356, {"test_data/port_channel_estimator_test_input_rg8.dat"}, {"test_data/port_channel_estimator_test_pilots8.dat"}, {"test_data/port_channel_estimator_test_output_ch_est8.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0094, 2.0225, 20, 19.267, 0.011922, 0.056966, 210, 198.7048, {"test_data/port_channel_estimator_test_input_rg9.dat"}, {"test_data/port_channel_estimator_test_pilots9.dat"}, {"test_data/port_channel_estimator_test_output_ch_est9.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9805, 1.9845, 20, 19.2363, 0.011834, 0.15462, -390, -403.9435, {"test_data/port_channel_estimator_test_input_rg10.dat"}, {"test_data/port_channel_estimator_test_pilots10.dat"}, {"test_data/port_channel_estimator_test_output_ch_est10.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9975, 2.0086, 20, 19.7488, 0.010607, 0.048828, 810, 809.7705, {"test_data/port_channel_estimator_test_input_rg11.dat"}, {"test_data/port_channel_estimator_test_pilots11.dat"}, {"test_data/port_channel_estimator_test_output_ch_est11.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0093, 1.9907, 20, 19.7619, 0.010638, 0.31738, 0, 2.851, {"test_data/port_channel_estimator_test_input_rg12.dat"}, {"test_data/port_channel_estimator_test_pilots12.dat"}, {"test_data/port_channel_estimator_test_output_ch_est12.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0158, 1.9875, 20, 19.7113, 0.010797, 0.42318, 210, 211.648, {"test_data/port_channel_estimator_test_input_rg13.dat"}, {"test_data/port_channel_estimator_test_pilots13.dat"}, {"test_data/port_channel_estimator_test_output_ch_est13.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.999, 2.0061, 20, 20.1501, 0.0096786, 0.052897, -390, -395.3968, {"test_data/port_channel_estimator_test_input_rg14.dat"}, {"test_data/port_channel_estimator_test_pilots14.dat"}, {"test_data/port_channel_estimator_test_output_ch_est14.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0153, 2.0098, 20, 21.0956, 0.0078485, 0.20752, 810, 812.19, {"test_data/port_channel_estimator_test_input_rg15.dat"}, {"test_data/port_channel_estimator_test_pilots15.dat"}, {"test_data/port_channel_estimator_test_output_ch_est15.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0487, 2.0175, 20, 19.9447, 0.0104, 1.0742, 0, -1.6279, {"test_data/port_channel_estimator_test_input_rg16.dat"}, {"test_data/port_channel_estimator_test_pilots16.dat"}, {"test_data/port_channel_estimator_test_output_ch_est16.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9887, 1.997, 20, 20.2945, 0.0093135, 0.11393, 105, 108.8448, {"test_data/port_channel_estimator_test_input_rg17.dat"}, {"test_data/port_channel_estimator_test_pilots17.dat"}, {"test_data/port_channel_estimator_test_output_ch_est17.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0118, 2.0174, 20, 20.4065, 0.0091819, 0.21159, -195, -195.2135, {"test_data/port_channel_estimator_test_input_rg18.dat"}, {"test_data/port_channel_estimator_test_pilots18.dat"}, {"test_data/port_channel_estimator_test_output_ch_est18.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9995, 2.0009, 20, 20.2794, 0.009397, 0.32552, 405, 398.3487, {"test_data/port_channel_estimator_test_input_rg19.dat"}, {"test_data/port_channel_estimator_test_pilots19.dat"}, {"test_data/port_channel_estimator_test_output_ch_est19.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9938, 2.002, 20, 20.6591, 0.0085859, 0.11393, 0, -4.2054, {"test_data/port_channel_estimator_test_input_rg20.dat"}, {"test_data/port_channel_estimator_test_pilots20.dat"}, {"test_data/port_channel_estimator_test_output_ch_est20.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0121, 2.0199, 20, 20.6436, 0.0086956, 0.11393, 105, 101.7418, {"test_data/port_channel_estimator_test_input_rg21.dat"}, {"test_data/port_channel_estimator_test_pilots21.dat"}, {"test_data/port_channel_estimator_test_output_ch_est21.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0016, 2.0079, 20, 20.2485, 0.0094738, 0.21159, -195, -191.3504, {"test_data/port_channel_estimator_test_input_rg22.dat"}, {"test_data/port_channel_estimator_test_pilots22.dat"}, {"test_data/port_channel_estimator_test_output_ch_est22.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9904, 1.9954, 20, 20.7301, 0.0084319, 0.21159, 405, 407.3559, {"test_data/port_channel_estimator_test_input_rg23.dat"}, {"test_data/port_channel_estimator_test_pilots23.dat"}, {"test_data/port_channel_estimator_test_output_ch_est23.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0173, 2.0124, 20, 20.5619, 0.0088834, 0.21159, 0, -5.2553, {"test_data/port_channel_estimator_test_input_rg24.dat"}, {"test_data/port_channel_estimator_test_pilots24.dat"}, {"test_data/port_channel_estimator_test_output_ch_est24.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9931, 2.0024, 20, 20.4725, 0.0089595, 0, 210, 208.5308, {"test_data/port_channel_estimator_test_input_rg25.dat"}, {"test_data/port_channel_estimator_test_pilots25.dat"}, {"test_data/port_channel_estimator_test_output_ch_est25.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0053, 2.0069, 20, 19.996, 0.01006, 0.16276, -390, -398.8123, {"test_data/port_channel_estimator_test_input_rg26.dat"}, {"test_data/port_channel_estimator_test_pilots26.dat"}, {"test_data/port_channel_estimator_test_output_ch_est26.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9906, 1.9964, 20, 20.3591, 0.0091848, 0.10579, 810, 815.9771, {"test_data/port_channel_estimator_test_input_rg27.dat"}, {"test_data/port_channel_estimator_test_pilots27.dat"}, {"test_data/port_channel_estimator_test_output_ch_est27.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0057, 1.9941, 20, 20.4467, 0.0090697, 0.26855, 0, -4.5018, {"test_data/port_channel_estimator_test_input_rg28.dat"}, {"test_data/port_channel_estimator_test_pilots28.dat"}, {"test_data/port_channel_estimator_test_output_ch_est28.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9988, 2.0073, 20, 20.2114, 0.0095419, 0.056966, 210, 217.2379, {"test_data/port_channel_estimator_test_input_rg29.dat"}, {"test_data/port_channel_estimator_test_pilots29.dat"}, {"test_data/port_channel_estimator_test_output_ch_est29.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0232, 1.9908, 20, 20.3972, 0.009254, 0.48014, -390, -385.5204, {"test_data/port_channel_estimator_test_input_rg30.dat"}, {"test_data/port_channel_estimator_test_pilots30.dat"}, {"test_data/port_channel_estimator_test_output_ch_est30.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0372, 2.0042, 20, 20.3757, 0.0093638, 0.53711, 810, 804.2148, {"test_data/port_channel_estimator_test_input_rg31.dat"}, {"test_data/port_channel_estimator_test_pilots31.dat"}, {"test_data/port_channel_estimator_test_output_ch_est31.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0435, 2.0119, 20, 20.0575, 0.010107, 1.0742, 0, 1.5958, {"test_data/port_channel_estimator_test_input_rg32.dat"}, {"test_data/port_channel_estimator_test_pilots32.dat"}, {"test_data/port_channel_estimator_test_output_ch_est32.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0382, 2.0085, 20, 20.3778, 0.0093638, 0.86263, 105, 109.0055, {"test_data/port_channel_estimator_test_input_rg33.dat"}, {"test_data/port_channel_estimator_test_pilots33.dat"}, {"test_data/port_channel_estimator_test_output_ch_est33.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.9939, 2.0033, 20, 20.2794, 0.0093706, 0, -195, -197.4148, {"test_data/port_channel_estimator_test_input_rg34.dat"}, {"test_data/port_channel_estimator_test_pilots34.dat"}, {"test_data/port_channel_estimator_test_output_ch_est34.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0325, 2.0007, 20, 20.0591, 0.010049, 0.96029, 405, 403.5268, {"test_data/port_channel_estimator_test_input_rg35.dat"}, {"test_data/port_channel_estimator_test_pilots35.dat"}, {"test_data/port_channel_estimator_test_output_ch_est35.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0004, 2.0085, 20, 20.4074, 0.009128, 0.056966, 0, 2.6347, {"test_data/port_channel_estimator_test_input_rg36.dat"}, {"test_data/port_channel_estimator_test_pilots36.dat"}, {"test_data/port_channel_estimator_test_output_ch_est36.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0414, 2.0092, 20, 20.2677, 0.0096194, 0.48014, 210, 204.1927, {"test_data/port_channel_estimator_test_input_rg37.dat"}, {"test_data/port_channel_estimator_test_pilots37.dat"}, {"test_data/port_channel_estimator_test_output_ch_est37.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0187, 2.0139, 20, 20.4222, 0.00918, 0.21159, -390, -391.2151, {"test_data/port_channel_estimator_test_input_rg38.dat"}, {"test_data/port_channel_estimator_test_pilots38.dat"}, {"test_data/port_channel_estimator_test_output_ch_est38.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, std::nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 2.0187, 2.0142, 20, 20.2277, 0.0096007, 0.21159, 810, 809.1345, {"test_data/port_channel_estimator_test_input_rg39.dat"}, {"test_data/port_channel_estimator_test_pilots39.dat"}, {"test_data/port_channel_estimator_test_output_ch_est39.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.92667, 1.0079, 20, 10.3881, 0.084744, 0, 0, 17.8793, {"test_data/port_channel_estimator_test_input_rg40.dat"}, {"test_data/port_channel_estimator_test_pilots40.dat"}, {"test_data/port_channel_estimator_test_output_ch_est40.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.98288, 0.99546, 20, 18.7455, 0.013121, 0, 105, 100.1957, {"test_data/port_channel_estimator_test_input_rg41.dat"}, {"test_data/port_channel_estimator_test_pilots41.dat"}, {"test_data/port_channel_estimator_test_output_ch_est41.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.98872, 1.0176, 20, 15.163, 0.030114, 0, -195, -249.8832, {"test_data/port_channel_estimator_test_input_rg42.dat"}, {"test_data/port_channel_estimator_test_pilots42.dat"}, {"test_data/port_channel_estimator_test_output_ch_est42.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.8379, 0.99569, 20, 7.0663, 0.16465, 0, 405, 458.8566, {"test_data/port_channel_estimator_test_input_rg43.dat"}, {"test_data/port_channel_estimator_test_pilots43.dat"}, {"test_data/port_channel_estimator_test_output_ch_est43.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.92702, 0.97098, 20, 13.0561, 0.045865, 0, 0, {}, {"test_data/port_channel_estimator_test_input_rg44.dat"}, {"test_data/port_channel_estimator_test_pilots44.dat"}, {"test_data/port_channel_estimator_test_output_ch_est44.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.96481, 0.97192, 20, 21.1381, 0.0074239, 0, 105, {}, {"test_data/port_channel_estimator_test_input_rg45.dat"}, {"test_data/port_channel_estimator_test_pilots45.dat"}, {"test_data/port_channel_estimator_test_output_ch_est45.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.98636, 1.0385, 20, 12.5825, 0.054424, 0, -195, {}, {"test_data/port_channel_estimator_test_input_rg46.dat"}, {"test_data/port_channel_estimator_test_pilots46.dat"}, {"test_data/port_channel_estimator_test_output_ch_est46.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 1.0025, 1.0136, 20, 19.3678, 0.011596, 0, 405, {}, {"test_data/port_channel_estimator_test_input_rg47.dat"}, {"test_data/port_channel_estimator_test_pilots47.dat"}, {"test_data/port_channel_estimator_test_output_ch_est47.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.9379, 1.009, 20, 11.0155, 0.074234, 0, 0, 141.6522, {"test_data/port_channel_estimator_test_input_rg48.dat"}, {"test_data/port_channel_estimator_test_pilots48.dat"}, {"test_data/port_channel_estimator_test_output_ch_est48.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.90768, 1.0274, 20, 8.614, 0.12489, 0, 210, 162.3948, {"test_data/port_channel_estimator_test_input_rg49.dat"}, {"test_data/port_channel_estimator_test_pilots49.dat"}, {"test_data/port_channel_estimator_test_output_ch_est49.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.99797, 1.0129, 20, 18.0514, 0.015631, 0, -390, -371.8697, {"test_data/port_channel_estimator_test_input_rg50.dat"}, {"test_data/port_channel_estimator_test_pilots50.dat"}, {"test_data/port_channel_estimator_test_output_ch_est50.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.9157, 1.0035, 20, 9.9976, 0.091621, 0, 810, 785.3555, {"test_data/port_channel_estimator_test_input_rg51.dat"}, {"test_data/port_channel_estimator_test_pilots51.dat"}, {"test_data/port_channel_estimator_test_output_ch_est51.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.94304, 1.0386, 20, 9.7579, 0.09971, 0, 0, {}, {"test_data/port_channel_estimator_test_input_rg52.dat"}, {"test_data/port_channel_estimator_test_pilots52.dat"}, {"test_data/port_channel_estimator_test_output_ch_est52.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.9393, 0.99071, 20, 12.4326, 0.053647, 0, 210, {}, {"test_data/port_channel_estimator_test_input_rg53.dat"}, {"test_data/port_channel_estimator_test_pilots53.dat"}, {"test_data/port_channel_estimator_test_output_ch_est53.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.90854, 1.0178, 20, 9.0127, 0.11404, 0, -390, {}, {"test_data/port_channel_estimator_test_input_rg54.dat"}, {"test_data/port_channel_estimator_test_pilots54.dat"}, {"test_data/port_channel_estimator_test_output_ch_est54.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 8, 4, {{{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 1.0539, 1.0641, 20, 19.957, 0.010643, 0, 810, {}, {"test_data/port_channel_estimator_test_input_rg55.dat"}, {"test_data/port_channel_estimator_test_pilots55.dat"}, {"test_data/port_channel_estimator_test_output_ch_est55.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.96191, 1.0109, 20, 12.8743, 0.049626, 0, 0, 60.4937, {"test_data/port_channel_estimator_test_input_rg56.dat"}, {"test_data/port_channel_estimator_test_pilots56.dat"}, {"test_data/port_channel_estimator_test_output_ch_est56.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.92806, 0.97217, 20, 13.1785, 0.04464, 0, 105, 133.8908, {"test_data/port_channel_estimator_test_input_rg57.dat"}, {"test_data/port_channel_estimator_test_pilots57.dat"}, {"test_data/port_channel_estimator_test_output_ch_est57.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.8481, 0.97469, 20, 8.2085, 0.12811, 0, -195, -157.735, {"test_data/port_channel_estimator_test_input_rg58.dat"}, {"test_data/port_channel_estimator_test_pilots58.dat"}, {"test_data/port_channel_estimator_test_output_ch_est58.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.5525, 1.0007, 20, 0.85624, 0.45364, 0, 405, 423.366, {"test_data/port_channel_estimator_test_input_rg59.dat"}, {"test_data/port_channel_estimator_test_pilots59.dat"}, {"test_data/port_channel_estimator_test_output_ch_est59.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.99336, 1.0019, 20, 20.587, 0.0086778, 0, 0, -0.86513, {"test_data/port_channel_estimator_test_input_rg60.dat"}, {"test_data/port_channel_estimator_test_pilots60.dat"}, {"test_data/port_channel_estimator_test_output_ch_est60.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.97749, 1.0007, 20, 16.1878, 0.023515, 0, 105, 116.191, {"test_data/port_channel_estimator_test_input_rg61.dat"}, {"test_data/port_channel_estimator_test_pilots61.dat"}, {"test_data/port_channel_estimator_test_output_ch_est61.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.90884, 1.0059, 20, 9.6636, 0.098204, 0, -195, -195.3017, {"test_data/port_channel_estimator_test_input_rg62.dat"}, {"test_data/port_channel_estimator_test_pilots62.dat"}, {"test_data/port_channel_estimator_test_output_ch_est62.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.79189, 1.0323, 20, 5.1249, 0.24332, 0, 405, 436.0944, {"test_data/port_channel_estimator_test_input_rg63.dat"}, {"test_data/port_channel_estimator_test_pilots63.dat"}, {"test_data/port_channel_estimator_test_output_ch_est63.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.98671, 1.0077, 20, 16.6618, 0.021282, 0, 0, 38.8966, {"test_data/port_channel_estimator_test_input_rg64.dat"}, {"test_data/port_channel_estimator_test_pilots64.dat"}, {"test_data/port_channel_estimator_test_output_ch_est64.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.92538, 1.0131, 20, 10.1789, 0.088803, 0, 210, 261.8987, {"test_data/port_channel_estimator_test_input_rg65.dat"}, {"test_data/port_channel_estimator_test_pilots65.dat"}, {"test_data/port_channel_estimator_test_output_ch_est65.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.86183, 1.0104, 20, 7.583, 0.15036, 0, -390, -338.1823, {"test_data/port_channel_estimator_test_input_rg66.dat"}, {"test_data/port_channel_estimator_test_pilots66.dat"}, {"test_data/port_channel_estimator_test_output_ch_est66.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.51508, 1.011, 20, 0.11269, 0.50189, 0, 810, 778.57, {"test_data/port_channel_estimator_test_input_rg67.dat"}, {"test_data/port_channel_estimator_test_pilots67.dat"}, {"test_data/port_channel_estimator_test_output_ch_est67.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.9677, 1.022, 20, 12.4575, 0.054953, 0, 0, 36.887, {"test_data/port_channel_estimator_test_input_rg68.dat"}, {"test_data/port_channel_estimator_test_pilots68.dat"}, {"test_data/port_channel_estimator_test_output_ch_est68.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.97489, 1.001, 20, 15.6744, 0.026394, 0, 210, 201.1862, {"test_data/port_channel_estimator_test_input_rg69.dat"}, {"test_data/port_channel_estimator_test_pilots69.dat"}, {"test_data/port_channel_estimator_test_output_ch_est69.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.95291, 1.0053, 20, 12.5452, 0.053031, 0, -390, -471.9865, {"test_data/port_channel_estimator_test_input_rg70.dat"}, {"test_data/port_channel_estimator_test_pilots70.dat"}, {"test_data/port_channel_estimator_test_output_ch_est70.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 14, {{{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::mean, false, 52, 0.78307, 1.0071, 20, 5.3828, 0.22673, 0, 810, 739.4834, {"test_data/port_channel_estimator_test_input_rg71.dat"}, {"test_data/port_channel_estimator_test_pilots71.dat"}, {"test_data/port_channel_estimator_test_output_ch_est71.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.90818, 0.96077, 20, 23.4291, 0.0041235, 1.0905, 0, -77.8652, {"test_data/port_channel_estimator_test_input_rg72.dat"}, {"test_data/port_channel_estimator_test_pilots72.dat"}, {"test_data/port_channel_estimator_test_output_ch_est72.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.9917, 1.0279, 20, 18.6853, 0.013423, 0.87891, 105, -21.1131, {"test_data/port_channel_estimator_test_input_rg73.dat"}, {"test_data/port_channel_estimator_test_pilots73.dat"}, {"test_data/port_channel_estimator_test_output_ch_est73.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.99378, 1.0461, 20, 21.8448, 0.0064984, 1.0091, -195, -185.0026, {"test_data/port_channel_estimator_test_input_rg74.dat"}, {"test_data/port_channel_estimator_test_pilots74.dat"}, {"test_data/port_channel_estimator_test_output_ch_est74.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.91883, 0.91961, 20, 20.3598, 0.0084578, 0.11393, 405, 261.1756, {"test_data/port_channel_estimator_test_input_rg75.dat"}, {"test_data/port_channel_estimator_test_pilots75.dat"}, {"test_data/port_channel_estimator_test_output_ch_est75.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.89601, 0.94902, 20, 21.6617, 0.0061114, 1.001, 0, {}, {"test_data/port_channel_estimator_test_input_rg76.dat"}, {"test_data/port_channel_estimator_test_pilots76.dat"}, {"test_data/port_channel_estimator_test_output_ch_est76.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0014, 1.0106, 20, 22.8022, 0.0052526, 0.08138, 105, {}, {"test_data/port_channel_estimator_test_input_rg77.dat"}, {"test_data/port_channel_estimator_test_pilots77.dat"}, {"test_data/port_channel_estimator_test_output_ch_est77.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0065, 1.0107, 20, 25.2981, 0.0029716, 0.04069, -195, {}, {"test_data/port_channel_estimator_test_input_rg78.dat"}, {"test_data/port_channel_estimator_test_pilots78.dat"}, {"test_data/port_channel_estimator_test_output_ch_est78.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.9985, 1.052, 20, 21.1924, 0.0075877, 0.93587, 405, {}, {"test_data/port_channel_estimator_test_input_rg79.dat"}, {"test_data/port_channel_estimator_test_pilots79.dat"}, {"test_data/port_channel_estimator_test_output_ch_est79.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.94751, 0.98757, 20, 18.0578, 0.014818, 0.39062, 0, 328.1227, {"test_data/port_channel_estimator_test_input_rg80.dat"}, {"test_data/port_channel_estimator_test_pilots80.dat"}, {"test_data/port_channel_estimator_test_output_ch_est80.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0419, 1.0425, 20, 21.1019, 0.0080841, 0.048828, 210, 161.7025, {"test_data/port_channel_estimator_test_input_rg81.dat"}, {"test_data/port_channel_estimator_test_pilots81.dat"}, {"test_data/port_channel_estimator_test_output_ch_est81.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.94052, 0.9704, 20, 17.2206, 0.017836, 0.21973, -390, -386.9386, {"test_data/port_channel_estimator_test_input_rg82.dat"}, {"test_data/port_channel_estimator_test_pilots82.dat"}, {"test_data/port_channel_estimator_test_output_ch_est82.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.99352, 1.0204, 20, 19.0758, 0.012291, 0.19531, 810, 1327.7275, {"test_data/port_channel_estimator_test_input_rg83.dat"}, {"test_data/port_channel_estimator_test_pilots83.dat"}, {"test_data/port_channel_estimator_test_output_ch_est83.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0474, 1.1004, 20, 22.5891, 0.0057701, 0.49235, 0, {}, {"test_data/port_channel_estimator_test_input_rg84.dat"}, {"test_data/port_channel_estimator_test_pilots84.dat"}, {"test_data/port_channel_estimator_test_output_ch_est84.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.955, 0.96624, 20, 20.4317, 0.0086464, -0.012207, 210, {}, {"test_data/port_channel_estimator_test_input_rg85.dat"}, {"test_data/port_channel_estimator_test_pilots85.dat"}, {"test_data/port_channel_estimator_test_output_ch_est85.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.98178, 0.97926, 20, 23.2012, 0.0046978, 0.073242, -390, {}, {"test_data/port_channel_estimator_test_input_rg86.dat"}, {"test_data/port_channel_estimator_test_pilots86.dat"}, {"test_data/port_channel_estimator_test_output_ch_est86.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 0, 2, {{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.9291, 0.935, 20, 22.2528, 0.0055307, 0.24007, 810, {}, {"test_data/port_channel_estimator_test_input_rg87.dat"}, {"test_data/port_channel_estimator_test_pilots87.dat"}, {"test_data/port_channel_estimator_test_output_ch_est87.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.1114, 1.0514, 20, 22.0965, 0.0068587, 0.65104, 0, {}, {"test_data/port_channel_estimator_test_input_rg88.dat"}, {"test_data/port_channel_estimator_test_pilots88.dat"}, {"test_data/port_channel_estimator_test_output_ch_est88.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0805, 0.97166, 20, 20.2555, 0.010187, 0.96029, 105, {}, {"test_data/port_channel_estimator_test_input_rg89.dat"}, {"test_data/port_channel_estimator_test_pilots89.dat"}, {"test_data/port_channel_estimator_test_output_ch_est89.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.1009, 1.076, 20, 23.5785, 0.0048292, 0.42318, -195, {}, {"test_data/port_channel_estimator_test_input_rg90.dat"}, {"test_data/port_channel_estimator_test_pilots90.dat"}, {"test_data/port_channel_estimator_test_output_ch_est90.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.98669, 0.9906, 20, 23.144, 0.0047839, 0.11393, 405, {}, {"test_data/port_channel_estimator_test_input_rg91.dat"}, {"test_data/port_channel_estimator_test_pilots91.dat"}, {"test_data/port_channel_estimator_test_output_ch_est91.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0078, 0.99632, 20, 22.5326, 0.005625, 0.15462, 0, {}, {"test_data/port_channel_estimator_test_input_rg92.dat"}, {"test_data/port_channel_estimator_test_pilots92.dat"}, {"test_data/port_channel_estimator_test_output_ch_est92.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0113, 1.0185, 20, 20.553, 0.008904, 0, 210, {}, {"test_data/port_channel_estimator_test_input_rg93.dat"}, {"test_data/port_channel_estimator_test_pilots93.dat"}, {"test_data/port_channel_estimator_test_output_ch_est93.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0376, 1.0327, 20, 22.4415, 0.005914, 0.10579, -390, {}, {"test_data/port_channel_estimator_test_input_rg94.dat"}, {"test_data/port_channel_estimator_test_pilots94.dat"}, {"test_data/port_channel_estimator_test_output_ch_est94.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 1, {{{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0591, 0.98466, 20, 20.4074, 0.009643, 0.37435, 810, {}, {"test_data/port_channel_estimator_test_input_rg95.dat"}, {"test_data/port_channel_estimator_test_pilots95.dat"}, {"test_data/port_channel_estimator_test_output_ch_est95.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0153, 1.0161, 20, 20.4588, 0.0091356, 0.21159, 0, 37.2051, {"test_data/port_channel_estimator_test_input_rg96.dat"}, {"test_data/port_channel_estimator_test_pilots96.dat"}, {"test_data/port_channel_estimator_test_output_ch_est96.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0143, 1.0215, 20, 20.2096, 0.0096654, 0.11393, 105, 114.1783, {"test_data/port_channel_estimator_test_input_rg97.dat"}, {"test_data/port_channel_estimator_test_pilots97.dat"}, {"test_data/port_channel_estimator_test_output_ch_est97.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.1163, 1.0205, 20, 20.1495, 0.010785, 0.86263, -195, -146.8239, {"test_data/port_channel_estimator_test_input_rg98.dat"}, {"test_data/port_channel_estimator_test_pilots98.dat"}, {"test_data/port_channel_estimator_test_output_ch_est98.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0155, 1.0217, 20, 20.8441, 0.0083614, 0.11393, 405, 448.619, {"test_data/port_channel_estimator_test_input_rg99.dat"}, {"test_data/port_channel_estimator_test_pilots99.dat"}, {"test_data/port_channel_estimator_test_output_ch_est99.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0445, 0.98772, 20, 21.9494, 0.0066673, 0.6429, 0, {}, {"test_data/port_channel_estimator_test_input_rg100.dat"}, {"test_data/port_channel_estimator_test_pilots100.dat"}, {"test_data/port_channel_estimator_test_output_ch_est100.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0608, 1.0055, 20, 21.2982, 0.0078669, 0.63477, 105, {}, {"test_data/port_channel_estimator_test_input_rg101.dat"}, {"test_data/port_channel_estimator_test_pilots101.dat"}, {"test_data/port_channel_estimator_test_output_ch_est101.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0566, 1.0007, 20, 21.4424, 0.0075803, 0.6429, -195, {}, {"test_data/port_channel_estimator_test_input_rg102.dat"}, {"test_data/port_channel_estimator_test_pilots102.dat"}, {"test_data/port_channel_estimator_test_output_ch_est102.dat"}}, + {{subcarrier_spacing::kHz15, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0666, 1.01, 20, 21.8603, 0.0069497, 0.63477, 405, {}, {"test_data/port_channel_estimator_test_input_rg103.dat"}, {"test_data/port_channel_estimator_test_pilots103.dat"}, {"test_data/port_channel_estimator_test_output_ch_est103.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0762, 1.0027, 20, 20.9423, 0.0086632, 0.37435, 0, -36.5569, {"test_data/port_channel_estimator_test_input_rg104.dat"}, {"test_data/port_channel_estimator_test_pilots104.dat"}, {"test_data/port_channel_estimator_test_output_ch_est104.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.104, 1.0099, 20, 20.0255, 0.010975, 0.43132, 210, 78.3938, {"test_data/port_channel_estimator_test_input_rg105.dat"}, {"test_data/port_channel_estimator_test_pilots105.dat"}, {"test_data/port_channel_estimator_test_output_ch_est105.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.98938, 0.99864, 20, 20.3087, 0.0092149, 0, -390, -494.4192, {"test_data/port_channel_estimator_test_input_rg106.dat"}, {"test_data/port_channel_estimator_test_pilots106.dat"}, {"test_data/port_channel_estimator_test_output_ch_est106.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, std::nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0075, 1.0135, 20, 21.1577, 0.0077172, 0.056966, 810, 743.568, {"test_data/port_channel_estimator_test_input_rg107.dat"}, {"test_data/port_channel_estimator_test_pilots107.dat"}, {"test_data/port_channel_estimator_test_output_ch_est107.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.99234, 0.9942, 20, 20.9477, 0.007978, 0.10579, 0, {}, {"test_data/port_channel_estimator_test_input_rg108.dat"}, {"test_data/port_channel_estimator_test_pilots108.dat"}, {"test_data/port_channel_estimator_test_output_ch_est108.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0422, 1.0038, 20, 21.3842, 0.0075773, 0.26855, 210, {}, {"test_data/port_channel_estimator_test_input_rg109.dat"}, {"test_data/port_channel_estimator_test_pilots109.dat"}, {"test_data/port_channel_estimator_test_output_ch_est109.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 0.97966, 0.98446, 20, 22.2941, 0.0057765, 0.052897, -390, {}, {"test_data/port_channel_estimator_test_input_rg110.dat"}, {"test_data/port_channel_estimator_test_pilots110.dat"}, {"test_data/port_channel_estimator_test_output_ch_est110.dat"}}, + {{subcarrier_spacing::kHz30, cyclic_prefix::NORMAL, 5, 2, {{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, port_channel_estimator_fd_smoothing_strategy::filter, true, 52, 1.0467, 1.0077, 20, 22.0156, 0.0065804, 0.26855, 810, {}, {"test_data/port_channel_estimator_test_input_rg111.dat"}, {"test_data/port_channel_estimator_test_pilots111.dat"}, {"test_data/port_channel_estimator_test_output_ch_est111.dat"}}, // clang-format on }; diff --git a/tests/unittests/rlc/CMakeLists.txt b/tests/unittests/rlc/CMakeLists.txt index e0fc4d4b4c..bef656961d 100644 --- a/tests/unittests/rlc/CMakeLists.txt +++ b/tests/unittests/rlc/CMakeLists.txt @@ -74,3 +74,8 @@ add_executable(rlc_retx_queue_test rlc_retx_queue_test.cpp) target_link_libraries(rlc_retx_queue_test srsran_support srslog gtest gtest_main) target_include_directories(rlc_retx_queue_test PRIVATE ${CMAKE_SOURCE_DIR}) gtest_discover_tests(rlc_retx_queue_test) + +add_executable(rlc_metrics_aggregator_test rlc_metrics_aggregator_test.cpp) +target_link_libraries(rlc_metrics_aggregator_test srsran_rlc srsran_support srslog gtest gtest_main) +target_include_directories(rlc_metrics_aggregator_test PRIVATE ${CMAKE_SOURCE_DIR}) +gtest_discover_tests(rlc_metrics_aggregator_test) diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp new file mode 100644 index 0000000000..580d9ec3ee --- /dev/null +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -0,0 +1,173 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include "lib/rlc/rlc_metrics_aggregator.h" +#include "srsran/srslog/srslog.h" +#include "srsran/support/executors/manual_task_worker.h" +#include + +using namespace srsran; + +class mock_rlc_metrics_notifier : public rlc_metrics_notifier +{ + void report_metrics(const rlc_metrics& metrics) override { metrics_list.push_back(metrics); } + +public: + std::vector metrics_list; +}; + +/// Fixture class for RLC metrics aggregator tests +class rlc_metrics_aggregator_test : public ::testing::Test +{ +protected: + void SetUp() override + { + // init test's logger + srslog::init(); + logger.set_level(srslog::basic_levels::debug); + + // init RLC logger + srslog::fetch_basic_logger("RLC", false).set_level(srslog::basic_levels::debug); + srslog::fetch_basic_logger("RLC", false).set_hex_dump_max_size(100); + + // Create mock metrics notifier and RLC AM TX entity + metrics_notif = std::make_unique(); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, metrics_notif.get(), ue_worker); + } + + void TearDown() override + { + // flush logger after each test + srslog::flush(); + } + std::unique_ptr metrics_agg; + std::unique_ptr metrics_notif; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + + manual_task_worker ue_worker{128}; +}; + +TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) +{ + // Check if pushing two metrics causes the metrics to be pushed. + { + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; + rlc_rx_metrics rx_m; + + hi_m.num_sdus = 10; + low_m.num_pdus_no_segmentation = 10; + rx_m.num_sdus = 20; + + metrics_agg->push_tx_high_metrics(hi_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_low_metrics(low_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_rx_high_metrics(rx_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 1); + // TODO check report + } + + metrics_notif->metrics_list.clear(); + + // Same, but reversed order of pushing. + { + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; + rlc_rx_metrics rx_m; + + hi_m.num_sdus = 10; + hi_m.counter = 1; + low_m.num_pdus_no_segmentation = 10; + low_m.counter = 1; + rx_m.num_sdus = 20; + rx_m.counter = 1; + + metrics_agg->push_rx_high_metrics(rx_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_low_metrics(low_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_high_metrics(hi_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 1); + + // TODO check report + } +} + +TEST_F(rlc_metrics_aggregator_test, drop_one_report) +{ + // Check if pushing two metrics causes the metrics to be pushed. + { + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; + rlc_rx_metrics rx_m; + + hi_m.num_sdus = 10; + low_m.num_pdus_no_segmentation = 10; + rx_m.num_sdus = 20; + + metrics_agg->push_tx_high_metrics(hi_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_low_metrics(low_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + // don't push RX report + } + + metrics_notif->metrics_list.clear(); + + // Now push counter == 1 + { + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; + rlc_rx_metrics rx_m; + + hi_m.num_sdus = 10; + hi_m.counter = 1; + low_m.num_pdus_no_segmentation = 10; + low_m.counter = 1; + rx_m.num_sdus = 20; + rx_m.counter = 1; + + metrics_agg->push_rx_high_metrics(rx_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_low_metrics(low_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 0); + + metrics_agg->push_tx_high_metrics(hi_m); + ASSERT_EQ(metrics_notif->metrics_list.size(), 1); + + // TODO check report + } +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index 7666a1ae74..813da3a094 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -54,7 +54,8 @@ rlc_rx_am_config cfg_18bit_status_limit = {/*sn_field_length=*/rlc_am_sn_size::s /// Mocking class of the surrounding layers invoked by the RLC AM Rx entity. class rlc_rx_am_test_frame : public rlc_rx_upper_layer_data_notifier, public rlc_tx_am_status_handler, - public rlc_tx_am_status_notifier + public rlc_tx_am_status_notifier, + public rlc_metrics_notifier { public: std::queue sdu_queue; @@ -73,9 +74,11 @@ class rlc_rx_am_test_frame : public rlc_rx_upper_layer_data_notifier, } // rlc_tx_am_status_handler interface - virtual void on_status_pdu(rlc_am_status_pdu status_) override { this->status = std::move(status_); } + void on_status_pdu(rlc_am_status_pdu status_) override { this->status = std::move(status_); } // rlc_tx_am_status_notifier interface - virtual void on_status_report_changed() override { this->status_trigger_counter++; } + void on_status_report_changed() override { this->status_trigger_counter++; } + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; /// Fixture class for RLC AM Rx tests. @@ -98,16 +101,20 @@ class rlc_rx_am_test : public ::testing::Test, public ::testing::WithParamInterf // Create test frame tester = std::make_unique(config.sn_field_length); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Create RLC AM RX entity rlc = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, config, *tester, - timer_factory{timers, ue_worker}, - ue_worker, + *metrics_agg, true, - pcap); + pcap, + ue_worker, + timers); // Bind AM Tx/Rx interconnect rlc->set_status_handler(tester.get()); @@ -412,14 +419,15 @@ class rlc_rx_am_test : public ::testing::Test, public ::testing::WithParamInterf ue_worker.run_pending_tasks(); } - srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); - rlc_rx_am_config config = GetParam(); - rlc_am_sn_size sn_size = config.sn_field_length; - timer_manager timers; - manual_task_worker ue_worker{128}; - std::unique_ptr tester; - null_rlc_pcap pcap; - std::unique_ptr rlc; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + rlc_rx_am_config config = GetParam(); + rlc_am_sn_size sn_size = config.sn_field_length; + timer_manager timers; + manual_task_worker ue_worker{128}; + std::unique_ptr tester; + null_rlc_pcap pcap; + std::unique_ptr rlc; + std::unique_ptr metrics_agg; }; class rlc_rx_am_test_with_limit : public rlc_rx_am_test diff --git a/tests/unittests/rlc/rlc_rx_tm_test.cpp b/tests/unittests/rlc/rlc_rx_tm_test.cpp index 819122888c..aec7788e5a 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -23,13 +23,14 @@ #include "lib/rlc/rlc_rx_tm_entity.h" #include "tests/test_doubles/pdcp/pdcp_pdu_generator.h" #include "srsran/rlc/rlc_srb_config_factory.h" +#include "srsran/support/executors/manual_task_worker.h" #include #include using namespace srsran; /// Mocking class of the surrounding layers invoked by the RLC TM Rx entity. -class rlc_rx_tm_test_frame : public rlc_rx_upper_layer_data_notifier +class rlc_rx_tm_test_frame : public rlc_rx_upper_layer_data_notifier, public rlc_metrics_notifier { public: std::queue sdu_queue; @@ -41,6 +42,8 @@ class rlc_rx_tm_test_frame : public rlc_rx_upper_layer_data_notifier sdu_queue.push(std::move(sdu)); sdu_counter++; } + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; /// Fixture class for RLC TM Rx tests @@ -62,14 +65,20 @@ class rlc_rx_am_test : public ::testing::Test // Create test frame tester = std::make_unique(); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_executor); + // Create RLC AM TX entity rlc = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, make_default_srb0_rlc_config().tm.rx, *tester, + *metrics_agg, true, - pcap); + pcap, + ue_executor, + timers); } void TearDown() override @@ -78,10 +87,13 @@ class rlc_rx_am_test : public ::testing::Test srslog::flush(); } - srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); - std::unique_ptr tester; - null_rlc_pcap pcap; - std::unique_ptr rlc; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + timer_manager timers; + std::unique_ptr tester; + null_rlc_pcap pcap; + std::unique_ptr rlc; + std::unique_ptr metrics_agg; + manual_task_worker ue_executor{128}; }; TEST_F(rlc_rx_am_test, create_new_entity) diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index c13f90fe55..6ab68c7535 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -33,7 +33,8 @@ using namespace srsran; class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, public rlc_tx_upper_layer_control_notifier, public rlc_tx_lower_layer_notifier, - public rlc_rx_am_status_provider + public rlc_rx_am_status_provider, + public rlc_metrics_notifier { public: std::list highest_transmitted_pdcp_sn_list; @@ -90,6 +91,9 @@ class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, rlc_am_status_pdu& get_status_pdu() override { return status; } uint32_t get_status_pdu_length() override { return status.get_packed_size(); } bool status_report_required() override { return status_required; } + + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; /// Fixture class for RLC AM Tx tests @@ -122,6 +126,9 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf // Create test frame tester = std::make_unique(config.sn_field_length); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Create RLC AM TX entity rlc = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, @@ -130,11 +137,12 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + *metrics_agg, + true, + pcap, pcell_worker, ue_worker, - true, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc->set_status_provider(tester.get()); @@ -311,15 +319,16 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf pcell_worker.run_pending_tasks(); } - srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); - rlc_am_sn_size sn_size = GetParam(); - rlc_tx_am_config config; - timer_manager timers; - manual_task_worker ue_worker{128}; - manual_task_worker pcell_worker{128}; - std::unique_ptr tester; - null_rlc_pcap pcap; - std::unique_ptr rlc; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + rlc_am_sn_size sn_size = GetParam(); + rlc_tx_am_config config; + timer_manager timers; + manual_task_worker ue_worker{128}; + manual_task_worker pcell_worker{128}; + std::unique_ptr tester; + null_rlc_pcap pcap; + std::unique_ptr rlc; + std::unique_ptr metrics_agg; }; TEST_P(rlc_tx_am_test, create_new_entity) @@ -483,8 +492,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) pcell_worker.run_pending_tasks(); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, ++n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 0); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 0); // Try discard of invalid SDU rlc->discard_sdu(999); @@ -492,8 +501,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 1); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 1); // Try discard of already discarded SDU rlc->discard_sdu(0); @@ -501,8 +510,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 2); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 2); // Transmit full PDU std::vector pdu_buf; @@ -518,8 +527,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 2); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 2); // Try discard of already transmitted SDU rlc->discard_sdu(1); @@ -527,8 +536,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); // Transmit full PDU pdu_buf.resize(data_pdu_size); @@ -542,8 +551,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); // Discard remaining SDU rlc->discard_sdu(5); @@ -553,8 +562,8 @@ TEST_P(rlc_tx_am_test, sdu_discard) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, ++n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 4); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 4); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); } TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) @@ -596,8 +605,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) pcell_worker.run_pending_tasks(); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, ++n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 0); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 0); // Try discard of invalid SDU rlc->discard_sdu((pdcp_sn_start + 999) % pdcp_sn_mod); @@ -605,8 +614,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 1); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 1); // Try discard of already discarded SDU rlc->discard_sdu((pdcp_sn_start + 0) % pdcp_sn_mod); @@ -614,8 +623,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 2); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 2); // Transmit full PDU std::vector pdu_buf; @@ -631,8 +640,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 2); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 2); // Try discard of already transmitted SDU rlc->discard_sdu((pdcp_sn_start + 1) % pdcp_sn_mod); @@ -640,8 +649,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); // Transmit full PDU pdu_buf.resize(data_pdu_size); @@ -655,8 +664,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 3); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); // Discard remaining SDU rlc->discard_sdu((pdcp_sn_start + 5) % pdcp_sn_mod); @@ -666,8 +675,8 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester->bsr, expect_mac_bsr); EXPECT_EQ(tester->bsr_count, ++n_bsr); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 4); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 3); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 4); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 3); } TEST_P(rlc_tx_am_test, invalid_status_report_ack_sn_larger_than_tx_next) diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index c192dbf434..716f858020 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -33,7 +33,8 @@ using namespace srsran; /// Mocking class of the surrounding layers invoked by the RLC TM Tx entity. class rlc_tx_tm_test_frame : public rlc_tx_upper_layer_data_notifier, public rlc_tx_upper_layer_control_notifier, - public rlc_tx_lower_layer_notifier + public rlc_tx_lower_layer_notifier, + public rlc_metrics_notifier { public: std::queue sdu_queue; @@ -57,6 +58,9 @@ class rlc_tx_tm_test_frame : public rlc_tx_upper_layer_data_notifier, this->bsr = bsr_; this->bsr_count++; } + + // rlc_metrics_notifier + void report_metrics(const rlc_metrics& metrics) override {} }; /// Fixture class for RLC TM Tx tests @@ -78,6 +82,9 @@ class rlc_tx_tm_test : public ::testing::Test // Create test frame tester = std::make_unique(); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, tester.get(), ue_worker); + // Create RLC TM TX entity rlc = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, @@ -86,9 +93,12 @@ class rlc_tx_tm_test : public ::testing::Test *tester, *tester, *tester, - pcell_worker, + *metrics_agg, true, - pcap); + pcap, + pcell_worker, + ue_worker, + timers); } void TearDown() override @@ -97,11 +107,14 @@ class rlc_tx_tm_test : public ::testing::Test srslog::flush(); } - srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); - manual_task_worker pcell_worker{128}; - std::unique_ptr tester; - null_rlc_pcap pcap; - std::unique_ptr rlc; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + timer_manager timers; + manual_task_worker pcell_worker{128}; + manual_task_worker ue_worker{128}; + std::unique_ptr tester; + null_rlc_pcap pcap; + std::unique_ptr rlc; + std::unique_ptr metrics_agg; }; TEST_F(rlc_tx_tm_test, create_new_entity) @@ -227,8 +240,8 @@ TEST_F(rlc_tx_tm_test, discard_sdu_increments_discard_failure_counter) pcell_worker.run_pending_tasks(); EXPECT_EQ(tester->bsr, sdu_size); EXPECT_EQ(tester->bsr_count, 1); - EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 0); - EXPECT_EQ(rlc->get_metrics().num_discard_failures, 1); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discarded_sdus, 0); + EXPECT_EQ(rlc->get_metrics().tx_high.num_discard_failures, 1); // read PDU from lower end std::vector tx_pdu(sdu_size); @@ -267,8 +280,8 @@ TEST_F(rlc_tx_tm_test, test_tx_metrics) byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); rlc_tx_metrics m = rlc->get_metrics(); - ASSERT_EQ(m.mode, rlc_mode::tm); - ASSERT_EQ(m.mode_specific.tm.num_small_allocs, 1); + ASSERT_EQ(m.tx_low.mode, rlc_mode::tm); + ASSERT_EQ(m.tx_low.mode_specific.tm.num_small_allocs, 1); } int main(int argc, char** argv) diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 2f6f839548..9c02f7ad68 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -109,10 +109,10 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface tester1, tester1, tester1, - timers, + pcap1, pcell_worker, ue_worker, - pcap1); + timers); rlc2 = std::make_unique(gnb_du_id_t::min, du_ue_index_t::MIN_DU_UE_INDEX, srb_id_t::srb0, @@ -123,10 +123,10 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface tester2, tester2, tester2, - timers, + pcap2, pcell_worker, ue_worker, - pcap2); + timers); // Bind interfaces rlc1_rx_lower = rlc1->get_rx_lower_layer_interface(); @@ -524,24 +524,24 @@ TEST_P(rlc_um_test, sdu_discard) EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 0); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 0); // Try discard of invalid SDU rlc1_tx_upper->discard_sdu(999); pcell_worker.run_pending_tasks(); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 1); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 1); // Try discard of already discarded SDU rlc1_tx_upper->discard_sdu(0); pcell_worker.run_pending_tasks(); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 2); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 2); // Transmit full PDU std::vector tx_pdu(data_pdu_size); @@ -555,16 +555,16 @@ TEST_P(rlc_um_test, sdu_discard) pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 2); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 2); // Try discard of already transmitted SDU rlc1_tx_upper->discard_sdu(1); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); // Transmit full PDU tx_pdu.resize(data_pdu_size); @@ -577,8 +577,8 @@ TEST_P(rlc_um_test, sdu_discard) pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); // Discard remaining SDU rlc1_tx_upper->discard_sdu(5); @@ -588,8 +588,8 @@ TEST_P(rlc_um_test, sdu_discard) EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 2); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 4); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 4); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); } TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) @@ -626,24 +626,24 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 0); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 0); // Try discard of invalid SDU rlc1_tx_upper->discard_sdu((pdcp_sn_start + 999) % pdcp_sn_mod); pcell_worker.run_pending_tasks(); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 1); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 1); // Try discard of already discarded SDU rlc1_tx_upper->discard_sdu((pdcp_sn_start + 0) % pdcp_sn_mod); pcell_worker.run_pending_tasks(); EXPECT_EQ(tester1.bsr, expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 2); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 2); // Transmit full PDU std::vector tx_pdu(data_pdu_size); @@ -657,16 +657,16 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 2); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 2); // Try discard of already transmitted SDU rlc1_tx_upper->discard_sdu((pdcp_sn_start + 1) % pdcp_sn_mod); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); // Transmit full PDU nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); @@ -678,8 +678,8 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 1); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 3); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); // Discard remaining SDU rlc1_tx_upper->discard_sdu((pdcp_sn_start + 5) % pdcp_sn_mod); @@ -688,8 +688,8 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc1_tx_lower->get_buffer_state(), expect_buffer_state); EXPECT_EQ(tester1.bsr_count, 2); - EXPECT_EQ(rlc1->get_metrics().tx.num_discarded_sdus, 4); - EXPECT_EQ(rlc1->get_metrics().tx.num_discard_failures, 3); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discarded_sdus, 4); + EXPECT_EQ(rlc1->get_metrics().tx.tx_high.num_discard_failures, 3); } TEST_P(rlc_um_test, tx_with_segmentation_reverse_rx) diff --git a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp index f2df4f1e5b..a70dbb5199 100644 --- a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_harq_sr_csi_test.cpp @@ -730,37 +730,6 @@ TEST_F(test_pucch_allocator_ded_resources, test_harq_alloc_4bits_over_sr_and_csi ASSERT_FALSE(test_pucch_res_indicator.has_value()); } -TEST_F(test_pucch_allocator_ded_resources, when_converting_harq_f1_to_f2_during_mplexing_csi_preserve_res_indicator) -{ - // This makes PUCCH resource indicator 0 busy for PUCCH resource set 0. - add_ue_with_harq_grant(); - add_csi_grant(); - - // At the end of the PUCCH allocation with Format 2, we expect the same PUCCH as for PUCCH format 1. - std::optional test_pucch_res_indicator = t_bench.pucch_alloc.alloc_ded_pucch_harq_ack_ue( - t_bench.res_grid, t_bench.get_main_ue().crnti, t_bench.get_main_ue().get_pcell().cfg(), t_bench.k0, t_bench.k1); - - ASSERT_TRUE(test_pucch_res_indicator.has_value()); - // PUCCH resource indicator 0 is used by the first UE that got allocated. - ASSERT_EQ(1U, test_pucch_res_indicator.value()); -} - -TEST_F(test_pucch_allocator_ded_resources, when_converting_harq_f1_to_f2_during_mplexing_sr_csi_preserve_res_indicator) -{ - // This makes PUCCH resource indicator 0 busy for PUCCH resource set 0. - add_ue_with_harq_grant(); - add_sr_grant(); - add_csi_grant(); - - // At the end of the PUCCH allocation with Format 2, we expect the same PUCCH as for PUCCH format 1. - std::optional test_pucch_res_indicator = t_bench.pucch_alloc.alloc_ded_pucch_harq_ack_ue( - t_bench.res_grid, t_bench.get_main_ue().crnti, t_bench.get_main_ue().get_pcell().cfg(), t_bench.k0, t_bench.k1); - - ASSERT_TRUE(test_pucch_res_indicator.has_value()); - // PUCCH resource indicator 0 is used by the first UE that got allocated. - ASSERT_EQ(1U, test_pucch_res_indicator.value()); -} - /////// Test allocation of common + dedicated resources. /////// TEST_F(test_pucch_allocator_ded_resources, test_common_plus_ded_resource_without_existing_grants) diff --git a/tests/unittests/security/integrity_engine_test.cpp b/tests/unittests/security/integrity_engine_test.cpp index 15fdfc17f2..593f342915 100644 --- a/tests/unittests/security/integrity_engine_test.cpp +++ b/tests/unittests/security/integrity_engine_test.cpp @@ -21,6 +21,8 @@ */ #include "lib/security/integrity_engine_generic.h" +#include "lib/security/integrity_engine_nia2_cmac.h" +#include "lib/security/integrity_engine_nia2_non_cmac.h" #include "nia1_test_set.h" #include "nia2_test_set.h" #include "nia3_test_set.h" @@ -132,12 +134,68 @@ TEST_P(fxt_nia1, integrity_engine_generic_nia1) std::make_unique(key, param.bearer, dir, integrity_algorithm::nia1); // Apply integrity and compare results - security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); - ASSERT_TRUE(result.buf.has_value()); - logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); - logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); - EXPECT_EQ(result.buf.value(), prot_buf); - EXPECT_EQ(result.count, param.count_i); + for (unsigned i = 0; i < 2; i++) { + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); + ASSERT_TRUE(result.buf.has_value()); + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); + EXPECT_EQ(result.buf.value(), prot_buf); + EXPECT_EQ(result.count, param.count_i); + } +} + +#ifdef MBEDTLS_CMAC_C +TEST_P(fxt_nia2, integrity_engine_nia2_cmac) +{ + nia_test_set param = GetParam(); + + // Pack hex strings into srsran types + sec_128_key key = make_sec_128_key(param.ik_cstr); + auto dir = static_cast(param.direction); + byte_buffer message = make_byte_buffer(param.message_cstr).value(); + byte_buffer mact_buf = make_byte_buffer(param.mact_cstr).value(); + byte_buffer prot_buf = message.deep_copy().value(); + ASSERT_TRUE(prot_buf.append(mact_buf)); + + // Create integrity engine + std::unique_ptr nia = std::make_unique(key, param.bearer, dir); + + // Apply integrity and compare results + for (unsigned i = 0; i < 2; i++) { + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); + ASSERT_TRUE(result.buf.has_value()); + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); + EXPECT_EQ(result.buf.value(), prot_buf); + EXPECT_EQ(result.count, param.count_i); + } +} +#endif // MBEDTLS_CMAC_C + +TEST_P(fxt_nia2, integrity_engine_nia2_non_cmac) +{ + nia_test_set param = GetParam(); + + // Pack hex strings into srsran types + sec_128_key key = make_sec_128_key(param.ik_cstr); + auto dir = static_cast(param.direction); + byte_buffer message = make_byte_buffer(param.message_cstr).value(); + byte_buffer mact_buf = make_byte_buffer(param.mact_cstr).value(); + byte_buffer prot_buf = message.deep_copy().value(); + ASSERT_TRUE(prot_buf.append(mact_buf)); + + // Create integrity engine + std::unique_ptr nia = std::make_unique(key, param.bearer, dir); + + // Apply integrity and compare results + for (unsigned i = 0; i < 2; i++) { + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); + ASSERT_TRUE(result.buf.has_value()); + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); + EXPECT_EQ(result.buf.value(), prot_buf); + EXPECT_EQ(result.count, param.count_i); + } } TEST_P(fxt_nia2, integrity_engine_generic_nia2) @@ -157,12 +215,14 @@ TEST_P(fxt_nia2, integrity_engine_generic_nia2) std::make_unique(key, param.bearer, dir, integrity_algorithm::nia2); // Apply integrity and compare results - security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); - ASSERT_TRUE(result.buf.has_value()); - logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); - logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); - EXPECT_EQ(result.buf.value(), prot_buf); - EXPECT_EQ(result.count, param.count_i); + for (unsigned i = 0; i < 2; i++) { + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); + ASSERT_TRUE(result.buf.has_value()); + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); + EXPECT_EQ(result.buf.value(), prot_buf); + EXPECT_EQ(result.count, param.count_i); + } } TEST_P(fxt_nia3, integrity_engine_generic_nia3) @@ -182,12 +242,14 @@ TEST_P(fxt_nia3, integrity_engine_generic_nia3) std::make_unique(key, param.bearer, dir, integrity_algorithm::nia3); // Apply integrity and compare results - security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); - ASSERT_TRUE(result.buf.has_value()); - logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); - logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); - EXPECT_EQ(result.buf.value(), prot_buf); - EXPECT_EQ(result.count, param.count_i); + for (unsigned i = 0; i < 2; i++) { + security_result result = nia->protect_integrity(message.deep_copy().value(), param.count_i); + ASSERT_TRUE(result.buf.has_value()); + logger.info(result.buf.value().begin(), result.buf.value().end(), "result:"); + logger.info(prot_buf.begin(), prot_buf.end(), "exp:"); + EXPECT_EQ(result.buf.value(), prot_buf); + EXPECT_EQ(result.count, param.count_i); + } } //////////////////////////////////////////////////////////