From 631c75cc6367a57a1b41882f7eed45cf65e75637 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Fri, 19 Jul 2024 09:09:07 +0200 Subject: [PATCH 01/66] fapi: order the precoding matrices by number of layers but the identity matrix, that is the first one --- .../precoding_matrix_table_generator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/fapi_adaptor/precoding_matrix_table_generator.cpp b/lib/fapi_adaptor/precoding_matrix_table_generator.cpp index 9866623dc5..6514e1e919 100644 --- a/lib/fapi_adaptor/precoding_matrix_table_generator.cpp +++ b/lib/fapi_adaptor/precoding_matrix_table_generator.cpp @@ -137,15 +137,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); } @@ -225,7 +225,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); @@ -236,8 +238,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); } From ff2986feae720fb07ef041032d7bb174a996e3b3 Mon Sep 17 00:00:00 2001 From: asaezper Date: Tue, 23 Jul 2024 15:30:58 +0200 Subject: [PATCH 02/66] ci: increase custom artifacts time --- .gitlab/ci/build.yml | 1 + .gitlab/ci/e2e.yml | 1 + .gitlab/ci/trx.yml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) 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..c5907ca623 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -20,6 +20,7 @@ variables: - "zmq_single_ue" - "zmq_4x4_mimo" - "zmq_srsue" + - "zmq_cudu" - "rf_b200" - "rf_hp" - "android_b200" 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 From 50d4a3266230baff4bcd85a2a3d7ef5c697989ea Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Tue, 23 Jul 2024 14:11:21 +0200 Subject: [PATCH 03/66] Revert "sched: rename local variables in pucch allocator" This reverts commit 3ca7ce055349659c8247e25b81bcf07f9c786714. --- .../pucch_scheduling/pucch_allocator_impl.cpp | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index 05f0aa8fbf..dec9ec247d 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -1849,42 +1849,43 @@ 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); + slot_harq, crnti, r_harq_ptr->harq_id.pucch_res_ind, pucch_cfg); resource_manager.set_new_resource_allocation(crnti, pucch_resource_usage::HARQ_SET_1); if (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.harq_id.pucch_res_ind = r_harq_ptr->harq_id.pucch_res_ind; new_resource.set_res_config(*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)) { From 7be4c629f432ad41561bd4ca2060756dfb88ab38 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Tue, 23 Jul 2024 14:11:36 +0200 Subject: [PATCH 04/66] Revert "sched: fix multiplexing for harq_bits <= 2 and csi" This reverts commit 856a5335aecd3485d791be498c5338626c7b9a59. --- .../pucch_scheduling/pucch_allocator_impl.cpp | 29 ++++++++++++----- .../pucch_alloc_harq_sr_csi_test.cpp | 31 ------------------- 2 files changed, 21 insertions(+), 39 deletions(-) diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index dec9ec247d..a52a49120b 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -1811,9 +1811,10 @@ pucch_allocator_impl::merge_pucch_resources(spanformat != 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_ptr->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_ptr->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_ptr->bits.harq_ack_nof_bits; new_resource.bits.sr_bits = r_sr_ptr->bits.sr_bits; 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 1dd02f8d9e..f972f036fb 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 @@ -718,37 +718,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) From 89c90319588991f2d96f0d0bf527520cb10a3377 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Mon, 22 Jul 2024 14:57:52 +0200 Subject: [PATCH 05/66] cu_up: handle BearerContextReleaseCommand in UE-specific execution context --- include/srsran/cu_up/cu_up_manager.h | 2 +- include/srsran/e1ap/cu_up/e1ap_cu_up.h | 3 +- lib/cu_up/adapters/e1ap_adapters.h | 7 ++- lib/cu_up/cu_up_manager_impl.cpp | 11 +++- lib/cu_up/cu_up_manager_impl.h | 2 +- lib/cu_up/ue_manager.cpp | 32 +++++----- lib/cu_up/ue_manager.h | 10 +-- lib/cu_up/ue_manager_interfaces.h | 8 +-- lib/e1ap/cu_up/CMakeLists.txt | 4 +- lib/e1ap/cu_up/e1ap_cu_up_impl.cpp | 36 ++++------- .../bearer_context_release_procedure.cpp | 61 +++++++++++++++++++ .../bearer_context_release_procedure.h | 52 ++++++++++++++++ tests/unittests/cu_up/ue_manager_test.cpp | 8 ++- tests/unittests/e1ap/common/test_helpers.h | 7 ++- 14 files changed, 183 insertions(+), 60 deletions(-) create mode 100644 lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp create mode 100644 lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h diff --git a/include/srsran/cu_up/cu_up_manager.h b/include/srsran/cu_up/cu_up_manager.h index 264e21ac9a..51a987ce60 100644 --- a/include/srsran/cu_up/cu_up_manager.h +++ b/include/srsran/cu_up/cu_up_manager.h @@ -47,7 +47,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/e1ap/cu_up/e1ap_cu_up.h b/include/srsran/e1ap/cu_up/e1ap_cu_up.h index 4914f2f65e..4054e9b1bc 100644 --- a/include/srsran/e1ap/cu_up/e1ap_cu_up.h +++ b/include/srsran/e1ap/cu_up/e1ap_cu_up.h @@ -70,7 +70,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/lib/cu_up/adapters/e1ap_adapters.h b/lib/cu_up/adapters/e1ap_adapters.h index 22ccce7211..609d069b06 100644 --- a/lib/cu_up/adapters/e1ap_adapters.h +++ b/lib/cu_up/adapters/e1ap_adapters.h @@ -45,11 +45,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 e2f2c4a4c7..b6857a30d6 100644 --- a/lib/cu_up/cu_up_manager_impl.cpp +++ b/lib/cu_up/cu_up_manager_impl.cpp @@ -47,6 +47,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); } @@ -168,17 +169,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 b66e41a1f1..8db8c7e1c8 100644 --- a/lib/cu_up/cu_up_manager_impl.h +++ b/lib/cu_up/cu_up_manager_impl.h @@ -37,7 +37,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_manager.cpp b/lib/cu_up/ue_manager.cpp index 375010cb1a..b4444242ca 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -9,6 +9,7 @@ */ #include "ue_manager.h" +#include "srsran/support/async/execute_on.h" using namespace srsran; using namespace srs_cu_up; @@ -24,6 +25,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_), @@ -36,6 +38,7 @@ 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_), @@ -95,26 +98,23 @@ 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); - // TODO: remove lookup maps - - task_sched.schedule([this, ue_index](coro_context>& ctx) { - CORO_BEGIN(ctx); - - // Stop UE activity. - CORO_AWAIT(ue_db[ue_index]->stop()); - - // remove UE from database - ue_db.erase(ue_index); - - logger.info("ue={}: UE removed", ue_index); - - CORO_RETURN(); - }); + // 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_executor& ue_ctrl_executor = ue_ctxt->ue_exec_mapper->ctrl_executor(); + + // Dispatch the stopping and deletion of the UE context to UE-specific ctrl executor + return execute_and_continue_on_blocking( + ue_ctrl_executor, ctrl_executor, [this, ue_index, ue_ctxt = std::move(ue_ctxt)]() mutable { + ue_ctxt->stop(); + ue_ctxt.reset(); + logger.info("ue={}: UE removed", ue_index); + }); } ue_index_t ue_manager::get_next_ue_index() diff --git a/lib/cu_up/ue_manager.h b/lib/cu_up/ue_manager.h index d3ffc8da43..af63baaef8 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -35,16 +35,17 @@ 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>; 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); @@ -63,6 +64,7 @@ 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; diff --git a/lib/cu_up/ue_manager_interfaces.h b/lib/cu_up/ue_manager_interfaces.h index 9a0a1b9817..5a614c3104 100644 --- a/lib/cu_up/ue_manager_interfaces.h +++ b/lib/cu_up/ue_manager_interfaces.h @@ -22,10 +22,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/e1ap/cu_up/CMakeLists.txt b/lib/e1ap/cu_up/CMakeLists.txt index 30a640bf2b..f59a964645 100644 --- a/lib/e1ap/cu_up/CMakeLists.txt +++ b/lib/e1ap/cu_up/CMakeLists.txt @@ -12,6 +12,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 d37735d71e..62bd0a6f12 100644 --- a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp +++ b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp @@ -11,6 +11,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" @@ -256,38 +257,23 @@ 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); - - // Forward message to CU-UP - cu_up_notifier.on_bearer_context_release_command_received(bearer_context_release_cmd); - - // Remove UE context - 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); + cu_up_notifier.on_schedule_ue_async_task(ue_ctxt.ue_ids.ue_index, + launch_async( + ue_ctxt, msg, ue_ctxt_list, *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..83ce20f977 --- /dev/null +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp @@ -0,0 +1,61 @@ +/* + * + * Copyright 2021-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. + * + */ + +#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(const e1ap_ue_context& ue_ctxt_, + const asn1::e1ap::bearer_context_release_cmd_s& cmd_, + e1ap_ue_context_list& ue_ctxt_list_, + e1ap_message_notifier& pdu_notifier_, + e1ap_cu_up_manager_notifier& cu_up_notifier_, + srslog::basic_logger& logger_) : + ue_ctxt(ue_ctxt_), + cmd(cmd_), + ue_ctxt_list(ue_ctxt_list_), + 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_ctxt.ue_ids.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)); + + // Remove UE context + ue_ctxt_list.remove_ue(ue_ctxt.ue_ids.ue_index); + + 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..841f41052a --- /dev/null +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h @@ -0,0 +1,52 @@ +/* + * + * Copyright 2021-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. + * + */ + +#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(const e1ap_ue_context& ue_ctxt_, + const asn1::e1ap::bearer_context_release_cmd_s& cmd_, + e1ap_ue_context_list& ue_ctxt_list_, + 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: + const e1ap_ue_context ue_ctxt; + const asn1::e1ap::bearer_context_release_cmd_s cmd; + e1ap_ue_context_list& ue_ctxt_list; + 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/tests/unittests/cu_up/ue_manager_test.cpp b/tests/unittests/cu_up/ue_manager_test.cpp index 0cf1f95102..3afb16b8d9 100644 --- a/tests/unittests/cu_up/ue_manager_test.cpp +++ b/tests/unittests/cu_up/ue_manager_test.cpp @@ -11,6 +11,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 @@ -50,6 +51,7 @@ class ue_manager_test : public ::testing::Test *gtpu_n3_allocator, *gtpu_f1u_allocator, *cu_up_exec_mapper, + worker, gtpu_pcap, test_logger); } @@ -77,6 +79,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) @@ -113,7 +118,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 4f10502e80..237bc8c362 100644 --- a/tests/unittests/e1ap/common/test_helpers.h +++ b/tests/unittests/e1ap/common/test_helpers.h @@ -149,10 +149,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 From 9199fe5025f5050b7b3e980068ea383a28c7dcde Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Mon, 22 Jul 2024 15:27:19 +0200 Subject: [PATCH 06/66] cu_up: replace ue_db container type --- lib/cu_up/ue_manager.cpp | 6 +++--- lib/cu_up/ue_manager.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/cu_up/ue_manager.cpp b/lib/cu_up/ue_manager.cpp index b4444242ca..199d80e324 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -49,7 +49,7 @@ ue_manager::ue_manager(network_interface_config& net_config_, 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) @@ -101,7 +101,7 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) 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); // 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]); @@ -121,7 +121,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 af63baaef8..5499af02a5 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -11,11 +11,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 { @@ -39,7 +39,7 @@ class ue_manager : public ue_manager_ctrl dlt_pcap& gtpu_pcap_, srslog::basic_logger& logger_); - using ue_db_t = slotted_array, MAX_NOF_UES>; + using ue_db_t = std::unordered_map>; const ue_db_t& get_ues() const { return ue_db; } ue_context* add_ue(const ue_context_cfg& cfg) override; From 890964df89c39476a4a26fd1cbbe5684516d24e9 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 14:00:14 +0200 Subject: [PATCH 07/66] cu_up: ensure UE task scheduler outlives UE context upon removal... ...because the removal routine is run by that scheduler. The task scheduler is now stored in a separate container in ue_manager; only a reference is injected into the UE context. --- lib/cu_up/ue_context.h | 5 +++-- lib/cu_up/ue_manager.cpp | 5 +++++ lib/cu_up/ue_manager.h | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/cu_up/ue_context.h b/lib/cu_up/ue_context.h index 0ff60263ab..a2bc7bf923 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -44,6 +44,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_, @@ -53,7 +54,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_)), @@ -127,7 +128,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 199d80e324..be8418e017 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -44,6 +44,10 @@ ue_manager::ue_manager(network_interface_config& net_config_, logger(logger_), task_sched(MAX_NOF_UES) { + // 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) @@ -83,6 +87,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, diff --git a/lib/cu_up/ue_manager.h b/lib/cu_up/ue_manager.h index 5499af02a5..b8a9561893 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -39,7 +39,8 @@ class ue_manager : public ue_manager_ctrl dlt_pcap& gtpu_pcap_, srslog::basic_logger& logger_); - using ue_db_t = std::unordered_map>; + 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; @@ -68,6 +69,7 @@ class ue_manager : public ue_manager_ctrl 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; From e4af0edd20afc491fb9dadda59ba329d9dc61215 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 14:02:01 +0200 Subject: [PATCH 08/66] cu_up: remove unused task scheduler from ue_manager --- lib/cu_up/ue_manager.cpp | 3 +-- lib/cu_up/ue_manager.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/cu_up/ue_manager.cpp b/lib/cu_up/ue_manager.cpp index be8418e017..bab1f76d7f 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -41,8 +41,7 @@ ue_manager::ue_manager(network_interface_config& net_config_, 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) { diff --git a/lib/cu_up/ue_manager.h b/lib/cu_up/ue_manager.h index b8a9561893..92fe63a4a8 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -71,8 +71,6 @@ class ue_manager : public ue_manager_ctrl 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 From 4294f4a51795540785543aeee650841a5326f1c7 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 16:52:27 +0200 Subject: [PATCH 09/66] cu_up: remove_ue shall await the `stop` of UE context. --- lib/cu_up/ue_manager.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/cu_up/ue_manager.cpp b/lib/cu_up/ue_manager.cpp index bab1f76d7f..9298e6db85 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -110,15 +110,24 @@ async_task ue_manager::remove_ue(ue_index_t ue_index) // 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_executor& ue_ctrl_executor = ue_ctxt->ue_exec_mapper->ctrl_executor(); // Dispatch the stopping and deletion of the UE context to UE-specific ctrl executor - return execute_and_continue_on_blocking( - ue_ctrl_executor, ctrl_executor, [this, ue_index, ue_ctxt = std::move(ue_ctxt)]() mutable { - ue_ctxt->stop(); - ue_ctxt.reset(); - logger.info("ue={}: UE removed", ue_index); - }); + return launch_async([this, ue_ctxt = std::move(ue_ctxt), ue_index](coro_context>& ctx) mutable { + CORO_BEGIN(ctx); + + // 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(); + }); } ue_index_t ue_manager::get_next_ue_index() From 361df7dba59d7cdc38a452df0ad2ec8b3b7afc6a Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 17:07:51 +0200 Subject: [PATCH 10/66] cu_up: return non-empty async_task on failure of handle_bearer_context_modification_request --- lib/cu_up/cu_up_manager_impl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/cu_up/cu_up_manager_impl.cpp b/lib/cu_up/cu_up_manager_impl.cpp index b6857a30d6..e09eb61519 100644 --- a/lib/cu_up/cu_up_manager_impl.cpp +++ b/lib/cu_up/cu_up_manager_impl.cpp @@ -104,7 +104,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]() { From 387d154bc579ad43c668f7c7a709337b104fe22d Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 23 Jul 2024 14:47:47 +0200 Subject: [PATCH 11/66] cu-cp: use configurable timeout for f1ap ue context removal procedure --- apps/units/cu_cp/cu_cp_config_translators.cpp | 4 ++-- apps/units/cu_cp/cu_cp_unit_config.h | 4 ++-- apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp | 6 ++---- apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp | 2 +- include/srsran/f1ap/cu_cp/f1ap_configuration.h | 4 ++-- lib/f1ap/cu_cp/f1ap_cu_impl.cpp | 2 +- .../procedures/ue_context_release_procedure.cpp | 12 +++++++----- .../cu_cp/procedures/ue_context_release_procedure.h | 4 +++- .../cu_cp/procedures/ue_context_setup_procedure.cpp | 2 +- .../f1ap_cu_ue_context_setup_procedure_test.cpp | 2 +- 10 files changed, 22 insertions(+), 20 deletions(-) diff --git a/apps/units/cu_cp/cu_cp_config_translators.cpp b/apps/units/cu_cp/cu_cp_config_translators.cpp index 3912f718a6..234270a1c4 100644 --- a/apps/units/cu_cp/cu_cp_config_translators.cpp +++ b/apps/units/cu_cp/cu_cp_config_translators.cpp @@ -215,8 +215,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 90dcf5ff32..79b4e6e30d 100644 --- a/apps/units/cu_cp/cu_cp_unit_config.h +++ b/apps/units/cu_cp/cu_cp_unit_config.h @@ -96,8 +96,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 36d7638050..44d4f31701 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 @@ -220,10 +220,8 @@ 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") + add_option( + app, "--ue_context_setup_timeout", f1ap_params.procedure_timeout, "UE context setup timeout in milliseconds") ->capture_default_str(); } 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 8ba27c8884..dc284050b1 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 @@ -146,7 +146,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["ue_context_setup_timeout"] = config.procedure_timeout; return node; } diff --git a/include/srsran/f1ap/cu_cp/f1ap_configuration.h b/include/srsran/f1ap/cu_cp/f1ap_configuration.h index 3acd324304..2382288415 100644 --- a/include/srsran/f1ap/cu_cp/f1ap_configuration.h +++ b/include/srsran/f1ap/cu_cp/f1ap_configuration.h @@ -17,8 +17,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/lib/f1ap/cu_cp/f1ap_cu_impl.cpp b/lib/f1ap/cu_cp/f1ap_cu_impl.cpp index ec524fa385..ff75917c0d 100644 --- a/lib/f1ap/cu_cp/f1ap_cu_impl.cpp +++ b/lib/f1ap/cu_cp/f1ap_cu_impl.cpp @@ -108,7 +108,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 522d426973..a61c2b113a 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp +++ b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp @@ -18,12 +18,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); @@ -45,7 +47,7 @@ void ue_context_release_procedure::operator()(coro_context>& ctx); @@ -42,6 +43,7 @@ class ue_context_release_procedure 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 9e9b77e3aa..49fc4146d7 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp +++ b/lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.cpp @@ -71,7 +71,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/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 1f701a3ac8..0f4a87f35f 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 @@ -22,7 +22,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) { From d1bafb2c2afc5733d19614942c0ce0263449c809 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 23 Jul 2024 15:11:17 +0200 Subject: [PATCH 12/66] f1ap-cu: improve log message when the ue context release procedure times out --- .../ue_context_release_procedure.cpp | 27 ++++++++++--------- .../procedures/ue_context_release_procedure.h | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) 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 a61c2b113a..7b5a0846c8 100644 --- a/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp +++ b/lib/f1ap/cu_cp/procedures/ue_context_release_procedure.cpp @@ -58,8 +58,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 cc34d5bd6a..a279ed55ca 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,7 @@ 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; From 58be34ad2619f88dd6dc17ce90ec275158a08ea4 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 23 Jul 2024 15:13:43 +0200 Subject: [PATCH 13/66] f1ap-cu: rename cli11 parameter --- apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp | 6 ++++-- apps/units/cu_cp/cu_cp_unit_config_yaml_writer.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) 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 44d4f31701..e62333203d 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 @@ -220,8 +220,10 @@ 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.procedure_timeout, "UE context setup timeout in milliseconds") + add_option(app, + "--procedure_timeout", + f1ap_params.procedure_timeout, + "Time that the F1AP waits for a DU response in milliseconds") ->capture_default_str(); } 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 dc284050b1..921b5bb3cd 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 @@ -146,7 +146,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.procedure_timeout; + node["procedure_timeout"] = config.procedure_timeout; return node; } From 3e49cc213919fe5b6f3145a8716b4156a0e81619 Mon Sep 17 00:00:00 2001 From: asaezper Date: Wed, 24 Jul 2024 15:36:07 +0200 Subject: [PATCH 14/66] ci: update retina to use new cu/du timeouts --- .gitlab/ci/e2e/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index bd3844c8c6..20ce24afd0 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.12 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 From 4d72b7ef136e8795e9591bd421c63f9d4d7626e5 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Wed, 24 Jul 2024 11:18:58 +0200 Subject: [PATCH 15/66] phy: update test vectors Two test vectors needed to be updated to match the new convention of writing scalar booleans as true/false instead of 1/0. --- .../pucch_processor_format0_test_data.h | 182 +++++++------- .../pucch_processor_format0_test_data.tar.gz | 4 +- .../port_channel_estimator_test_data.h | 226 +++++++++--------- .../port_channel_estimator_test_data.tar.gz | 4 +- 4 files changed, 208 insertions(+), 208 deletions(-) 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 de9002611f..1edb87b2e3 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 @@ -10,7 +10,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" @@ -32,96 +32,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/channel_processors/pucch_processor_format0_test_data.tar.gz b/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.tar.gz index a0c265d04e..0a32075717 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.tar.gz +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_format0_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:686f3596482e434475dded0e699b9b54dde80344fe494f5ff85d2fc7b7f02428 -size 26815 +oid sha256:e3fab6b1027f1a1a3d28465ac21d42e7f87ddb460bd74ea3fb2d8f9a99a34617 +size 26876 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 e694529ecd..b0c81d6835 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 @@ -10,7 +10,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" @@ -41,118 +41,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/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz index a9cad6121e..6ea554dccf 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:097fd2ccacf78fb766a8d9fd95465a7bea4e452ca7527b161ab56b3e5f024d32 -size 1620998 +oid sha256:4105e0c556064912dd8691f36786e30d14fb29ce3b7569598a1ca9efc3f0d0df +size 1621077 From 2838922549cf18805b37673a137ac75868705051 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 16 Jul 2024 14:15:18 +0100 Subject: [PATCH 16/66] rlc: starting to remove atomics from RLC metrics --- lib/rlc/rlc_metrics_aggregator.cpp | 0 lib/rlc/rlc_metrics_aggregator.h | 29 +++++++++++ .../rlc/rlc_metrics_aggregator_test.cpp | 49 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 lib/rlc/rlc_metrics_aggregator.cpp create mode 100644 lib/rlc/rlc_metrics_aggregator.h create mode 100644 tests/unittests/rlc/rlc_metrics_aggregator_test.cpp diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h new file mode 100644 index 0000000000..8a9cbb2957 --- /dev/null +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -0,0 +1,29 @@ +/* + * + * Copyright 2021-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. + * + */ + +#pragma once + +#include "rlc_tx_metrics_container.h" + +namespace srsran { +class rlc_metrics_aggregator +{ +public: + // \breif push metrics from the lower RLC executor to the agregator + // This will be called will transfer the execution by pushing a copy to + // ue executor + void push_low_metric(rlc_tx_metrics_atomic_lower m_lower); + // \breif push metrics from the high RLC executors to the agregator + // As these are called from the UE executor no execution transfer is required. + void push_high_metrics(rlc_tx_metrics_atomic_higher m_higher); + + void handle_new_metrics_push(); +}; +} // namespace srsran 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..cf9e04afe6 --- /dev/null +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -0,0 +1,49 @@ +/* + * + * Copyright 2021-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. + * + */ +#include "lib/rlc/rlc_metrics_aggregator.h" +#include "srsran/srslog/srslog.h" +#include + +using namespace srsran; + +/// 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 RLC AM TX entity + metrics_agg = std::make_unique(); + } + + void TearDown() override + { + // flush logger after each test + srslog::flush(); + } + std::unique_ptr metrics_agg; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); +}; + +TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) {} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From c23247356b205e5675789945f4ea34f0f558e675 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jul 2024 15:00:02 +0100 Subject: [PATCH 17/66] rlc: remove atomics from rlc tx metrics --- lib/rlc/rlc_tx_metrics_container.h | 175 +++++++++--------- .../rlc/rlc_metrics_aggregator_test.cpp | 9 +- 2 files changed, 93 insertions(+), 91 deletions(-) diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index a9fd8e8af9..f1d5a159ce 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -14,69 +14,69 @@ 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)> +struct rlc_tx_metrics_higher { + 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_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); + num_sdus = {}; + num_of_pulled_sdus = {}; + num_sdu_bytes = {}; + num_dropped_sdus = {}; + num_discarded_sdus = {}; + num_discard_failures = {}; + sum_sdu_latency_us = {}; } }; struct rlc_tm_tx_metrics_atomic_lower { - std::atomic num_small_allocs; ///< Number of allocations that are too small to TX PDU + uint32_t num_small_allocs; ///< Number of allocations that are too small to TX PDU - void reset() { num_small_allocs.store(0, std::memory_order_relaxed); } + void reset() { num_small_allocs = {}; } }; 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 + 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.store(0, std::memory_order_relaxed); - num_pdu_bytes_with_segmentation.store(0, std::memory_order_relaxed); + num_pdus_with_segmentation = {}; + num_pdu_bytes_with_segmentation = {}; } }; 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 + 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 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 void reset() { - 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); + num_pdus_with_segmentation = {}; + num_pdu_bytes_with_segmentation = {}; + num_retx_pdus = {}; + num_retx_pdu_bytes = {}; + num_ctrl_pdus = {}; + num_ctrl_pdu_bytes = {}; } }; 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 + 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 /// RLC mode of the entity - std::atomic mode; + rlc_mode mode; /// Mode-specific metrics /// @@ -90,11 +90,11 @@ struct rlc_tx_metrics_atomic_lower { void reset() { - num_pdus_no_segmentation.store(0, std::memory_order_relaxed); - num_pdu_bytes_no_segmentation.store(0, std::memory_order_relaxed); + num_pdus_no_segmentation = {}; + num_pdu_bytes_no_segmentation = {}; // reset mode-specific values - switch (mode.load(std::memory_order_relaxed)) { + switch (mode) { case rlc_mode::tm: mode_specific.tm.reset(); break; @@ -114,9 +114,9 @@ struct rlc_tx_metrics_atomic_lower { class rlc_tx_metrics_container { - rlc_tx_metrics_atomic_higher metrics_hi = {}; - rlc_tx_metrics_atomic_lower metrics_lo = {}; - bool enabled = false; + rlc_tx_metrics_higher metrics_hi = {}; + rlc_tx_metrics_atomic_lower metrics_lo = {}; + bool enabled = false; public: rlc_tx_metrics_container(bool enabled_) : enabled(enabled_) {} @@ -126,7 +126,7 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_lo.mode.store(mode, std::memory_order_relaxed); + metrics_lo.mode = mode; } void metrics_add_sdus(uint32_t num_sdus, size_t num_sdu_bytes) @@ -134,8 +134,8 @@ class rlc_tx_metrics_container if (not enabled) { 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); + metrics_hi.num_sdus += num_sdus; + metrics_hi.num_sdu_bytes += num_sdu_bytes; } void metrics_add_pulled_sdus(uint32_t num_sdus) @@ -143,7 +143,7 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_hi.num_of_pulled_sdus.fetch_add(num_sdus, std::memory_order_relaxed); + metrics_hi.num_of_pulled_sdus += num_sdus; } void metrics_add_lost_sdus(uint32_t num_sdus) @@ -151,7 +151,7 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_hi.num_dropped_sdus.fetch_add(num_sdus, std::memory_order_relaxed); + metrics_hi.num_dropped_sdus += num_sdus; } void metrics_add_discard(uint32_t num_discarded_sdus) @@ -159,7 +159,7 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_hi.num_discarded_sdus.fetch_add(num_discarded_sdus, std::memory_order_relaxed); + metrics_hi.num_discarded_sdus += num_discarded_sdus; } void metrics_add_discard_failure(uint32_t num_discard_failures) @@ -167,7 +167,7 @@ class rlc_tx_metrics_container if (not enabled) { return; } - metrics_hi.num_discard_failures.fetch_add(num_discard_failures, std::memory_order_relaxed); + metrics_hi.num_discard_failures += num_discard_failures; } void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) @@ -175,15 +175,15 @@ class rlc_tx_metrics_container 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_pdus_no_segmentation += num_pdus; + metrics_lo.num_pdu_bytes_no_segmentation += num_pdu_bytes; } 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_hi.sum_sdu_latency_us += sdu_latency; } // TM specific metrics @@ -192,8 +192,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 @@ -202,10 +202,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 @@ -214,9 +214,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) @@ -224,9 +224,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) @@ -234,9 +234,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_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 @@ -249,41 +249,36 @@ class rlc_tx_metrics_container rlc_tx_metrics 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); + ret.num_sdus = metrics_hi.num_sdus; + ret.num_of_pulled_sdus = metrics_hi.num_of_pulled_sdus; + ret.num_sdu_bytes = metrics_hi.num_sdu_bytes; + ret.num_dropped_sdus = metrics_hi.num_dropped_sdus; + ret.num_discarded_sdus = metrics_hi.num_discarded_sdus; + ret.num_discard_failures = metrics_hi.num_discard_failures; + ret.sum_sdu_latency_us = metrics_hi.sum_sdu_latency_us; // 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); + ret.num_pdus_no_segmentation = metrics_lo.num_pdus_no_segmentation; + ret.num_pdu_bytes_no_segmentation = metrics_lo.num_pdu_bytes_no_segmentation; + ret.mode = metrics_lo.mode; 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); + ret.mode_specific.tm.num_small_allocs = metrics_lo.mode_specific.tm.num_small_allocs; 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_pdus_with_segmentation = metrics_lo.mode_specific.um.num_pdus_with_segmentation; ret.mode_specific.um.num_pdu_bytes_with_segmentation = - metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation.load(std::memory_order_relaxed); + metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation; 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_pdus_with_segmentation = metrics_lo.mode_specific.am.num_pdus_with_segmentation; 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); + metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation; + ret.mode_specific.am.num_retx_pdus = metrics_lo.mode_specific.am.num_retx_pdus; + ret.mode_specific.am.num_retx_pdu_bytes = metrics_lo.mode_specific.am.num_retx_pdu_bytes; + ret.mode_specific.am.num_ctrl_pdus = metrics_lo.mode_specific.am.num_ctrl_pdus; + ret.mode_specific.am.num_ctrl_pdu_bytes = metrics_lo.mode_specific.am.num_ctrl_pdu_bytes; break; default: // nothing to do here diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index cf9e04afe6..0cc9e4318b 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -40,7 +40,14 @@ class rlc_metrics_aggregator_test : public ::testing::Test srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); }; -TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) {} +TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) +{ + rlc_tx_metrics_atomic_higher hi_m; + rlc_tx_metrics_atomic_lower low_m; + + hi_m.num_sdus = 10; + low_m.num_pdus_no_segmentation = 10; +} int main(int argc, char** argv) { From 7962d13b0178d945398d1ea0a9f1093f1ffbc5db Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 17 Jul 2024 15:28:13 +0100 Subject: [PATCH 18/66] rlc: splitting high metrics and low metrics --- lib/rlc/CMakeLists.txt | 1 + lib/rlc/rlc_metrics_aggregator.cpp | 21 +++ lib/rlc/rlc_metrics_aggregator.h | 10 +- lib/rlc/rlc_tx_am_entity.cpp | 28 ++-- lib/rlc/rlc_tx_entity.h | 17 +- lib/rlc/rlc_tx_metrics_container.h | 156 ++++++++++-------- lib/rlc/rlc_tx_tm_entity.cpp | 12 +- lib/rlc/rlc_tx_um_entity.cpp | 18 +- tests/unittests/rlc/CMakeLists.txt | 5 + .../rlc/rlc_metrics_aggregator_test.cpp | 21 ++- 10 files changed, 180 insertions(+), 109 deletions(-) diff --git a/lib/rlc/CMakeLists.txt b/lib/rlc/CMakeLists.txt index a1b5b125bf..d3e759126a 100644 --- a/lib/rlc/CMakeLists.txt +++ b/lib/rlc/CMakeLists.txt @@ -15,6 +15,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_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index e69de29bb2..8a8079b478 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -0,0 +1,21 @@ +/* + * + * Copyright 2021-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. + * + */ +#include "rlc_metrics_aggregator.h" + +using namespace srsran; + +rlc_metrics_aggregator::rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_) : + rlc_metrics_notif(rlc_metrics_notif_) +{ +} + +void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower) {} + +void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher) {} diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 8a9cbb2957..9483216e46 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -11,19 +11,23 @@ #pragma once #include "rlc_tx_metrics_container.h" +#include "srsran/rlc/rlc_metrics.h" namespace srsran { class rlc_metrics_aggregator { public: + rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_); + // \breif push metrics from the lower RLC executor to the agregator // This will be called will transfer the execution by pushing a copy to // ue executor - void push_low_metric(rlc_tx_metrics_atomic_lower m_lower); + void push_tx_low_metrics(rlc_tx_metrics_lower m_lower); // \breif push metrics from the high RLC executors to the agregator // As these are called from the UE executor no execution transfer is required. - void push_high_metrics(rlc_tx_metrics_atomic_higher m_higher); + void push_tx_high_metrics(rlc_tx_metrics_higher m_higher); - void handle_new_metrics_push(); +private: + rlc_metrics_notifier* rlc_metrics_notif; }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index ca3a2c5cfd..a672a8fae5 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -47,7 +47,7 @@ rlc_tx_am_entity::rlc_tx_am_entity(gnb_du_id_t gnb_du_i 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, @@ -94,7 +94,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={} {}", @@ -102,7 +102,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); } } @@ -111,11 +111,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); } } @@ -151,7 +151,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); @@ -268,12 +268,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_high.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_high.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); @@ -337,7 +337,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); @@ -430,13 +430,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_high.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_high.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); @@ -572,7 +572,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_entity.h b/lib/rlc/rlc_tx_entity.h index 7e80ce1879..b640203a9d 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -35,7 +35,8 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, bool metrics_enabled, rlc_pcap& pcap_) : 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_), @@ -45,7 +46,8 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, } 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; @@ -63,8 +65,15 @@ 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() + { + return {}; + /*return metrics.get_metrics();*/ + } + void reset_metrics() + { + // return metrics.reset_metrics(); + } }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index f1d5a159ce..df750c0157 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -23,6 +23,16 @@ struct rlc_tx_metrics_higher { 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)> + 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 = {}; @@ -32,16 +42,17 @@ struct rlc_tx_metrics_higher { num_discarded_sdus = {}; num_discard_failures = {}; sum_sdu_latency_us = {}; + // do not reset counter } }; -struct rlc_tm_tx_metrics_atomic_lower { +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_atomic_lower { +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 @@ -52,7 +63,7 @@ struct rlc_um_tx_metrics_atomic_lower { } }; -struct rlc_am_tx_metrics_atomic_lower { +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 retransmitted PDUs @@ -71,7 +82,7 @@ struct rlc_am_tx_metrics_atomic_lower { } }; -struct rlc_tx_metrics_atomic_lower { +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 @@ -83,11 +94,20 @@ struct rlc_tx_metrics_atomic_lower { /// 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; + 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 = {}; @@ -112,22 +132,13 @@ struct rlc_tx_metrics_atomic_lower { } }; -class rlc_tx_metrics_container +class rlc_tx_metrics_high_container { - rlc_tx_metrics_higher metrics_hi = {}; - rlc_tx_metrics_atomic_lower metrics_lo = {}; - bool enabled = false; + rlc_tx_metrics_higher metrics_hi = {}; + bool enabled = false; public: - rlc_tx_metrics_container(bool enabled_) : enabled(enabled_) {} - - void metrics_set_mode(rlc_mode mode) - { - if (not enabled) { - return; - } - metrics_lo.mode = mode; - } + rlc_tx_metrics_high_container(bool enabled_) : enabled(enabled_) {} void metrics_add_sdus(uint32_t num_sdus, size_t num_sdu_bytes) { @@ -170,20 +181,68 @@ class rlc_tx_metrics_container metrics_hi.num_discard_failures += num_discard_failures; } - void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) + void metrics_add_sdu_latency_us(uint32_t sdu_latency) { if (not enabled) { return; } - metrics_lo.num_pdus_no_segmentation += num_pdus; - metrics_lo.num_pdu_bytes_no_segmentation += num_pdu_bytes; + metrics_hi.sum_sdu_latency_us += sdu_latency; } - void metrics_add_sdu_latency_us(uint32_t sdu_latency) + + // 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.get(); + } + + void reset_metrics() + { + srsran_assert(enabled, "Trying to reset metrics, but metrics are disabled."); if (not enabled) { return; } - metrics_hi.sum_sdu_latency_us += sdu_latency; + metrics_hi.reset(); // do not reset the counter + } + + rlc_tx_metrics_higher get_and_reset_metrics() + { + srsran_assert(enabled, "Trying to get metrics, but metrics are disabled."); + if (not enabled) { + return {false}; + } + rlc_tx_metrics_higher ret = get_hi_metrics(); + reset_metrics(); + return ret; + } +}; + +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_lo.mode = mode; + } + + void metrics_add_pdus_no_segmentation(uint32_t num_pdus, size_t num_pdu_bytes) + { + if (not enabled) { + return; + } + metrics_lo.num_pdus_no_segmentation += num_pdus; + metrics_lo.num_pdu_bytes_no_segmentation += num_pdu_bytes; } // TM specific metrics @@ -240,52 +299,16 @@ class rlc_tx_metrics_container } // 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; - ret.num_of_pulled_sdus = metrics_hi.num_of_pulled_sdus; - ret.num_sdu_bytes = metrics_hi.num_sdu_bytes; - ret.num_dropped_sdus = metrics_hi.num_dropped_sdus; - ret.num_discarded_sdus = metrics_hi.num_discarded_sdus; - ret.num_discard_failures = metrics_hi.num_discard_failures; - ret.sum_sdu_latency_us = metrics_hi.sum_sdu_latency_us; - - // Metrics accessed from lower layer - ret.num_pdus_no_segmentation = metrics_lo.num_pdus_no_segmentation; - ret.num_pdu_bytes_no_segmentation = metrics_lo.num_pdu_bytes_no_segmentation; - ret.mode = metrics_lo.mode; - switch (ret.mode) { - case rlc_mode::tm: - ret.mode_specific.tm.num_small_allocs = metrics_lo.mode_specific.tm.num_small_allocs; - 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; - ret.mode_specific.um.num_pdu_bytes_with_segmentation = - metrics_lo.mode_specific.um.num_pdu_bytes_with_segmentation; - break; - case rlc_mode::am: - ret.mode_specific.am.num_pdus_with_segmentation = metrics_lo.mode_specific.am.num_pdus_with_segmentation; - ret.mode_specific.am.num_pdu_bytes_with_segmentation = - metrics_lo.mode_specific.am.num_pdu_bytes_with_segmentation; - ret.mode_specific.am.num_retx_pdus = metrics_lo.mode_specific.am.num_retx_pdus; - ret.mode_specific.am.num_retx_pdu_bytes = metrics_lo.mode_specific.am.num_retx_pdu_bytes; - ret.mode_specific.am.num_ctrl_pdus = metrics_lo.mode_specific.am.num_ctrl_pdus; - ret.mode_specific.am.num_ctrl_pdu_bytes = metrics_lo.mode_specific.am.num_ctrl_pdu_bytes; - break; - default: - // nothing to do here - break; - } - - return ret; + return metrics_lo.get(); } void reset_metrics() @@ -294,17 +317,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 978d97edd9..746d5fe88b 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -28,7 +28,7 @@ rlc_tx_tm_entity::rlc_tx_tm_entity(gnb_du_id_t du_id, 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); } @@ -47,11 +47,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); } } @@ -59,7 +59,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 @@ -81,7 +81,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; } @@ -102,7 +102,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_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index aa267fc6da..c7137faec3 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -35,7 +35,7 @@ rlc_tx_um_entity::rlc_tx_um_entity(gnb_du_id_t du_id, 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, @@ -70,11 +70,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); } } @@ -83,11 +83,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); } } @@ -174,8 +174,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_high.metrics_add_sdu_latency_us(latency.count() / 1000); + metrics_high.metrics_add_pulled_sdus(1); } else { // advance SO offset next_so += payload_len; @@ -188,9 +188,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/tests/unittests/rlc/CMakeLists.txt b/tests/unittests/rlc/CMakeLists.txt index 2fefcbd285..7023f5a014 100644 --- a/tests/unittests/rlc/CMakeLists.txt +++ b/tests/unittests/rlc/CMakeLists.txt @@ -62,3 +62,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 index 0cc9e4318b..e3bc3b97c2 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -13,6 +13,10 @@ using namespace srsran; +class mock_rlc_metrics_notifier : public rlc_metrics_notifier +{ + void report_metrics(const rlc_metrics& metrics) override {} +}; /// Fixture class for RLC metrics aggregator tests class rlc_metrics_aggregator_test : public ::testing::Test { @@ -27,8 +31,9 @@ class rlc_metrics_aggregator_test : public ::testing::Test 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 RLC AM TX entity - metrics_agg = std::make_unique(); + // Create mock metrics notifier and RLC AM TX entity + metrics_notif = std::make_unique(); + metrics_agg = std::make_unique(metrics_notif.get()); } void TearDown() override @@ -36,17 +41,21 @@ class rlc_metrics_aggregator_test : public ::testing::Test // flush logger after each test srslog::flush(); } - std::unique_ptr metrics_agg; - srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + std::unique_ptr metrics_agg; + std::unique_ptr metrics_notif; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); }; TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) { - rlc_tx_metrics_atomic_higher hi_m; - rlc_tx_metrics_atomic_lower low_m; + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; hi_m.num_sdus = 10; low_m.num_pdus_no_segmentation = 10; + + metrics_agg->push_tx_high_metrics(hi_m); + metrics_agg->push_tx_low_metrics(low_m); } int main(int argc, char** argv) From b05adb1ac0637293809ec077452601b6d171816c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jul 2024 16:19:51 +0100 Subject: [PATCH 19/66] rlc: start to push metrics from aggregator --- lib/rlc/rlc_metrics_aggregator.cpp | 20 +++++++- lib/rlc/rlc_metrics_aggregator.h | 7 ++- lib/rlc/rlc_rx_metrics_container.h | 1 - .../rlc/rlc_metrics_aggregator_test.cpp | 47 ++++++++++++++++--- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index 8a8079b478..5f2168abb4 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -14,8 +14,24 @@ using namespace srsran; rlc_metrics_aggregator::rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_) : rlc_metrics_notif(rlc_metrics_notif_) { + m_lower.counter = UINT32_MAX; + m_higher.counter = UINT32_MAX; } -void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower) {} +void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) +{ + m_lower = m_lower_; + if (m_lower.counter == m_higher.counter) { + rlc_metrics report = {}; + rlc_metrics_notif->report_metrics(report); + } +} -void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher) {} +void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) +{ + m_higher = m_higher_; + if (m_lower.counter == m_higher.counter) { + rlc_metrics report = {}; + rlc_metrics_notif->report_metrics(report); + } +} diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 9483216e46..27fd9f6d1a 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -22,12 +22,15 @@ class rlc_metrics_aggregator // \breif push metrics from the lower RLC executor to the agregator // 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); + void push_tx_low_metrics(rlc_tx_metrics_lower m_lower_); // \breif push metrics from the high RLC executors to the agregator // As these are called from the UE executor no execution transfer is required. - void push_tx_high_metrics(rlc_tx_metrics_higher m_higher); + void push_tx_high_metrics(rlc_tx_metrics_higher m_higher_); private: rlc_metrics_notifier* rlc_metrics_notif; + + rlc_tx_metrics_lower m_lower; + rlc_tx_metrics_higher m_higher; }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index d356e24a8f..3d88947610 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -11,7 +11,6 @@ #pragma once #include "srsran/rlc/rlc_rx_metrics.h" -#include "srsran/srslog/srslog.h" #include namespace srsran { diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index e3bc3b97c2..c7b409748d 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -15,8 +15,12 @@ using namespace srsran; class mock_rlc_metrics_notifier : public rlc_metrics_notifier { - void report_metrics(const rlc_metrics& metrics) override {} + 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 { @@ -48,14 +52,43 @@ class rlc_metrics_aggregator_test : public ::testing::Test TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) { - rlc_tx_metrics_higher hi_m; - rlc_tx_metrics_lower low_m; + // Check if pushing two metrics causes the metrics to be pushed. + { + rlc_tx_metrics_higher hi_m; + rlc_tx_metrics_lower low_m; + + hi_m.num_sdus = 10; + low_m.num_pdus_no_segmentation = 10; + + 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(), 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; - hi_m.num_sdus = 10; - low_m.num_pdus_no_segmentation = 10; + hi_m.num_sdus = 10; + hi_m.counter = 1; + low_m.num_pdus_no_segmentation = 10; + low_m.counter = 1; - metrics_agg->push_tx_high_metrics(hi_m); - metrics_agg->push_tx_low_metrics(low_m); + 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) From e40faef61832c8b5948d4959486d18ed90357e82 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jul 2024 17:56:34 +0100 Subject: [PATCH 20/66] rlc: pass timer_manager to rlc entities We pass the timer manager instead of the timer factory class to the RLC entities, so that it is clearer which executor a particular timer is running on and also to make it easier to start metrics timers on both the pcell executor and the ue executor. --- lib/rlc/rlc_am_entity.h | 10 +++++----- lib/rlc/rlc_factory.cpp | 12 +++++------ lib/rlc/rlc_tm_entity.h | 10 ++++++---- lib/rlc/rlc_tx_am_entity.cpp | 20 ++++++++++++++----- lib/rlc/rlc_tx_am_entity.h | 6 +++--- lib/rlc/rlc_tx_entity.h | 15 ++++++++++++-- lib/rlc/rlc_tx_tm_entity.cpp | 19 ++++++++++++++---- lib/rlc/rlc_tx_tm_entity.h | 12 +++++------ lib/rlc/rlc_tx_um_entity.cpp | 19 ++++++++++++++---- lib/rlc/rlc_tx_um_entity.h | 12 +++++------ lib/rlc/rlc_um_entity.h | 10 ++++++---- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 6 +++--- .../rlc/rlc_handle_status_report.cpp | 6 +++--- tests/unittests/rlc/rlc_tx_am_test.cpp | 6 +++--- tests/unittests/rlc/rlc_tx_tm_test.cpp | 8 ++++++-- tests/unittests/rlc/rlc_um_test.cpp | 8 ++++---- 16 files changed, 115 insertions(+), 64 deletions(-) diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index a477ed0e76..3f75405493 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -29,10 +29,10 @@ 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) : + timer_manager& timers) : rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, @@ -48,11 +48,11 @@ class rlc_am_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - timer_factory{timers, pcell_executor}, + 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_, diff --git a/lib/rlc/rlc_factory.cpp b/lib/rlc/rlc_factory.cpp index f137efc759..eb33053941 100644 --- a/lib/rlc/rlc_factory.cpp +++ b/lib/rlc/rlc_factory.cpp @@ -29,10 +29,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: @@ -46,10 +46,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, @@ -61,10 +61,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_tm_entity.h b/lib/rlc/rlc_tm_entity.h index 03ac77ce1a..45cdd616c4 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -29,10 +29,10 @@ 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) : + timer_manager& timers) : rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, @@ -47,9 +47,11 @@ class rlc_tm_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - pcell_executor, 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, metrics_period.count() != 0, pcap); } diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index a672a8fae5..f2ed640d50 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -26,12 +26,22 @@ 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, + 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_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))), @@ -41,7 +51,7 @@ 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_), diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index 928666ad10..d1222a03a8 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -133,11 +133,11 @@ 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, + 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 { diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index b640203a9d..fa3afb086f 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -33,7 +33,10 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_tx_upper_layer_control_notifier& upper_cn_, rlc_tx_lower_layer_notifier& lower_dn_, 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_high(metrics_enabled), metrics_low(metrics_enabled), @@ -41,7 +44,11 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, 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} { } @@ -53,6 +60,10 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, 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; public: /// \brief Stops all internal timers. diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index 746d5fe88b..700043831f 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -19,13 +19,24 @@ 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_, 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_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_low.metrics_set_mode(rlc_mode::tm); diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index 81c6d85537..4588ed74a3 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -25,8 +25,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. @@ -43,12 +41,14 @@ 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_, 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 { + // There are no timers to be stopped here. }; // Interfaces for higher layers diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index c7137faec3..05283647b1 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -22,17 +22,28 @@ 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_, 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_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_low.metrics_set_mode(rlc_mode::um_bidir); diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 064078b3c6..68a7b04cf6 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -56,8 +56,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 @@ -77,12 +75,14 @@ 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_, 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 { + // There are no timers to be stopped here. }; // Interfaces for higher layers diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index acf224a1d2..aea767dbec 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -29,10 +29,10 @@ 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) : + timer_manager& timers) : rlc_base_entity(gnb_du_id_, ue_index_, rb_id_, @@ -47,9 +47,11 @@ class rlc_um_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - pcell_executor, metrics_period.count() != 0, - pcap); + pcap, + pcell_executor, + ue_executor, + timers); rx = std::make_unique(gnb_du_id_, ue_index_, rb_id_, diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 4bcfcc2378..af09a966aa 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -150,11 +150,11 @@ std::vector generate_pdus(bench_params params, rx_order order) *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + false, + pcap, pcell_worker, ue_worker, - false, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc_tx->set_status_provider(tester.get()); diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index 7e84ea4080..b2ce86474c 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -119,11 +119,11 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + false, + pcap, pcell_worker, ue_worker, - false, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc->set_status_provider(tester.get()); diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index eb74250d8f..83af0a3fd6 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -118,11 +118,11 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf *tester, *tester, *tester, - timer_factory{timers, pcell_worker}, + true, + pcap, pcell_worker, ue_worker, - true, - pcap); + timers); // Bind AM Rx/Tx interconnect rlc->set_status_provider(tester.get()); diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index 8a8172ccf6..ea9209d746 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -74,9 +74,11 @@ class rlc_tx_tm_test : public ::testing::Test *tester, *tester, *tester, - pcell_worker, true, - pcap); + pcap, + pcell_worker, + ue_worker, + timers); } void TearDown() override @@ -87,9 +89,11 @@ class rlc_tx_tm_test : public ::testing::Test srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); manual_task_worker pcell_worker{128}; + manual_task_worker ue_worker{128}; std::unique_ptr tester; null_rlc_pcap pcap; std::unique_ptr rlc; + timer_manager timers; }; TEST_F(rlc_tx_tm_test, create_new_entity) diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 01ff24c294..693241d91f 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -97,10 +97,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, @@ -111,10 +111,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(); From ff541bee733d83b0f41641b8b92f7151113ccae2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jul 2024 22:12:13 +0100 Subject: [PATCH 21/66] rlc: pass metrics notifier to tx entity --- lib/rlc/rlc_am_entity.h | 1 + lib/rlc/rlc_tm_entity.h | 1 + lib/rlc/rlc_tx_am_entity.cpp | 2 ++ lib/rlc/rlc_tx_am_entity.h | 1 + lib/rlc/rlc_tx_entity.h | 8 +++++++- lib/rlc/rlc_tx_tm_entity.cpp | 3 +++ lib/rlc/rlc_tx_tm_entity.h | 1 + lib/rlc/rlc_tx_um_entity.cpp | 2 ++ lib/rlc/rlc_tx_um_entity.h | 1 + lib/rlc/rlc_um_entity.h | 1 + tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 7 ++++++- tests/benchmarks/rlc/rlc_handle_status_report.cpp | 7 ++++++- tests/unittests/rlc/rlc_tx_am_test.cpp | 7 ++++++- tests/unittests/rlc/rlc_tx_tm_test.cpp | 7 ++++++- 14 files changed, 44 insertions(+), 5 deletions(-) diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index 3f75405493..9d9789d60c 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -48,6 +48,7 @@ class rlc_am_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, + rlc_metrics_notifier_, metrics_period.count() != 0, pcap, pcell_executor, diff --git a/lib/rlc/rlc_tm_entity.h b/lib/rlc/rlc_tm_entity.h index 45cdd616c4..78bbd4a132 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -47,6 +47,7 @@ class rlc_tm_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, + rlc_metrics_notifier_, metrics_period.count() != 0, pcap, pcell_executor, diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index f2ed640d50..01513c6a9e 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -26,6 +26,7 @@ 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_, + rlc_metrics_notifier* metrics_notifier_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -37,6 +38,7 @@ rlc_tx_am_entity::rlc_tx_am_entity(gnb_du_id_t gnb_du_i upper_dn_, upper_cn_, lower_dn_, + metrics_notifier_, metrics_enabled_, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index d1222a03a8..2ceafd8f60 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -133,6 +133,7 @@ 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_, + rlc_metrics_notifier* metrics_notifier_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index fa3afb086f..0387850bdf 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -11,6 +11,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" @@ -32,6 +33,7 @@ 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_notifier* rlc_metrics_notifier_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -48,7 +50,8 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, pcell_executor{pcell_executor_}, ue_executor{ue_executor_}, pcell_timer_factory{timers, pcell_executor}, - ue_timer_factory{timers, ue_executor} + ue_timer_factory{timers, ue_executor}, + metrics_agg(rlc_metrics_notifier_) { } @@ -65,6 +68,9 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, timer_factory pcell_timer_factory; timer_factory ue_timer_factory; +private: + rlc_metrics_aggregator metrics_agg; + public: /// \brief Stops all internal timers. /// diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index 700043831f..dc6a35fd3d 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -9,6 +9,7 @@ */ #include "rlc_tx_tm_entity.h" +#include "srsran/rlc/rlc_metrics.h" using namespace srsran; @@ -19,6 +20,7 @@ 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_, + rlc_metrics_notifier* metrics_notifier_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -30,6 +32,7 @@ rlc_tx_tm_entity::rlc_tx_tm_entity(gnb_du_id_t du_id, upper_dn_, upper_cn_, lower_dn_, + metrics_notifier_, metrics_enabled_, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index 4588ed74a3..78ffe9a706 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -41,6 +41,7 @@ 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_, + rlc_metrics_notifier* rlc_metrics_notifier_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 05283647b1..736cd3eb31 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -22,6 +22,7 @@ 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_, + rlc_metrics_notifier* metrics_notifier_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -33,6 +34,7 @@ rlc_tx_um_entity::rlc_tx_um_entity(gnb_du_id_t du_id, upper_dn_, upper_cn_, lower_dn_, + metrics_notifier_, metrics_enabled, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 68a7b04cf6..7098c28d1e 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -75,6 +75,7 @@ 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_, + rlc_metrics_notifier* metrics_notifier_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index aea767dbec..35a1c62368 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -47,6 +47,7 @@ class rlc_um_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, + rlc_metrics_notifier_, metrics_period.count() != 0, pcap, pcell_executor, diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index af09a966aa..a1b34fe4cd 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -21,7 +21,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; @@ -50,6 +51,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 {} }; /// Mocking class of the surrounding layers invoked by the RLC AM Rx entity. @@ -150,6 +154,7 @@ std::vector generate_pdus(bench_params params, rx_order order) *tester, *tester, *tester, + tester.get(), false, pcap, pcell_worker, diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index b2ce86474c..bcaa22cf51 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -20,7 +20,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; @@ -49,6 +50,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 { @@ -119,6 +123,7 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& *tester, *tester, *tester, + tester.get(), false, pcap, pcell_worker, diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index 83af0a3fd6..c675d6d093 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -21,7 +21,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; @@ -78,6 +79,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 @@ -118,6 +122,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf *tester, *tester, *tester, + tester.get(), true, pcap, pcell_worker, diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index ea9209d746..743eb0d85c 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -21,7 +21,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; @@ -45,6 +46,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 @@ -74,6 +78,7 @@ class rlc_tx_tm_test : public ::testing::Test *tester, *tester, *tester, + tester.get(), true, pcap, pcell_worker, From c9d1761de5ba68fb478b86b482671436375f7d7f Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 18 Jul 2024 22:42:25 +0100 Subject: [PATCH 22/66] rlc: run metrics timer --- lib/rlc/rlc_base_entity.h | 8 ++++---- lib/rlc/rlc_metrics_aggregator.cpp | 2 ++ lib/rlc/rlc_tx_entity.h | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index 763a613294..475d8cf364 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -40,10 +40,10 @@ class rlc_base_entity : public rlc_entity metrics_timer(timers.create_timer()) { 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(); - } + // 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; diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index 5f2168abb4..d4221f7bac 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -20,6 +20,7 @@ rlc_metrics_aggregator::rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) { + fmt::print("low metrics {}\n", m_lower_.counter); m_lower = m_lower_; if (m_lower.counter == m_higher.counter) { rlc_metrics report = {}; @@ -29,6 +30,7 @@ void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) { + fmt::print("high metrics {}\n", m_higher_.counter); m_higher = m_higher_; if (m_lower.counter == m_higher.counter) { rlc_metrics report = {}; diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index 0387850bdf..045c5556ae 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -51,8 +51,19 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, 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(rlc_metrics_notifier_) { + 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_hi_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_low_metrics()); }); + low_metrics_timer.run(); + } } rlc_bearer_logger logger; @@ -68,6 +79,9 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, 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; From 923772b738161b9008b3711920252458e9ff678d Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 19 Jul 2024 13:39:18 +0100 Subject: [PATCH 23/66] rlc: store metrics low and high on rlc_tx_metrics struct --- apps/services/rlc_metrics_plotter_json.cpp | 10 +- include/srsran/rlc/rlc_tx_metrics.h | 187 +++++++++++++----- .../e2sm_kpm_du_meas_provider_impl.cpp | 37 ++-- lib/rlc/rlc_metrics_aggregator.cpp | 15 +- lib/rlc/rlc_metrics_aggregator.h | 3 + lib/rlc/rlc_tx_metrics_container.h | 118 ----------- .../e2/e2sm_kpm_meas_provider_test.cpp | 22 +-- tests/unittests/rlc/rlc_tx_am_test.cpp | 56 +++--- tests/unittests/rlc/rlc_tx_tm_test.cpp | 8 +- tests/unittests/rlc/rlc_um_test.cpp | 56 +++--- 10 files changed, 239 insertions(+), 273 deletions(-) diff --git a/apps/services/rlc_metrics_plotter_json.cpp b/apps/services/rlc_metrics_plotter_json.cpp index c2de41c81c..f254bdc565 100644 --- a/apps/services/rlc_metrics_plotter_json.cpp +++ b/apps/services/rlc_metrics_plotter_json.cpp @@ -90,11 +90,11 @@ void rlc_metrics_plotter_json::report_metrics(const rlc_metrics& drb) // 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/include/srsran/rlc/rlc_tx_metrics.h b/include/srsran/rlc/rlc_tx_metrics.h index 92098f73e0..b4809de98c 100644 --- a/include/srsran/rlc/rlc_tx_metrics.h +++ b/include/srsran/rlc/rlc_tx_metrics.h @@ -17,35 +17,75 @@ namespace srsran { -struct rlc_tm_tx_metrics { +struct rlc_tx_metrics_higher { + 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)> + + 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_of_pulled_sdus = {}; + num_sdu_bytes = {}; + num_dropped_sdus = {}; + num_discarded_sdus = {}; + num_discard_failures = {}; + sum_sdu_latency_us = {}; + // 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 @@ -57,10 +97,47 @@ 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 = {}; + + // 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 @@ -85,39 +162,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); } @@ -141,13 +220,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/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 2c13a125ba..b0db5dd32a 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 @@ -135,6 +135,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; @@ -437,20 +438,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; @@ -459,7 +460,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() / @@ -649,11 +650,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) { @@ -681,13 +682,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; } @@ -725,7 +726,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 @@ -747,7 +748,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; @@ -829,11 +830,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_high.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_high.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; @@ -859,16 +860,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_high.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/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index d4221f7bac..09127e8c3d 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -18,22 +18,23 @@ rlc_metrics_aggregator::rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics m_higher.counter = UINT32_MAX; } -void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) +void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) { - fmt::print("low metrics {}\n", m_lower_.counter); - m_lower = m_lower_; + fmt::print("high metrics {}\n", m_higher_.counter); + m_higher = m_higher_; if (m_lower.counter == m_higher.counter) { rlc_metrics report = {}; rlc_metrics_notif->report_metrics(report); } } -void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) +// TODO make sure this is run in the UE executor +void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) { - fmt::print("high metrics {}\n", m_higher_.counter); - m_higher = m_higher_; + fmt::print("low metrics {}\n", m_lower_.counter); + m_lower = m_lower_; if (m_lower.counter == m_higher.counter) { - rlc_metrics report = {}; + rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, {}, 0, std::chrono::milliseconds{1000}}; rlc_metrics_notif->report_metrics(report); } } diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 27fd9f6d1a..7f41d9f1fd 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -30,6 +30,9 @@ class rlc_metrics_aggregator private: rlc_metrics_notifier* rlc_metrics_notif; + uint32_t du; + du_ue_index_t ue; + rb_id_t rb; rlc_tx_metrics_lower m_lower; rlc_tx_metrics_higher m_higher; }; diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index df750c0157..10e7a91393 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -14,124 +14,6 @@ namespace srsran { -struct rlc_tx_metrics_higher { - 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)> - - 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_of_pulled_sdus = {}; - num_sdu_bytes = {}; - num_dropped_sdus = {}; - num_discarded_sdus = {}; - num_discard_failures = {}; - sum_sdu_latency_us = {}; - // 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_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_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 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 - - 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 = {}; - } -}; - -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 - - /// RLC mode of the entity - rlc_mode 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_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 = {}; - - // 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; - } - } -}; - class rlc_tx_metrics_high_container { rlc_tx_metrics_higher metrics_hi = {}; diff --git a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp index 72746c44da..4c56323aa2 100644 --- a/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp +++ b/tests/unittests/e2/e2sm_kpm_meas_provider_test.cpp @@ -126,17 +126,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/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index c675d6d093..9dec950575 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -476,8 +476,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); @@ -485,8 +485,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); @@ -494,8 +494,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; @@ -511,8 +511,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); @@ -520,8 +520,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); @@ -535,8 +535,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); @@ -546,8 +546,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) @@ -589,8 +589,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); @@ -598,8 +598,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); @@ -607,8 +607,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; @@ -624,8 +624,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); @@ -633,8 +633,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); @@ -648,8 +648,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); @@ -659,8 +659,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 743eb0d85c..1368f02b62 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -224,8 +224,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); @@ -264,8 +264,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 693241d91f..aa8284cc6e 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -512,24 +512,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); @@ -543,16 +543,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); @@ -565,8 +565,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); @@ -576,8 +576,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) @@ -614,24 +614,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); @@ -645,16 +645,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); @@ -666,8 +666,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); @@ -676,8 +676,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) From e1f0d585dc939d4bedcae0da1f308d7f4bc82572 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 19 Jul 2024 13:51:31 +0100 Subject: [PATCH 24/66] rlc: push report from aggregator to metrics notifier --- lib/rlc/rlc_metrics_aggregator.cpp | 18 ++++++++++++------ lib/rlc/rlc_metrics_aggregator.h | 8 ++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index 09127e8c3d..b0e9c445ef 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -22,10 +22,10 @@ void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher { fmt::print("high metrics {}\n", m_higher_.counter); m_higher = m_higher_; - if (m_lower.counter == m_higher.counter) { - rlc_metrics report = {}; - rlc_metrics_notif->report_metrics(report); + if (m_lower.counter != m_higher.counter) { + return; } + push_report(); } // TODO make sure this is run in the UE executor @@ -33,8 +33,14 @@ void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) { fmt::print("low metrics {}\n", m_lower_.counter); m_lower = m_lower_; - if (m_lower.counter == m_higher.counter) { - rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, {}, 0, std::chrono::milliseconds{1000}}; - rlc_metrics_notif->report_metrics(report); + if (m_lower.counter != m_higher.counter) { + return; } + push_report(); +} + +void rlc_metrics_aggregator::push_report() +{ + rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, {}, 0, std::chrono::milliseconds{1000}}; + rlc_metrics_notif->report_metrics(report); } diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 7f41d9f1fd..4bffea8f34 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -19,15 +19,19 @@ class rlc_metrics_aggregator public: rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_); - // \breif push metrics from the lower RLC executor to the agregator + // \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_); - // \breif push metrics from the high RLC executors to the agregator + // \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_); private: + // \brief build and push metrics report to the metrics notifier. + // Must be run from the UE executor. + void push_report(); + rlc_metrics_notifier* rlc_metrics_notif; uint32_t du; From e3dae153b24197f8372fa90c6e9f91747a0b1669 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 19 Jul 2024 16:32:11 +0100 Subject: [PATCH 25/66] rlc: pass ue executor for metrics aggregator --- apps/services/rlc_metrics_plotter_json.cpp | 2 +- include/srsran/rlc/rlc_metrics.h | 3 ++- lib/rlc/rlc_metrics_aggregator.cpp | 27 ++++++++++++++++--- lib/rlc/rlc_metrics_aggregator.h | 17 +++++++++--- lib/rlc/rlc_tx_entity.h | 2 +- .../rlc/rlc_metrics_aggregator_test.cpp | 6 ++++- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/apps/services/rlc_metrics_plotter_json.cpp b/apps/services/rlc_metrics_plotter_json.cpp index f254bdc565..d1c791a97b 100644 --- a/apps/services/rlc_metrics_plotter_json.cpp +++ b/apps/services/rlc_metrics_plotter_json.cpp @@ -84,7 +84,7 @@ 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())); diff --git a/include/srsran/rlc/rlc_metrics.h b/include/srsran/rlc/rlc_metrics.h index 4989c021d2..a6fd66280a 100644 --- a/include/srsran/rlc/rlc_metrics.h +++ b/include/srsran/rlc/rlc_metrics.h @@ -11,6 +11,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" @@ -19,7 +20,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/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index b0e9c445ef..af9c787d1f 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -11,14 +11,34 @@ using namespace srsran; -rlc_metrics_aggregator::rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_) : - rlc_metrics_notif(rlc_metrics_notif_) +rlc_metrics_aggregator::rlc_metrics_aggregator(gnb_du_id_t du_, + du_ue_index_t ue_, + rb_id_t rb_, + rlc_metrics_notifier* rlc_metrics_notif_, + task_executor& ue_executor_) : + du(du_), ue(ue_), rb(rb_), rlc_metrics_notif(rlc_metrics_notif_), ue_executor(ue_executor_) { m_lower.counter = UINT32_MAX; m_higher.counter = UINT32_MAX; } void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher_) +{ + fmt::print("high metrics {}\n", m_higher_.counter); + if (not ue_executor.execute([this, m_higher_]() { push_tx_high_metrics_impl(m_higher_); })) { + // TODO log error + } +} + +// TODO make sure this is run in the UE executor +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_); })) { + // TODO log error + } +} + +void rlc_metrics_aggregator::push_tx_high_metrics_impl(rlc_tx_metrics_higher m_higher_) { fmt::print("high metrics {}\n", m_higher_.counter); m_higher = m_higher_; @@ -28,8 +48,7 @@ void rlc_metrics_aggregator::push_tx_high_metrics(rlc_tx_metrics_higher m_higher push_report(); } -// TODO make sure this is run in the UE executor -void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) +void rlc_metrics_aggregator::push_tx_low_metrics_impl(rlc_tx_metrics_lower m_lower_) { fmt::print("low metrics {}\n", m_lower_.counter); m_lower = m_lower_; diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 4bffea8f34..7b7616d884 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -10,14 +10,18 @@ #pragma once -#include "rlc_tx_metrics_container.h" +#include "srsran/ran/gnb_du_id.h" #include "srsran/rlc/rlc_metrics.h" namespace srsran { class rlc_metrics_aggregator { public: - rlc_metrics_aggregator(rlc_metrics_notifier* rlc_metrics_notif_); + rlc_metrics_aggregator(gnb_du_id_t du, + du_ue_index_t ue, + rb_id_t rb, + 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 @@ -32,12 +36,17 @@ class rlc_metrics_aggregator // Must be run from the UE executor. void push_report(); - rlc_metrics_notifier* rlc_metrics_notif; + void push_tx_high_metrics_impl(rlc_tx_metrics_higher m_higher_); + void push_tx_low_metrics_impl(rlc_tx_metrics_lower m_lower_); - uint32_t du; + 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_metrics_notifier* rlc_metrics_notif; + + task_executor& ue_executor; }; } // namespace srsran diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index 045c5556ae..896565f072 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -53,7 +53,7 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, ue_timer_factory{timers, ue_executor}, high_metrics_timer(pcell_timer_factory.create_timer()), low_metrics_timer(ue_timer_factory.create_timer()), - metrics_agg(rlc_metrics_notifier_) + metrics_agg(gnb_du_id, ue_index, rb_id_, rlc_metrics_notifier_, ue_executor_) { if (metrics_enabled) { high_metrics_timer.set(std::chrono::milliseconds(1000), [this](timer_id_t tid) { diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index c7b409748d..ccc9ac5b7a 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -9,6 +9,7 @@ */ #include "lib/rlc/rlc_metrics_aggregator.h" #include "srsran/srslog/srslog.h" +#include "srsran/support/executors/manual_task_worker.h" #include using namespace srsran; @@ -37,7 +38,8 @@ class rlc_metrics_aggregator_test : public ::testing::Test // Create mock metrics notifier and RLC AM TX entity metrics_notif = std::make_unique(); - metrics_agg = std::make_unique(metrics_notif.get()); + metrics_agg = std::make_unique( + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, metrics_notif.get(), ue_worker); } void TearDown() override @@ -48,6 +50,8 @@ class rlc_metrics_aggregator_test : public ::testing::Test 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) From af171145f837fd97ae9362f83a1f34d0e407deb9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 19 Jul 2024 17:49:15 +0100 Subject: [PATCH 26/66] rlc: fix crash in TM tests --- lib/rlc/rlc_tx_tm_entity.h | 16 +++++++++++++--- tests/unittests/rlc/rlc_tx_tm_test.cpp | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index 78ffe9a706..29c89249f8 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -48,9 +48,17 @@ class rlc_tx_tm_entity : public rlc_tx_entity 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; @@ -75,6 +83,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/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index 1368f02b62..26dd9d6d8d 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -93,12 +93,12 @@ class rlc_tx_tm_test : public ::testing::Test } 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; - timer_manager timers; }; TEST_F(rlc_tx_tm_test, create_new_entity) From 03411e34b4f885a2ca79ab8ef17189d73c01a2c4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 10:00:03 +0100 Subject: [PATCH 27/66] rlc: fix metrics getter, that was required for unit tests --- lib/rlc/rlc_tx_entity.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index 896565f072..5d56663bad 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -98,12 +98,16 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, rlc_tx_metrics get_metrics() { - return {}; - /*return 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; } - void reset_metrics() + + virtual void reset_metrics() { - // return metrics.reset_metrics(); + // metrics_high.reset(); + // metrics_low.reset(); } }; From d94018f803c8116b2b6a8102ddb9f6a2303080b9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 10:15:38 +0100 Subject: [PATCH 28/66] rlc: restart metrics timer --- lib/rlc/rlc_tx_entity.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index 5d56663bad..e429b64ef3 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -58,10 +58,14 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, 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_hi_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_low_metrics()); + low_metrics_timer.run(); + }); + 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_low_metrics()); }); low_metrics_timer.run(); } } From 7e07c30d74edd80bbd20fef60951ab9a4d4cbbb8 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 11:30:33 +0100 Subject: [PATCH 29/66] rlc: push RX metrics to aggregator --- include/srsran/rlc/rlc_rx_metrics.h | 18 ++++++++++ lib/rlc/rlc_metrics_aggregator.cpp | 34 ++++++++++++------- lib/rlc/rlc_metrics_aggregator.h | 5 +++ lib/rlc/rlc_rx_metrics_container.h | 23 ++++--------- .../rlc/rlc_metrics_aggregator_test.cpp | 12 ++++++- 5 files changed, 61 insertions(+), 31 deletions(-) diff --git a/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index 4f6e974041..46eb77434d 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -55,6 +55,24 @@ 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() + { + uint32_t tmp_counter = counter; + *this = {}; + counter = tmp_counter; + // do not reset counter + } }; class rlc_rx_metrics_interface diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index af9c787d1f..783a0bd608 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -18,19 +18,18 @@ rlc_metrics_aggregator::rlc_metrics_aggregator(gnb_du_id_t du_, task_executor& ue_executor_) : du(du_), ue(ue_), rb(rb_), rlc_metrics_notif(rlc_metrics_notif_), ue_executor(ue_executor_) { - m_lower.counter = UINT32_MAX; - m_higher.counter = UINT32_MAX; + 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_) { - fmt::print("high metrics {}\n", m_higher_.counter); if (not ue_executor.execute([this, m_higher_]() { push_tx_high_metrics_impl(m_higher_); })) { // TODO log error } } -// TODO make sure this is run in the UE executor 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_); })) { @@ -38,28 +37,37 @@ void rlc_metrics_aggregator::push_tx_low_metrics(rlc_tx_metrics_lower m_lower_) } } +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_); })) { + // TODO log error + } +} + void rlc_metrics_aggregator::push_tx_high_metrics_impl(rlc_tx_metrics_higher m_higher_) { - fmt::print("high metrics {}\n", m_higher_.counter); m_higher = m_higher_; - if (m_lower.counter != m_higher.counter) { - return; - } push_report(); } void rlc_metrics_aggregator::push_tx_low_metrics_impl(rlc_tx_metrics_lower m_lower_) { - fmt::print("low metrics {}\n", m_lower_.counter); m_lower = m_lower_; - if (m_lower.counter != m_higher.counter) { - return; - } + 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() { - rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, {}, 0, std::chrono::milliseconds{1000}}; + if (m_lower.counter != m_higher.counter || m_lower.counter != m_rx_high.counter || + m_higher.counter != m_rx_high.counter) { + return; + } + rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, m_rx_high, 0, std::chrono::milliseconds{1000}}; rlc_metrics_notif->report_metrics(report); } diff --git a/lib/rlc/rlc_metrics_aggregator.h b/lib/rlc/rlc_metrics_aggregator.h index 7b7616d884..b8b93ad593 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -30,6 +30,9 @@ class rlc_metrics_aggregator // \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. @@ -38,12 +41,14 @@ class rlc_metrics_aggregator 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; rlc_metrics_notifier* rlc_metrics_notif; diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index 3d88947610..c8a410ef7f 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -18,7 +18,6 @@ namespace srsran { class rlc_rx_metrics_container { rlc_rx_metrics metrics = {}; - std::mutex metrics_mutex; bool enabled = false; public: @@ -29,7 +28,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.mode = mode; } @@ -38,7 +36,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_; } @@ -48,7 +45,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_; } @@ -58,7 +54,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_lost_pdus += num_pdus_; } @@ -67,7 +62,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.num_malformed_pdus += num_pdus_; } @@ -76,7 +70,6 @@ class rlc_rx_metrics_container if (not enabled) { return; } - std::lock_guard lock(metrics_mutex); metrics.sdu_latency_us += sdu_latency_us_; } @@ -86,7 +79,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_; @@ -98,7 +90,6 @@ class rlc_rx_metrics_container if (not enabled) { return {}; } - std::lock_guard lock(metrics_mutex); return metrics; } @@ -108,10 +99,9 @@ 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; + metrics = {}; + metrics.mode = ret.mode; return ret; } @@ -121,10 +111,9 @@ 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; + metrics = {}; + metrics.mode = tmp_mode; } }; } // namespace srsran diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index ccc9ac5b7a..f5611490a8 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -60,16 +60,20 @@ TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) { 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(), 1); + 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 } @@ -79,11 +83,17 @@ TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) { 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); From a82d8b1999d0314141a890b29dce273d13e12c1b Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 15:38:21 +0100 Subject: [PATCH 30/66] rlc: move some metrics from high to the low metrics --- include/srsran/rlc/rlc_tx_metrics.h | 8 ++--- .../e2sm_kpm_du_meas_provider_impl.cpp | 6 ++-- lib/rlc/rlc_tx_am_entity.cpp | 8 ++--- lib/rlc/rlc_tx_am_entity.h | 2 ++ lib/rlc/rlc_tx_metrics_container.h | 32 +++++++++---------- lib/rlc/rlc_tx_um_entity.cpp | 4 +-- lib/rlc/rlc_tx_um_entity.h | 14 ++++++-- 7 files changed, 42 insertions(+), 32 deletions(-) diff --git a/include/srsran/rlc/rlc_tx_metrics.h b/include/srsran/rlc/rlc_tx_metrics.h index b4809de98c..a86fab3771 100644 --- a/include/srsran/rlc/rlc_tx_metrics.h +++ b/include/srsran/rlc/rlc_tx_metrics.h @@ -19,12 +19,10 @@ namespace srsran { struct rlc_tx_metrics_higher { 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)> uint32_t counter = 0; ///< Counter of amount of times we collected metrics. /// Useful to aggregate high and low metrics. @@ -39,12 +37,10 @@ struct rlc_tx_metrics_higher { void reset() { num_sdus = {}; - num_of_pulled_sdus = {}; num_sdu_bytes = {}; num_dropped_sdus = {}; num_discarded_sdus = {}; num_discard_failures = {}; - sum_sdu_latency_us = {}; // do not reset counter } }; @@ -88,6 +84,8 @@ struct rlc_am_tx_metrics_lower { 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; @@ -115,6 +113,8 @@ struct rlc_tx_metrics_lower { { num_pdus_no_segmentation = {}; num_pdu_bytes_no_segmentation = {}; + num_of_pulled_sdus = {}; + sum_sdu_latency_us = {}; // reset mode-specific values switch (mode) { 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 b0db5dd32a..cd72d95d44 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 @@ -830,11 +830,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.tx_high.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.tx_high.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; @@ -864,7 +864,7 @@ bool e2sm_kpm_du_meas_provider_impl::get_drb_dl_rlc_sdu_latency(const asn1::e2sm 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_high.sum_sdu_latency_us; }); + [](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(), diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index 01513c6a9e..cf218f8786 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -280,8 +280,8 @@ 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_high.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics_high.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 @@ -442,8 +442,8 @@ 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_high.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics_high.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; } diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index 2ceafd8f60..cab1a5302e 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -144,6 +144,8 @@ class rlc_tx_am_entity : public rlc_tx_entity, public rlc_tx_am_status_handler, { // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically poll_retransmit_timer.stop(); + high_metrics_timer.stop(); + low_metrics_timer.stop(); }; // TX/RX interconnect diff --git a/lib/rlc/rlc_tx_metrics_container.h b/lib/rlc/rlc_tx_metrics_container.h index 10e7a91393..4ce59b0275 100644 --- a/lib/rlc/rlc_tx_metrics_container.h +++ b/lib/rlc/rlc_tx_metrics_container.h @@ -31,14 +31,6 @@ class rlc_tx_metrics_high_container metrics_hi.num_sdu_bytes += num_sdu_bytes; } - void metrics_add_pulled_sdus(uint32_t num_sdus) - { - if (not enabled) { - return; - } - metrics_hi.num_of_pulled_sdus += num_sdus; - } - void metrics_add_lost_sdus(uint32_t num_sdus) { if (not enabled) { @@ -63,14 +55,6 @@ class rlc_tx_metrics_high_container metrics_hi.num_discard_failures += num_discard_failures; } - void metrics_add_sdu_latency_us(uint32_t sdu_latency) - { - if (not enabled) { - return; - } - metrics_hi.sum_sdu_latency_us += sdu_latency; - } - // Metrics getters and setters rlc_tx_metrics_higher get_hi_metrics() { @@ -127,6 +111,22 @@ class rlc_tx_metrics_low_container metrics_lo.num_pdu_bytes_no_segmentation += num_pdu_bytes; } + void metrics_add_pulled_sdus(uint32_t num_sdus) + { + if (not enabled) { + return; + } + metrics_lo.num_of_pulled_sdus += num_sdus; + } + + void metrics_add_sdu_latency_us(uint32_t sdu_latency) + { + if (not enabled) { + return; + } + metrics_lo.sum_sdu_latency_us += sdu_latency; + } + // TM specific metrics void metrics_add_small_alloc(uint32_t num_allocs) { diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 736cd3eb31..8a2da6a151 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -187,8 +187,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_high.metrics_add_sdu_latency_us(latency.count() / 1000); - metrics_high.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; diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 7098c28d1e..8a68f2287f 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -82,9 +82,15 @@ class rlc_tx_um_entity : public rlc_tx_entity 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; @@ -117,6 +123,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 From fcd2a5b6c6876dc4b9fdf4346a4b77e511d91b60 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 16:58:40 +0100 Subject: [PATCH 31/66] rlc: fix up reset of RX metrics --- include/srsran/rlc/rlc_rx_metrics.h | 46 +++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index 46eb77434d..98490e2a7f 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -17,11 +17,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 { @@ -29,6 +36,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 { @@ -68,10 +82,32 @@ struct rlc_rx_metrics { void reset() { - uint32_t tmp_counter = counter; - *this = {}; - counter = tmp_counter; - // do not reset counter + // 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 } }; From 2922207ecda2f2db192ab482e4cfbbc8e18d7517 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 18:22:02 +0100 Subject: [PATCH 32/66] rlc: make sure RLC Rx metrics timer is initialized --- lib/rlc/rlc_am_entity.h | 7 +++-- lib/rlc/rlc_base_entity.h | 4 --- lib/rlc/rlc_rx_am_entity.cpp | 13 +++++---- lib/rlc/rlc_rx_am_entity.h | 11 +++---- lib/rlc/rlc_rx_entity.h | 30 ++++++++++++++++++-- lib/rlc/rlc_rx_tm_entity.cpp | 7 +++-- lib/rlc/rlc_rx_tm_entity.h | 20 ++++++++----- lib/rlc/rlc_rx_um_entity.cpp | 11 +++---- lib/rlc/rlc_rx_um_entity.h | 12 ++++---- lib/rlc/rlc_tm_entity.h | 12 ++++++-- lib/rlc/rlc_um_entity.h | 7 +++-- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 16 +++++++---- tests/unittests/rlc/rlc_rx_am_test.cpp | 16 +++++++---- tests/unittests/rlc/rlc_rx_tm_test.cpp | 12 ++++++-- 14 files changed, 119 insertions(+), 59 deletions(-) diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index 9d9789d60c..b952be481a 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -59,10 +59,11 @@ class rlc_am_entity : public rlc_base_entity rb_id_, config.rx, rx_upper_dn, - timer_factory{timers, ue_executor}, - ue_executor, + rlc_metrics_notifier_, 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 475d8cf364..eaf59769c8 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -40,10 +40,6 @@ class rlc_base_entity : public rlc_entity metrics_timer(timers.create_timer()) { 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; diff --git a/lib/rlc/rlc_rx_am_entity.cpp b/lib/rlc/rlc_rx_am_entity.cpp index f8381ecf76..5af0d727f7 100644 --- a/lib/rlc/rlc_rx_am_entity.cpp +++ b/lib/rlc/rlc_rx_am_entity.cpp @@ -20,11 +20,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_notifier* metrics_notifier_, 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_notifier_, 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))), @@ -32,8 +33,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 f8f9d8593f..e251ba715e 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -143,10 +143,11 @@ class rlc_rx_am_entity : public rlc_rx_entity, public rlc_rx_am_status_provider 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_notifier* metrics_notifier_, bool metrics_enabled, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor_, + timer_manager& timers); void stop() final { @@ -319,8 +320,8 @@ struct formatter { } template - auto format(const srsran::rlc_rx_am_sdu_info& info, FormatContext& ctx) - -> decltype(std::declval().out()) + 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 diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index c3d45093f2..13f1e52915 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -11,8 +11,10 @@ #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_metrics.h" #include "srsran/rlc/rlc_rx.h" namespace srsran { @@ -26,16 +28,38 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics 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_notifier* rlc_metrics_notifier_, + 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(gnb_du_id, ue_index, rb_id, rlc_metrics_notifier_, ue_executor_) { + if (metrics_enabled) { + high_metrics_timer.set(std::chrono::milliseconds(1000), [this](timer_id_t tid) { + metrics_agg.push_rx_high_metrics(metrics.get_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. diff --git a/lib/rlc/rlc_rx_tm_entity.cpp b/lib/rlc/rlc_rx_tm_entity.cpp index 6182d5a79f..6b7acafe18 100644 --- a/lib/rlc/rlc_rx_tm_entity.cpp +++ b/lib/rlc/rlc_rx_tm_entity.cpp @@ -17,9 +17,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_notifier* metrics_notifier_, 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_notifier_, 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 703bc5a1c2..9a0ab95cbe 100644 --- a/lib/rlc/rlc_rx_tm_entity.h +++ b/lib/rlc/rlc_rx_tm_entity.h @@ -11,25 +11,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_notifier* metrics_notifier_, bool metrics_enabled, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers); void stop() final { @@ -38,6 +36,14 @@ 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; + + rlc_metrics_notifier* metrics_notif; }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_um_entity.cpp b/lib/rlc/rlc_rx_um_entity.cpp index 9070fac61f..70ae1606f9 100644 --- a/lib/rlc/rlc_rx_um_entity.cpp +++ b/lib/rlc/rlc_rx_um_entity.cpp @@ -18,16 +18,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_notifier* metrics_notifier, 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_notifier, 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 25e73600f9..635204f8b8 100644 --- a/lib/rlc/rlc_rx_um_entity.h +++ b/lib/rlc/rlc_rx_um_entity.h @@ -13,6 +13,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" @@ -96,10 +97,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_notifier* metrics_notifier_, bool metrics_enabled_, - rlc_pcap& pcap_); + rlc_pcap& pcap_, + task_executor& ue_executor, + timer_manager& timers); void stop() final { @@ -172,8 +174,8 @@ struct formatter { } template - auto format(const srsran::rlc_rx_um_sdu_info& info, FormatContext& ctx) - -> decltype(std::declval().out()) + 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={}", diff --git a/lib/rlc/rlc_tm_entity.h b/lib/rlc/rlc_tm_entity.h index 78bbd4a132..e4e59fbf35 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -53,8 +53,16 @@ class rlc_tm_entity : public rlc_base_entity pcell_executor, ue_executor, timers); - rx = std::make_unique( - gnb_du_id_, ue_index_, rb_id_, config.rx, rx_upper_dn, metrics_period.count() != 0, pcap); + rx = std::make_unique(gnb_du_id_, + ue_index_, + rb_id_, + config.rx, + rx_upper_dn, + rlc_metrics_notifier_, + metrics_period.count() != 0, + pcap, + ue_executor, + timers); } }; diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index 35a1c62368..809c096e49 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -58,10 +58,11 @@ class rlc_um_entity : public rlc_base_entity rb_id_, config.rx, rx_upper_dn, - timer_factory{timers, ue_executor}, - ue_executor, + rlc_metrics_notifier_, metrics_period.count() != 0, - pcap); + pcap, + ue_executor, + timers); } }; diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index a1b34fe4cd..8c58c55e42 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -59,7 +59,8 @@ class rlc_tx_am_test_frame : public rlc_tx_upper_layer_data_notifier, /// 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() {} @@ -68,9 +69,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 { @@ -236,10 +239,11 @@ void benchmark_rx_pdu(const bench_params& params, rx_order order) drb_id_t::drb1, config, *tester, - timer_factory{timers, ue_worker}, - ue_worker, + tester.get(), false, - pcap); + pcap, + ue_worker, + timers); // Bind AM Rx/Tx interconnect rlc_rx->set_status_notifier(tester.get()); diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index 7079308e85..cd2220c9ae 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -42,7 +42,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; @@ -61,9 +62,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. @@ -92,10 +95,11 @@ class rlc_rx_am_test : public ::testing::Test, public ::testing::WithParamInterf srb_id_t::srb0, config, *tester, - timer_factory{timers, ue_worker}, - ue_worker, + tester.get(), true, - pcap); + pcap, + ue_worker, + timers); // Bind AM Tx/Rx interconnect rlc->set_status_handler(tester.get()); diff --git a/tests/unittests/rlc/rlc_rx_tm_test.cpp b/tests/unittests/rlc/rlc_rx_tm_test.cpp index 72f724d790..e9c878c3b5 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -11,13 +11,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; @@ -29,6 +30,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 @@ -56,8 +59,11 @@ class rlc_rx_am_test : public ::testing::Test srb_id_t::srb0, make_default_srb0_rlc_config().tm.rx, *tester, + tester.get(), true, - pcap); + pcap, + ue_executor, + timers); } void TearDown() override @@ -70,6 +76,8 @@ class rlc_rx_am_test : public ::testing::Test std::unique_ptr tester; null_rlc_pcap pcap; std::unique_ptr rlc; + manual_task_worker ue_executor{128}; + timer_manager timers; }; TEST_F(rlc_rx_am_test, create_new_entity) From ea90a9a96400b843abaee918233de1c1b65cfc67 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 22 Jul 2024 22:20:33 +0100 Subject: [PATCH 33/66] rlc: make tx and rx entities share metrics aggregator --- apps/services/metrics_log_helper.cpp | 1 + include/srsran/rlc/rlc_rx_metrics.h | 19 ++++++++------- lib/rlc/rlc_am_entity.h | 11 +++------ lib/rlc/rlc_base_entity.h | 17 +++---------- lib/rlc/rlc_rx_am_entity.cpp | 4 ++-- lib/rlc/rlc_rx_am_entity.h | 2 +- lib/rlc/rlc_rx_entity.h | 8 +++---- lib/rlc/rlc_rx_metrics_container.h | 13 +++++----- lib/rlc/rlc_rx_tm_entity.cpp | 4 ++-- lib/rlc/rlc_rx_tm_entity.h | 2 +- lib/rlc/rlc_rx_um_entity.cpp | 4 ++-- lib/rlc/rlc_rx_um_entity.h | 2 +- lib/rlc/rlc_tm_entity.h | 11 +++------ lib/rlc/rlc_tx_am_entity.cpp | 4 ++-- lib/rlc/rlc_tx_am_entity.h | 2 +- lib/rlc/rlc_tx_entity.h | 10 ++++---- lib/rlc/rlc_tx_tm_entity.cpp | 5 ++-- lib/rlc/rlc_tx_tm_entity.h | 2 +- lib/rlc/rlc_tx_um_entity.cpp | 4 ++-- lib/rlc/rlc_tx_um_entity.h | 2 +- lib/rlc/rlc_um_entity.h | 11 +++------ tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 13 +++++++--- .../rlc/rlc_handle_status_report.cpp | 7 ++++-- tests/unittests/rlc/rlc_rx_am_test.cpp | 22 ++++++++++------- tests/unittests/rlc/rlc_rx_tm_test.cpp | 18 ++++++++------ tests/unittests/rlc/rlc_tx_am_test.cpp | 24 +++++++++++-------- tests/unittests/rlc/rlc_tx_tm_test.cpp | 20 +++++++++------- 27 files changed, 122 insertions(+), 120 deletions(-) diff --git a/apps/services/metrics_log_helper.cpp b/apps/services/metrics_log_helper.cpp index da82e1d81c..fa9b0b2b79 100644 --- a/apps/services/metrics_log_helper.cpp +++ b/apps/services/metrics_log_helper.cpp @@ -121,6 +121,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/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index 98490e2a7f..bfd1905911 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -129,12 +129,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)) { @@ -149,9 +150,9 @@ 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", - scaled_fmt_integer(m.mode_specific.am.num_sdu_segments, false), + " num_sdu_segments={} sdu_segmments_rate={}bps ctrl_pdus={} ctrl_rate={}bps", + // scaled_fmt_integer(m.mode_specific.am.num_sdu_segments, false), + m.mode_specific.am.num_sdu_segments, float_to_eng_string( static_cast(m.mode_specific.am.num_sdu_segment_bytes) * 8 * 1000 / metrics_period.count(), 1, false), scaled_fmt_integer(m.mode_specific.am.num_ctrl_pdus, false), diff --git a/lib/rlc/rlc_am_entity.h b/lib/rlc/rlc_am_entity.h index b952be481a..2e6dcc9cb6 100644 --- a/lib/rlc/rlc_am_entity.h +++ b/lib/rlc/rlc_am_entity.h @@ -33,12 +33,7 @@ class rlc_am_entity : public rlc_base_entity task_executor& pcell_executor, task_executor& ue_executor, timer_manager& timers) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + 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_, @@ -48,7 +43,7 @@ class rlc_am_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, pcell_executor, @@ -59,7 +54,7 @@ class rlc_am_entity : public rlc_base_entity rb_id_, config.rx, rx_upper_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, ue_executor, diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index eaf59769c8..4f70eff677 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -32,12 +32,12 @@ 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_, rlc_metrics_notifier_, ue_executor_) { rlc_metrics_notif = rlc_metrics_notifier_; } @@ -90,21 +90,10 @@ class rlc_base_entity : public rlc_entity std::unique_ptr tx; std::unique_ptr rx; timer_duration metrics_period; + rlc_metrics_aggregator metrics_agg; 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(); - } }; } // namespace srsran diff --git a/lib/rlc/rlc_rx_am_entity.cpp b/lib/rlc/rlc_rx_am_entity.cpp index 5af0d727f7..e09d6c180d 100644 --- a/lib/rlc/rlc_rx_am_entity.cpp +++ b/lib/rlc/rlc_rx_am_entity.cpp @@ -20,12 +20,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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& ue_executor_, timer_manager& timers) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_notifier_, metrics_enabled, pcap_, ue_executor_, 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))), diff --git a/lib/rlc/rlc_rx_am_entity.h b/lib/rlc/rlc_rx_am_entity.h index e251ba715e..d8c629b55e 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -143,7 +143,7 @@ class rlc_rx_am_entity : public rlc_rx_entity, public rlc_rx_am_status_provider rb_id_t rb_id, const rlc_rx_am_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& ue_executor_, diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index 13f1e52915..154c953963 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -28,7 +28,7 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics du_ue_index_t ue_index, rb_id_t rb_id, rlc_rx_upper_layer_data_notifier& upper_dn_, - rlc_metrics_notifier* rlc_metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& ue_executor_, @@ -39,11 +39,11 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics pcap(pcap_), ue_timer_factory{timers, ue_executor_}, high_metrics_timer(ue_timer_factory.create_timer()), - metrics_agg(gnb_du_id, ue_index, rb_id, rlc_metrics_notifier_, ue_executor_) + 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_metrics()); + metrics_agg.push_rx_high_metrics(metrics.get_and_reset_metrics()); high_metrics_timer.run(); }); high_metrics_timer.run(); @@ -59,7 +59,7 @@ class rlc_rx_entity : public rlc_rx_lower_layer_interface, public rlc_rx_metrics unique_timer high_metrics_timer; private: - rlc_metrics_aggregator metrics_agg; + rlc_metrics_aggregator& metrics_agg; public: /// \brief Stops all internal timers. diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index c8a410ef7f..42e39b1ca1 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -11,7 +11,6 @@ #pragma once #include "srsran/rlc/rlc_rx_metrics.h" -#include namespace srsran { @@ -90,7 +89,7 @@ class rlc_rx_metrics_container if (not enabled) { return {}; } - return metrics; + return metrics.get(); } rlc_rx_metrics get_and_reset_metrics() @@ -99,7 +98,7 @@ class rlc_rx_metrics_container if (not enabled) { return {}; } - rlc_rx_metrics ret = metrics; + rlc_rx_metrics ret = metrics.get(); metrics = {}; metrics.mode = ret.mode; return ret; @@ -111,9 +110,11 @@ class rlc_rx_metrics_container if (not enabled) { return; } - 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 6b7acafe18..396caeaefb 100644 --- a/lib/rlc/rlc_rx_tm_entity.cpp +++ b/lib/rlc/rlc_rx_tm_entity.cpp @@ -17,12 +17,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_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& ue_executor, timer_manager& timers) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_notifier_, metrics_enabled, pcap_, ue_executor, 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 9a0ab95cbe..e88ae310f2 100644 --- a/lib/rlc/rlc_rx_tm_entity.h +++ b/lib/rlc/rlc_rx_tm_entity.h @@ -23,7 +23,7 @@ class rlc_rx_tm_entity : public rlc_rx_entity rb_id_t rb_id, const rlc_rx_tm_config& config, rlc_rx_upper_layer_data_notifier& upper_dn_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& ue_executor, diff --git a/lib/rlc/rlc_rx_um_entity.cpp b/lib/rlc/rlc_rx_um_entity.cpp index 70ae1606f9..a75c6f2200 100644 --- a/lib/rlc/rlc_rx_um_entity.cpp +++ b/lib/rlc/rlc_rx_um_entity.cpp @@ -18,12 +18,12 @@ 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_, - rlc_metrics_notifier* metrics_notifier, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enable, rlc_pcap& pcap_, task_executor& ue_executor, timer_manager& timers) : - rlc_rx_entity(gnb_du_id, ue_index, rb_id, upper_dn_, metrics_notifier, metrics_enable, pcap_, ue_executor, 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))), diff --git a/lib/rlc/rlc_rx_um_entity.h b/lib/rlc/rlc_rx_um_entity.h index 635204f8b8..861542ec7e 100644 --- a/lib/rlc/rlc_rx_um_entity.h +++ b/lib/rlc/rlc_rx_um_entity.h @@ -97,7 +97,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& ue_executor, diff --git a/lib/rlc/rlc_tm_entity.h b/lib/rlc/rlc_tm_entity.h index e4e59fbf35..7c8cdf0248 100644 --- a/lib/rlc/rlc_tm_entity.h +++ b/lib/rlc/rlc_tm_entity.h @@ -33,12 +33,7 @@ class rlc_tm_entity : public rlc_base_entity task_executor& pcell_executor, task_executor& ue_executor, timer_manager& timers) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + 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_, @@ -47,7 +42,7 @@ class rlc_tm_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, pcell_executor, @@ -58,7 +53,7 @@ class rlc_tm_entity : public rlc_base_entity rb_id_, config.rx, rx_upper_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, ue_executor, diff --git a/lib/rlc/rlc_tx_am_entity.cpp b/lib/rlc/rlc_tx_am_entity.cpp index cf218f8786..ab74c790c5 100644 --- a/lib/rlc/rlc_tx_am_entity.cpp +++ b/lib/rlc/rlc_tx_am_entity.cpp @@ -26,7 +26,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -38,7 +38,7 @@ rlc_tx_am_entity::rlc_tx_am_entity(gnb_du_id_t gnb_du_i upper_dn_, upper_cn_, lower_dn_, - metrics_notifier_, + metrics_agg_, metrics_enabled_, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index cab1a5302e..02aa98234a 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -133,7 +133,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_aggregator_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_tx_entity.h b/lib/rlc/rlc_tx_entity.h index e429b64ef3..857dbd2309 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -33,7 +33,7 @@ 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_notifier* rlc_metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -53,15 +53,15 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, ue_timer_factory{timers, ue_executor}, high_metrics_timer(pcell_timer_factory.create_timer()), low_metrics_timer(ue_timer_factory.create_timer()), - metrics_agg(gnb_du_id, ue_index, rb_id_, rlc_metrics_notifier_, ue_executor_) + 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_hi_metrics()); + 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_low_metrics()); + metrics_agg.push_tx_low_metrics(metrics_low.get_and_reset_metrics()); low_metrics_timer.run(); }); @@ -87,7 +87,7 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, unique_timer low_metrics_timer; private: - rlc_metrics_aggregator metrics_agg; + rlc_metrics_aggregator& metrics_agg; public: /// \brief Stops all internal timers. diff --git a/lib/rlc/rlc_tx_tm_entity.cpp b/lib/rlc/rlc_tx_tm_entity.cpp index dc6a35fd3d..796d169739 100644 --- a/lib/rlc/rlc_tx_tm_entity.cpp +++ b/lib/rlc/rlc_tx_tm_entity.cpp @@ -9,7 +9,6 @@ */ #include "rlc_tx_tm_entity.h" -#include "srsran/rlc/rlc_metrics.h" using namespace srsran; @@ -20,7 +19,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -32,7 +31,7 @@ rlc_tx_tm_entity::rlc_tx_tm_entity(gnb_du_id_t du_id, upper_dn_, upper_cn_, lower_dn_, - metrics_notifier_, + metrics_agg_, metrics_enabled_, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_tm_entity.h b/lib/rlc/rlc_tx_tm_entity.h index 29c89249f8..27f6acb7c2 100644 --- a/lib/rlc/rlc_tx_tm_entity.h +++ b/lib/rlc/rlc_tx_tm_entity.h @@ -41,7 +41,7 @@ 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_, - rlc_metrics_notifier* rlc_metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled_, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_tx_um_entity.cpp b/lib/rlc/rlc_tx_um_entity.cpp index 8a2da6a151..66bd18b3d5 100644 --- a/lib/rlc/rlc_tx_um_entity.cpp +++ b/lib/rlc/rlc_tx_um_entity.cpp @@ -22,7 +22,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, @@ -34,7 +34,7 @@ rlc_tx_um_entity::rlc_tx_um_entity(gnb_du_id_t du_id, upper_dn_, upper_cn_, lower_dn_, - metrics_notifier_, + metrics_agg_, metrics_enabled, pcap_, pcell_executor_, diff --git a/lib/rlc/rlc_tx_um_entity.h b/lib/rlc/rlc_tx_um_entity.h index 8a68f2287f..8cedb1fe3c 100644 --- a/lib/rlc/rlc_tx_um_entity.h +++ b/lib/rlc/rlc_tx_um_entity.h @@ -75,7 +75,7 @@ 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_, - rlc_metrics_notifier* metrics_notifier_, + rlc_metrics_aggregator& metrics_agg_, bool metrics_enabled, rlc_pcap& pcap_, task_executor& pcell_executor_, diff --git a/lib/rlc/rlc_um_entity.h b/lib/rlc/rlc_um_entity.h index 809c096e49..772ee5fd95 100644 --- a/lib/rlc/rlc_um_entity.h +++ b/lib/rlc/rlc_um_entity.h @@ -33,12 +33,7 @@ class rlc_um_entity : public rlc_base_entity task_executor& pcell_executor, task_executor& ue_executor, timer_manager& timers) : - rlc_base_entity(gnb_du_id_, - ue_index_, - rb_id_, - metrics_period_, - rlc_metrics_notifier_, - timer_factory{timers, ue_executor}) + 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_, @@ -47,7 +42,7 @@ class rlc_um_entity : public rlc_base_entity tx_upper_dn, tx_upper_cn, tx_lower_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, pcell_executor, @@ -58,7 +53,7 @@ class rlc_um_entity : public rlc_base_entity rb_id_, config.rx, rx_upper_dn, - rlc_metrics_notifier_, + metrics_agg, metrics_period.count() != 0, pcap, ue_executor, diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 8c58c55e42..3a416c87f7 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -141,13 +141,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{}, tester.get(), ue_worker); + // Make PDUs std::vector pdus; rlc_tx = std::make_unique(gnb_du_id_t::min, @@ -157,7 +161,7 @@ std::vector generate_pdus(bench_params params, rx_order order) *tester, *tester, *tester, - tester.get(), + *metrics_agg, false, pcap, pcell_worker, @@ -233,13 +237,16 @@ 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{}, 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, - tester.get(), + *metrics_agg, false, pcap, ue_worker, diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index bcaa22cf51..b7a6e7c303 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -114,8 +114,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{}, 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, @@ -123,7 +126,7 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& *tester, *tester, *tester, - tester.get(), + *metrics_agg, false, pcap, pcell_worker, diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index cd2220c9ae..8dab8636c3 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -89,13 +89,16 @@ 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{}, 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, - tester.get(), + *metrics_agg, true, pcap, ue_worker, @@ -404,14 +407,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 e9c878c3b5..8636c1b3a9 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -53,13 +53,16 @@ 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{}, 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, - tester.get(), + *metrics_agg, true, pcap, ue_executor, @@ -72,12 +75,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; - manual_task_worker ue_executor{128}; - timer_manager timers; + srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST", false); + std::unique_ptr tester; + null_rlc_pcap pcap; + std::unique_ptr rlc; + std::unique_ptr metrics_agg; + manual_task_worker ue_executor{128}; + timer_manager timers; }; 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 9dec950575..7ee64dc1d3 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -114,6 +114,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{}, 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, @@ -122,7 +125,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf *tester, *tester, *tester, - tester.get(), + *metrics_agg, true, pcap, pcell_worker, @@ -304,15 +307,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) diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index 26dd9d6d8d..f468198155 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -70,6 +70,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{}, 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, @@ -78,7 +81,7 @@ class rlc_tx_tm_test : public ::testing::Test *tester, *tester, *tester, - tester.get(), + *metrics_agg, true, pcap, pcell_worker, @@ -92,13 +95,14 @@ class rlc_tx_tm_test : public ::testing::Test srslog::flush(); } - 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; + 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) From ac9f204c5f5b251a1814909ff7406d14b29914fd Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 23 Jul 2024 12:53:03 +0100 Subject: [PATCH 34/66] rlc: pass correct timer period in metrics for tput calculations --- lib/rlc/rlc_base_entity.h | 2 +- lib/rlc/rlc_metrics_aggregator.cpp | 11 +++++++++-- lib/rlc/rlc_metrics_aggregator.h | 5 +++++ lib/rlc/rlc_rx_am_entity.h | 12 ++++++------ tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 8 ++++---- tests/benchmarks/rlc/rlc_handle_status_report.cpp | 4 ++-- tests/unittests/rlc/rlc_metrics_aggregator_test.cpp | 2 +- tests/unittests/rlc/rlc_rx_am_test.cpp | 4 ++-- tests/unittests/rlc/rlc_rx_tm_test.cpp | 6 +++--- tests/unittests/rlc/rlc_tx_am_test.cpp | 4 ++-- tests/unittests/rlc/rlc_tx_tm_test.cpp | 4 ++-- 11 files changed, 37 insertions(+), 25 deletions(-) diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index 4f70eff677..6a306f4b1c 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -37,7 +37,7 @@ class rlc_base_entity : public rlc_entity ue_index(ue_index_), rb_id(rb_id_), metrics_period(metrics_period_), - metrics_agg(gnb_du_id_, ue_index, rb_id_, rlc_metrics_notifier_, ue_executor_) + metrics_agg(gnb_du_id_, ue_index, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor_) { rlc_metrics_notif = rlc_metrics_notifier_; } diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index 783a0bd608..a24f15b230 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -14,9 +14,16 @@ 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_), rlc_metrics_notif(rlc_metrics_notif_), ue_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; @@ -68,6 +75,6 @@ void rlc_metrics_aggregator::push_report() m_higher.counter != m_rx_high.counter) { return; } - rlc_metrics report = {du, ue, rb, {m_higher, m_lower}, m_rx_high, 0, std::chrono::milliseconds{1000}}; + 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 index b8b93ad593..93ad3ff85a 100644 --- a/lib/rlc/rlc_metrics_aggregator.h +++ b/lib/rlc/rlc_metrics_aggregator.h @@ -10,6 +10,7 @@ #pragma once +#include "rlc_bearer_logger.h" #include "srsran/ran/gnb_du_id.h" #include "srsran/rlc/rlc_metrics.h" @@ -20,6 +21,7 @@ class 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_); @@ -49,9 +51,12 @@ class rlc_metrics_aggregator 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.h b/lib/rlc/rlc_rx_am_entity.h index d8c629b55e..686a4de573 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -314,21 +314,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()) + auto format(const srsran::rlc_rx_am_sdu_info& info, FormatContext& ctx) { 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); @@ -346,13 +346,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/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 3a416c87f7..ee020da3f5 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -149,8 +149,8 @@ std::vector generate_pdus(bench_params params, rx_order order) null_rlc_pcap pcap; - metrics_agg = - std::make_unique(gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, tester.get(), ue_worker); + 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; @@ -237,8 +237,8 @@ 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{}, tester.get(), ue_worker); + 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, diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index b7a6e7c303..4a478f88e0 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -114,8 +114,8 @@ 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{}, tester.get(), ue_worker); + 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, &metrics_agg, config, &timers, &pcell_worker, &ue_worker, &pcap]() { diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index f5611490a8..6ea28a3b81 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -39,7 +39,7 @@ class rlc_metrics_aggregator_test : public ::testing::Test // 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{}, metrics_notif.get(), ue_worker); + gnb_du_id_t{}, du_ue_index_t{}, rb_id_t{}, timer_duration{1000}, metrics_notif.get(), ue_worker); } void TearDown() override diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index 8dab8636c3..4a69086a09 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -89,8 +89,8 @@ 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{}, tester.get(), ue_worker); + 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, diff --git a/tests/unittests/rlc/rlc_rx_tm_test.cpp b/tests/unittests/rlc/rlc_rx_tm_test.cpp index 8636c1b3a9..a42963e7e5 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -53,8 +53,8 @@ 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{}, tester.get(), ue_executor); + 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, @@ -76,12 +76,12 @@ class rlc_rx_am_test : public ::testing::Test } 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}; - timer_manager timers; }; 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 7ee64dc1d3..bb0adad0e0 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -114,8 +114,8 @@ 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{}, tester.get(), ue_worker); + 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, diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index f468198155..55039dd779 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -70,8 +70,8 @@ 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{}, tester.get(), ue_worker); + 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, From 7a4544f7b245ee0b57964c2479ed81c446ee88ec Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 23 Jul 2024 15:05:41 +0100 Subject: [PATCH 35/66] rlc: rm unecessary decltype from format --- lib/rlc/rlc_metrics_aggregator.cpp | 6 +++--- lib/rlc/rlc_rx_um_entity.h | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index a24f15b230..b3cdeeb58c 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -33,21 +33,21 @@ rlc_metrics_aggregator::rlc_metrics_aggregator(gnb_du_id_t du_, 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_); })) { - // TODO log error + 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_); })) { - // TODO log error + 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_); })) { - // TODO log error + logger.log_error("Could not push RX high metrics"); } } diff --git a/lib/rlc/rlc_rx_um_entity.h b/lib/rlc/rlc_rx_um_entity.h index 861542ec7e..0277f91185 100644 --- a/lib/rlc/rlc_rx_um_entity.h +++ b/lib/rlc/rlc_rx_um_entity.h @@ -168,14 +168,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()) + auto format(const srsran::rlc_rx_um_sdu_info& info, FormatContext& ctx) { return format_to(ctx.out(), "has_gap={} fully_received={} nof_segments={}", @@ -188,13 +187,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={}", From a1998ba8fa9e7837c3f7c2067a188eecd2e2f608 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Tue, 23 Jul 2024 18:22:20 +0100 Subject: [PATCH 36/66] rlc: fix RX metrics reset --- lib/rlc/rlc_rx_metrics_container.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rlc/rlc_rx_metrics_container.h b/lib/rlc/rlc_rx_metrics_container.h index 42e39b1ca1..36c0629b06 100644 --- a/lib/rlc/rlc_rx_metrics_container.h +++ b/lib/rlc/rlc_rx_metrics_container.h @@ -99,8 +99,7 @@ class rlc_rx_metrics_container return {}; } rlc_rx_metrics ret = metrics.get(); - metrics = {}; - metrics.mode = ret.mode; + reset_metrics(); return ret; } From a0b9e4df23671911db426e26932f553f44ba4888 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 24 Jul 2024 16:28:07 +0100 Subject: [PATCH 37/66] rlc: small fixes to metrics * removed commented code * removed unused private member * removed condition that was always true * removed unused function from rlc_tx/rx_entity * added stop flag to rlc_tx/rx_am_entity --- include/srsran/rlc/rlc_rx_metrics.h | 3 +-- lib/rlc/rlc_base_entity.h | 10 ---------- lib/rlc/rlc_metrics_aggregator.cpp | 3 +-- lib/rlc/rlc_rx_am_entity.h | 9 +++++++-- lib/rlc/rlc_rx_entity.h | 4 +--- lib/rlc/rlc_tx_am_entity.h | 11 ++++++++--- lib/rlc/rlc_tx_entity.h | 6 ------ 7 files changed, 18 insertions(+), 28 deletions(-) diff --git a/include/srsran/rlc/rlc_rx_metrics.h b/include/srsran/rlc/rlc_rx_metrics.h index bfd1905911..6aceed6da6 100644 --- a/include/srsran/rlc/rlc_rx_metrics.h +++ b/include/srsran/rlc/rlc_rx_metrics.h @@ -151,8 +151,7 @@ inline std::string format_rlc_rx_metrics(timer_duration metrics_period, const rl fmt::format_to( buffer, " num_sdu_segments={} sdu_segmments_rate={}bps ctrl_pdus={} ctrl_rate={}bps", - // scaled_fmt_integer(m.mode_specific.am.num_sdu_segments, false), - m.mode_specific.am.num_sdu_segments, + 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), scaled_fmt_integer(m.mode_specific.am.num_ctrl_pdus, false), diff --git a/lib/rlc/rlc_base_entity.h b/lib/rlc/rlc_base_entity.h index 6a306f4b1c..2485fa5e9e 100644 --- a/lib/rlc/rlc_base_entity.h +++ b/lib/rlc/rlc_base_entity.h @@ -39,7 +39,6 @@ class rlc_base_entity : public rlc_entity metrics_period(metrics_period_), metrics_agg(gnb_du_id_, ue_index, rb_id_, metrics_period_, rlc_metrics_notifier_, ue_executor_) { - rlc_metrics_notif = rlc_metrics_notifier_; } ~rlc_base_entity() override = default; rlc_base_entity(const rlc_base_entity&) = delete; @@ -77,12 +76,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; @@ -91,9 +84,6 @@ class rlc_base_entity : public rlc_entity std::unique_ptr rx; timer_duration metrics_period; rlc_metrics_aggregator metrics_agg; - -private: - rlc_metrics_notifier* rlc_metrics_notif; }; } // namespace srsran diff --git a/lib/rlc/rlc_metrics_aggregator.cpp b/lib/rlc/rlc_metrics_aggregator.cpp index b3cdeeb58c..13c2adf44f 100644 --- a/lib/rlc/rlc_metrics_aggregator.cpp +++ b/lib/rlc/rlc_metrics_aggregator.cpp @@ -71,8 +71,7 @@ void rlc_metrics_aggregator::push_rx_high_metrics_impl(rlc_rx_metrics m_rx_high_ void rlc_metrics_aggregator::push_report() { - if (m_lower.counter != m_higher.counter || m_lower.counter != m_rx_high.counter || - m_higher.counter != m_rx_high.counter) { + 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}; diff --git a/lib/rlc/rlc_rx_am_entity.h b/lib/rlc/rlc_rx_am_entity.h index 686a4de573..b08618025c 100644 --- a/lib/rlc/rlc_rx_am_entity.h +++ b/lib/rlc/rlc_rx_am_entity.h @@ -137,6 +137,8 @@ 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, @@ -152,8 +154,11 @@ class rlc_rx_am_entity : public rlc_rx_entity, public rlc_rx_am_status_provider 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 diff --git a/lib/rlc/rlc_rx_entity.h b/lib/rlc/rlc_rx_entity.h index 154c953963..b8f8f00242 100644 --- a/lib/rlc/rlc_rx_entity.h +++ b/lib/rlc/rlc_rx_entity.h @@ -14,14 +14,13 @@ #include "rlc_metrics_aggregator.h" #include "rlc_rx_metrics_container.h" #include "srsran/pcap/rlc_pcap.h" -#include "srsran/rlc/rlc_metrics.h" #include "srsran/rlc/rlc_rx.h" 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, @@ -73,7 +72,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_tx_am_entity.h b/lib/rlc/rlc_tx_am_entity.h index 02aa98234a..402c3ee8cc 100644 --- a/lib/rlc/rlc_tx_am_entity.h +++ b/lib/rlc/rlc_tx_am_entity.h @@ -125,6 +125,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, @@ -143,9 +145,12 @@ class rlc_tx_am_entity : public rlc_tx_entity, public rlc_tx_am_status_handler, void stop() final { // Stop all timers. Any queued handlers of timers that just expired before this call are canceled automatically - poll_retransmit_timer.stop(); - high_metrics_timer.stop(); - low_metrics_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 857dbd2309..af9c9a4b9b 100644 --- a/lib/rlc/rlc_tx_entity.h +++ b/lib/rlc/rlc_tx_entity.h @@ -107,12 +107,6 @@ class rlc_tx_entity : public rlc_tx_upper_layer_data_interface, m.tx_low = metrics_low.get_low_metrics(); return m; } - - virtual void reset_metrics() - { - // metrics_high.reset(); - // metrics_low.reset(); - } }; } // namespace srsran From 4693d62a4ee4cda55e91b5f631fd0cc2cd9dd5f3 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 24 Jul 2024 17:51:40 +0100 Subject: [PATCH 38/66] rlc: added unit test for missing report for metrics aggregator --- lib/rlc/rlc_rx_tm_entity.h | 2 - .../rlc/rlc_metrics_aggregator_test.cpp | 49 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/rlc/rlc_rx_tm_entity.h b/lib/rlc/rlc_rx_tm_entity.h index e88ae310f2..4ed8e75ec5 100644 --- a/lib/rlc/rlc_rx_tm_entity.h +++ b/lib/rlc/rlc_rx_tm_entity.h @@ -42,8 +42,6 @@ class rlc_rx_tm_entity : public rlc_rx_entity const rlc_rx_tm_config cfg; pcap_rlc_pdu_context pcap_context; - - rlc_metrics_notifier* metrics_notif; }; } // namespace srsran diff --git a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp index 6ea28a3b81..d4a5ea0fac 100644 --- a/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp +++ b/tests/unittests/rlc/rlc_metrics_aggregator_test.cpp @@ -105,6 +105,55 @@ TEST_F(rlc_metrics_aggregator_test, check_basic_aggregation) } } +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); From 3fca49b28793b43cd576ea0ff36619bc370a585b Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Fri, 19 Jul 2024 13:19:32 +0200 Subject: [PATCH 39/66] sec: add NIA2 engines (with/without MBEDTLS CMAC) --- lib/security/CMakeLists.txt | 2 + lib/security/integrity_engine_nia2_cmac.cpp | 97 +++++++++++++ lib/security/integrity_engine_nia2_cmac.h | 43 ++++++ .../integrity_engine_nia2_non_cmac.cpp | 131 ++++++++++++++++++ lib/security/integrity_engine_nia2_non_cmac.h | 37 +++++ lib/security/security_engine_impl.cpp | 22 ++- .../security/integrity_engine_test.cpp | 52 +++++++ 7 files changed, 378 insertions(+), 6 deletions(-) create mode 100644 lib/security/integrity_engine_nia2_cmac.cpp create mode 100644 lib/security/integrity_engine_nia2_cmac.h create mode 100644 lib/security/integrity_engine_nia2_non_cmac.cpp create mode 100644 lib/security/integrity_engine_nia2_non_cmac.h diff --git a/lib/security/CMakeLists.txt b/lib/security/CMakeLists.txt index e7c19025f4..86dbb410db 100644 --- a/lib/security/CMakeLists.txt +++ b/lib/security/CMakeLists.txt @@ -12,6 +12,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..bbf15c53d3 --- /dev/null +++ b/lib/security/integrity_engine_nia2_cmac.cpp @@ -0,0 +1,97 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2021-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. + * + */ + +#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_) +{ +} + +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()}; + + int ret; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t* cipher_info; + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + if (cipher_info == nullptr) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + mbedtls_cipher_init(&ctx); + + ret = mbedtls_cipher_setup(&ctx, cipher_info); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + + ret = mbedtls_cipher_cmac_starts(&ctx, k_128_int.data(), 128); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + + 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()); + + 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; + } + } + uint8_t tmp_mac[16]; + ret = mbedtls_cipher_cmac_finish(&ctx, tmp_mac); + if (ret != 0) { + result.buf = make_unexpected(security_error::integrity_failure); + return result; + } + mbedtls_cipher_free(&ctx); + for (int i = 0; i < 4; ++i) { + mac[i] = tmp_mac[i]; + } + + 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..2a69ee1f9f --- /dev/null +++ b/lib/security/integrity_engine_nia2_cmac.h @@ -0,0 +1,43 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2021-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. + * + */ + +#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() = 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; +}; + +#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..9d7c343b62 --- /dev/null +++ b/lib/security/integrity_engine_nia2_non_cmac.cpp @@ -0,0 +1,131 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2021-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. + * + */ + +#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_) +{ +} + +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; + aes_context ctx; + uint32_t i; + uint32_t j; + uint32_t n; + uint32_t pad_bits; + uint8_t const_zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t L[16]; + uint8_t K1[16]; + uint8_t K2[16]; + uint8_t T[16]; + uint8_t tmp[16]; + + 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); + + std::array M_buf; + span M(M_buf.data(), msg_len_block_8_with_padding); + + // Subkey L generation + aes_setkey_enc(&ctx, k_128_int.data(), 128); + aes_crypt_ecb(&ctx, aes_encrypt, const_zero, L); + + // Subkey K1 generation + for (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 (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; + } + + // Construct M + std::fill(M.begin(), M.end(), 0); + M[0] = (count >> 24) & 0xff; + M[1] = (count >> 16) & 0xff; + M[2] = (count >> 8) & 0xff; + M[3] = count & 0xff; + M[4] = (bearer_id << 3) | (to_number(direction) << 2); + for (i = 0; i < len; i++) { + M[8 + i] = v[i]; + } + + // MAC generation + n = (uint32_t)(ceilf((float)(len + 8) / (float)(16))); + for (i = 0; i < 16; i++) { + T[i] = 0; + } + for (i = 0; i < n - 1; i++) { + for (j = 0; j < 16; j++) { + tmp[j] = T[j] ^ M[i * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp, T); + } + pad_bits = ((len_bits) + 64) % 128; + if (pad_bits == 0) { + for (j = 0; j < 16; j++) { + tmp[j] = T[j] ^ K1[j] ^ M[i * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp, T); + } else { + pad_bits = (128 - pad_bits) - 1; + M[i * 16 + (15 - (pad_bits / 8))] |= 0x1 << (pad_bits % 8); + for (j = 0; j < 16; j++) { + tmp[j] = T[j] ^ K2[j] ^ M[i * 16 + j]; + } + aes_crypt_ecb(&ctx, aes_encrypt, tmp, T); + } + + for (i = 0; i < 4; i++) { + mac[i] = T[i]; + } + + 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..5d8266abb5 --- /dev/null +++ b/lib/security/integrity_engine_nia2_non_cmac.h @@ -0,0 +1,37 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2021-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. + * + */ + +#pragma once + +#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; +}; + +} // namespace security +} // namespace srsran diff --git a/lib/security/security_engine_impl.cpp b/lib/security/security_engine_impl.cpp index 82703e1170..13612384ec 100644 --- a/lib/security/security_engine_impl.cpp +++ b/lib/security/security_engine_impl.cpp @@ -15,6 +15,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; @@ -26,12 +28,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/tests/unittests/security/integrity_engine_test.cpp b/tests/unittests/security/integrity_engine_test.cpp index d041feaf75..e478ee1736 100644 --- a/tests/unittests/security/integrity_engine_test.cpp +++ b/tests/unittests/security/integrity_engine_test.cpp @@ -9,6 +9,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" @@ -128,6 +130,56 @@ TEST_P(fxt_nia1, integrity_engine_generic_nia1) 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 + 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 + 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) { nia_test_set param = GetParam(); From 693ecf18051d873f8371e6e4d09e75d670b9b846 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 15:36:29 +0200 Subject: [PATCH 40/66] sec: tests shall repeat integrity check twice with same engine... ...to ensure each transaction starts with a clean state. --- .../security/integrity_engine_test.cpp | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/tests/unittests/security/integrity_engine_test.cpp b/tests/unittests/security/integrity_engine_test.cpp index e478ee1736..7075351d1a 100644 --- a/tests/unittests/security/integrity_engine_test.cpp +++ b/tests/unittests/security/integrity_engine_test.cpp @@ -122,12 +122,14 @@ 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 @@ -147,12 +149,14 @@ TEST_P(fxt_nia2, integrity_engine_nia2_cmac) std::unique_ptr nia = std::make_unique(key, param.bearer, dir); // 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); + } } #endif // MBEDTLS_CMAC_C @@ -172,12 +176,14 @@ TEST_P(fxt_nia2, integrity_engine_nia2_non_cmac) std::unique_ptr nia = std::make_unique(key, param.bearer, dir); // 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_nia2, integrity_engine_generic_nia2) @@ -197,12 +203,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) @@ -222,12 +230,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); + } } ////////////////////////////////////////////////////////// From 83e983fdf6469ffe3e52ad04cd16cabb9296e066 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 23 Jul 2024 15:37:27 +0200 Subject: [PATCH 41/66] sec: optimize NIA2 engine (variant with CMAC) --- lib/security/integrity_engine_nia2_cmac.cpp | 61 +++++++++++++-------- lib/security/integrity_engine_nia2_cmac.h | 5 +- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/lib/security/integrity_engine_nia2_cmac.cpp b/lib/security/integrity_engine_nia2_cmac.cpp index bbf15c53d3..c9585d2ef4 100644 --- a/lib/security/integrity_engine_nia2_cmac.cpp +++ b/lib/security/integrity_engine_nia2_cmac.cpp @@ -24,37 +24,48 @@ integrity_engine_nia2_cmac::integrity_engine_nia2_cmac(sec_128_key k_128_ security_direction direction_) : k_128_int(k_128_int_), bearer_id(bearer_id_), direction(direction_) { -} - -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()}; - - int ret; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t* cipher_info; cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (cipher_info == nullptr) { - result.buf = make_unexpected(security_error::integrity_failure); - return result; + 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) { - result.buf = make_unexpected(security_error::integrity_failure); - return result; + 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; @@ -62,7 +73,12 @@ security_result integrity_engine_nia2_cmac::protect_integrity(byte_buffer buf, u 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()); @@ -71,16 +87,17 @@ security_result integrity_engine_nia2_cmac::protect_integrity(byte_buffer buf, u return result; } } - uint8_t tmp_mac[16]; - ret = mbedtls_cipher_cmac_finish(&ctx, tmp_mac); + + // 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; } - mbedtls_cipher_free(&ctx); - for (int i = 0; i < 4; ++i) { - mac[i] = tmp_mac[i]; - } + + // 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); diff --git a/lib/security/integrity_engine_nia2_cmac.h b/lib/security/integrity_engine_nia2_cmac.h index 2a69ee1f9f..c6b483ebc8 100644 --- a/lib/security/integrity_engine_nia2_cmac.h +++ b/lib/security/integrity_engine_nia2_cmac.h @@ -26,7 +26,7 @@ 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() = default; + ~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; @@ -35,6 +35,9 @@ class integrity_engine_nia2_cmac final : public integrity_engine 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 From 6374fb522b379a853b953f38b735b9ff9a659ea0 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Wed, 24 Jul 2024 11:43:18 +0200 Subject: [PATCH 42/66] sec: optimize NIA2 engine (variant without CMAC) --- .../integrity_engine_nia2_non_cmac.cpp | 120 ++++++++---------- lib/security/integrity_engine_nia2_non_cmac.h | 8 ++ 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/lib/security/integrity_engine_nia2_non_cmac.cpp b/lib/security/integrity_engine_nia2_non_cmac.cpp index 9d7c343b62..08ed1b3bca 100644 --- a/lib/security/integrity_engine_nia2_non_cmac.cpp +++ b/lib/security/integrity_engine_nia2_non_cmac.cpp @@ -22,6 +22,29 @@ integrity_engine_nia2_non_cmac::integrity_engine_nia2_non_cmac(sec_128_key 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) @@ -31,19 +54,11 @@ security_result integrity_engine_nia2_non_cmac::protect_integrity(byte_buffer bu byte_buffer_view v{result.buf.value().begin(), result.buf.value().end()}; - uint32_t len = v.length(); - uint32_t len_bits = len * 8; - aes_context ctx; - uint32_t i; - uint32_t j; - uint32_t n; - uint32_t pad_bits; - uint8_t const_zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t L[16]; - uint8_t K1[16]; - uint8_t K2[16]; - uint8_t T[16]; - uint8_t tmp[16]; + 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, @@ -52,71 +67,44 @@ security_result integrity_engine_nia2_non_cmac::protect_integrity(byte_buffer bu msg_len_block_8_with_padding, sec_max_pdu_size); - std::array M_buf; - span M(M_buf.data(), msg_len_block_8_with_padding); - - // Subkey L generation - aes_setkey_enc(&ctx, k_128_int.data(), 128); - aes_crypt_ecb(&ctx, aes_encrypt, const_zero, L); - - // Subkey K1 generation - for (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 (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; - } + span msg(msg_buf.data(), msg_len_block_8_with_padding); - // Construct M - std::fill(M.begin(), M.end(), 0); - M[0] = (count >> 24) & 0xff; - M[1] = (count >> 16) & 0xff; - M[2] = (count >> 8) & 0xff; - M[3] = count & 0xff; - M[4] = (bearer_id << 3) | (to_number(direction) << 2); - for (i = 0; i < len; i++) { - M[8 + i] = v[i]; - } + // 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 - n = (uint32_t)(ceilf((float)(len + 8) / (float)(16))); - for (i = 0; i < 16; i++) { - T[i] = 0; - } - for (i = 0; i < n - 1; i++) { - for (j = 0; j < 16; j++) { - tmp[j] = T[j] ^ M[i * 16 + j]; + 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, T); + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); } - pad_bits = ((len_bits) + 64) % 128; + uint32_t pad_bits = ((len_bits) + 64) % 128; if (pad_bits == 0) { - for (j = 0; j < 16; j++) { - tmp[j] = T[j] ^ K1[j] ^ M[i * 16 + j]; + 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, T); + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); } else { pad_bits = (128 - pad_bits) - 1; - M[i * 16 + (15 - (pad_bits / 8))] |= 0x1 << (pad_bits % 8); - for (j = 0; j < 16; j++) { - tmp[j] = T[j] ^ K2[j] ^ M[i * 16 + j]; + 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, T); + aes_crypt_ecb(&ctx, aes_encrypt, tmp.data(), tmp_mac.data()); } - for (i = 0; i < 4; i++) { - mac[i] = T[i]; - } + // 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); diff --git a/lib/security/integrity_engine_nia2_non_cmac.h b/lib/security/integrity_engine_nia2_non_cmac.h index 5d8266abb5..a44b766601 100644 --- a/lib/security/integrity_engine_nia2_non_cmac.h +++ b/lib/security/integrity_engine_nia2_non_cmac.h @@ -12,6 +12,7 @@ #pragma once +#include "mbedtls/aes.h" #include "srsran/security/integrity_engine.h" #include "srsran/security/security.h" @@ -31,6 +32,13 @@ class integrity_engine_nia2_non_cmac final : public integrity_engine 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 From 0f5d542bb3d14a43c01ea62abfe05f6a140c5a54 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 12:00:40 +0200 Subject: [PATCH 43/66] cu_up: remove ue_ctxt from ue_ctxt_list before launching bearer_context_release_procedure --- lib/e1ap/cu_up/e1ap_cu_up_impl.cpp | 12 ++++++++---- .../bearer_context_release_procedure.cpp | 15 +++------------ .../procedures/bearer_context_release_procedure.h | 6 ++---- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp index 62bd0a6f12..32a1860711 100644 --- a/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp +++ b/lib/e1ap/cu_up/e1ap_cu_up_impl.cpp @@ -269,11 +269,15 @@ void e1ap_cu_up_impl::handle_bearer_context_release_command(const asn1::e1ap::be return; } - e1ap_ue_context& ue_ctxt = ue_ctxt_list[int_to_gnb_cu_up_ue_e1ap_id(msg->gnb_cu_up_ue_e1ap_id)]; + 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; + + // 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); - cu_up_notifier.on_schedule_ue_async_task(ue_ctxt.ue_ids.ue_index, - launch_async( - ue_ctxt, msg, ue_ctxt_list, *pdu_notifier, cu_up_notifier, logger)); + // 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 index 83ce20f977..caadb00be9 100644 --- a/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.cpp @@ -16,18 +16,12 @@ using namespace srsran; using namespace srsran::srs_cu_up; -bearer_context_release_procedure::bearer_context_release_procedure(const e1ap_ue_context& ue_ctxt_, +bearer_context_release_procedure::bearer_context_release_procedure(ue_index_t ue_index_, const asn1::e1ap::bearer_context_release_cmd_s& cmd_, - e1ap_ue_context_list& ue_ctxt_list_, e1ap_message_notifier& pdu_notifier_, e1ap_cu_up_manager_notifier& cu_up_notifier_, srslog::basic_logger& logger_) : - ue_ctxt(ue_ctxt_), - cmd(cmd_), - ue_ctxt_list(ue_ctxt_list_), - pdu_notifier(pdu_notifier_), - cu_up_notifier(cu_up_notifier_), - logger(logger_) + ue_index(ue_index_), cmd(cmd_), pdu_notifier(pdu_notifier_), cu_up_notifier(cu_up_notifier_), logger(logger_) { } @@ -35,15 +29,12 @@ void bearer_context_release_procedure::operator()(coro_context> { CORO_BEGIN(ctx); - bearer_context_release_cmd.ue_index = ue_ctxt.ue_ids.ue_index; + 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)); - // Remove UE context - ue_ctxt_list.remove_ue(ue_ctxt.ue_ids.ue_index); - 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 = diff --git a/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h index 841f41052a..4143362431 100644 --- a/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h +++ b/lib/e1ap/cu_up/procedures/bearer_context_release_procedure.h @@ -25,9 +25,8 @@ namespace srsran::srs_cu_up { class bearer_context_release_procedure { public: - bearer_context_release_procedure(const e1ap_ue_context& ue_ctxt_, + bearer_context_release_procedure(ue_index_t ue_index, const asn1::e1ap::bearer_context_release_cmd_s& cmd_, - e1ap_ue_context_list& ue_ctxt_list_, e1ap_message_notifier& pdu_notifier_, e1ap_cu_up_manager_notifier& cu_up_notifier_, srslog::basic_logger& logger_); @@ -37,9 +36,8 @@ class bearer_context_release_procedure static const char* name() { return "E1AP CU-UP Bearer Context Release Procedure"; } private: - const e1ap_ue_context ue_ctxt; + ue_index_t ue_index; const asn1::e1ap::bearer_context_release_cmd_s cmd; - e1ap_ue_context_list& ue_ctxt_list; e1ap_message_notifier& pdu_notifier; e1ap_cu_up_manager_notifier& cu_up_notifier; srslog::basic_logger& logger; From c54a21bdeaa38877632d28b06bb03bfc3d1fb135 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 25 Jul 2024 10:43:33 +0200 Subject: [PATCH 44/66] phy: make DFT init faster --- lib/phy/upper/upper_phy_factories.cpp | 2 +- .../phy/upper/channel_processors/pxsch_bler_test_factories.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 1ca1070ab6..8c6d4fae45 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -338,7 +338,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/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp b/tests/integrationtests/phy/upper/channel_processors/pxsch_bler_test_factories.cpp index da35f08414..6321df01e3 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 @@ -53,7 +53,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"); From bc62ccb5fcf4cb2a83010b15f38deac43876f55f Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 12:58:26 +0200 Subject: [PATCH 45/66] f1ap,sctp: set F1AP port as per TS 38.472 Sec. 7 --- apps/cu/cu.cpp | 2 +- apps/du/adapters/f1_gateways.h | 2 +- include/srsran/gateways/sctp_network_gateway.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/cu/cu.cpp b/apps/cu/cu.cpp index 51321c0acf..6b1a09bd64 100644 --- a/apps/cu/cu.cpp +++ b/apps/cu/cu.cpp @@ -280,7 +280,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 65480de93f..c549edcd90 100644 --- a/apps/du/adapters/f1_gateways.h +++ b/apps/du/adapters/f1_gateways.h @@ -24,7 +24,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/include/srsran/gateways/sctp_network_gateway.h b/include/srsran/gateways/sctp_network_gateway.h index b5e52f8a42..00e51fbc18 100644 --- a/include/srsran/gateways/sctp_network_gateway.h +++ b/include/srsran/gateways/sctp_network_gateway.h @@ -23,6 +23,8 @@ 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 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 { /// Name provided to the interface node. From 597f3613d6006f917745df25acd8aa6ada8f5419 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 13:54:33 +0200 Subject: [PATCH 46/66] sctp: update includes --- include/srsran/gateways/sctp_network_gateway.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/srsran/gateways/sctp_network_gateway.h b/include/srsran/gateways/sctp_network_gateway.h index 00e51fbc18..d2501544ee 100644 --- a/include/srsran/gateways/sctp_network_gateway.h +++ b/include/srsran/gateways/sctp_network_gateway.h @@ -10,8 +10,8 @@ #pragma once -#include "srsran/adt/optional.h" #include "srsran/gateways/network_gateway.h" +#include #include namespace srsran { From 08bf889427a7770374f4dc613307e5a3752a87f8 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 13:55:14 +0200 Subject: [PATCH 47/66] sctp: convert comments to docstrings --- include/srsran/gateways/sctp_network_gateway.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/srsran/gateways/sctp_network_gateway.h b/include/srsran/gateways/sctp_network_gateway.h index d2501544ee..0bcad098ca 100644 --- a/include/srsran/gateways/sctp_network_gateway.h +++ b/include/srsran/gateways/sctp_network_gateway.h @@ -16,12 +16,12 @@ 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 F1AP_PORT = 38472; ///< F1AP port, see TS 38.472, section 7. From 0be895005a273cf1c3f5429d4564be785a7a06a3 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 14:07:24 +0200 Subject: [PATCH 48/66] ngap,sctp: define NGAP port in common location --- include/srsran/gateways/sctp_network_gateway.h | 1 + include/srsran/ngap/gateways/n2_connection_client_factory.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/srsran/gateways/sctp_network_gateway.h b/include/srsran/gateways/sctp_network_gateway.h index 0bcad098ca..6b0905dd10 100644 --- a/include/srsran/gateways/sctp_network_gateway.h +++ b/include/srsran/gateways/sctp_network_gateway.h @@ -23,6 +23,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. diff --git a/include/srsran/ngap/gateways/n2_connection_client_factory.h b/include/srsran/ngap/gateways/n2_connection_client_factory.h index 6635afe387..1cd6135c5a 100644 --- a/include/srsran/ngap/gateways/n2_connection_client_factory.h +++ b/include/srsran/ngap/gateways/n2_connection_client_factory.h @@ -32,7 +32,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; @@ -52,4 +52,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 From 011905c995e5f7e27c6626c844b8fe41a153cbee Mon Sep 17 00:00:00 2001 From: asaezper Date: Thu, 25 Jul 2024 13:26:31 +0200 Subject: [PATCH 49/66] ci: add 2x2 mimo dddsu tests --- .gitlab/ci/e2e.yml | 15 ++++ .gitlab/ci/e2e/.env | 2 +- .../ci/e2e/retina_request_zmq_2x2_mimo.yml | 79 +++++++++++++++++++ tests/e2e/pyproject.toml | 1 + tests/e2e/tests/iperf.py | 57 +++++++++++++ tests/e2e/tests/steps/configuration.py | 4 + 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 .gitlab/ci/e2e/retina_request_zmq_2x2_mimo.yml diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index c5907ca623..1c42fa705e 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -18,6 +18,7 @@ variables: - "zmq" - "zmq_deb" - "zmq_single_ue" + - "zmq_2x2_mimo" - "zmq_4x4_mimo" - "zmq_srsue" - "zmq_cudu" @@ -287,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: diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 20ce24afd0..e648aee215 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.12 +RETINA_VERSION=0.51.14 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/tests/e2e/pyproject.toml b/tests/e2e/pyproject.toml index c7b8084bb7..d7ba705db3 100644 --- a/tests/e2e/pyproject.toml +++ b/tests/e2e/pyproject.toml @@ -34,6 +34,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 65edcd1c05..1a2a5435b0 100644 --- a/tests/e2e/tests/iperf.py +++ b/tests/e2e/tests/iperf.py @@ -335,6 +335,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=False, + rx_to_tx_latency=2, + enable_dddsu=True, + ) + + @mark.parametrize( "direction", ( @@ -617,6 +670,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 @@ -633,6 +688,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 d3b9a37d51..ef8b2b17eb 100644 --- a/tests/e2e/tests/steps/configuration.py +++ b/tests/e2e/tests/steps/configuration.py @@ -40,6 +40,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 @@ -58,6 +60,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": { @@ -73,6 +76,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, }, }, } From 8e2001a555718027a620489814b1d3ab0bb1be0d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 26 Jul 2024 16:54:11 +0200 Subject: [PATCH 50/66] phy: review channel equalizer abnormal cases --- include/srsran/phy/support/re_buffer.h | 12 ++-- .../upper/equalization/modular_ch_est_list.h | 9 ++- .../pusch/pusch_demodulator_impl.h | 5 +- .../channel_equalizer_generic_impl.cpp | 59 ++++++++++++++++++- lib/phy/upper/equalization/equalize_zf_1xn.h | 14 +---- 5 files changed, 77 insertions(+), 22 deletions(-) diff --git a/include/srsran/phy/support/re_buffer.h b/include/srsran/phy/support/re_buffer.h index 11263beb25..2423ef2573 100644 --- a/include/srsran/phy/support/re_buffer.h +++ b/include/srsran/phy/support/re_buffer.h @@ -278,13 +278,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. @@ -340,7 +342,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. 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 c3a03b08f2..8006355775 100644 --- a/include/srsran/phy/upper/equalization/modular_ch_est_list.h +++ b/include/srsran/phy/upper/equalization/modular_ch_est_list.h @@ -16,6 +16,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: @@ -25,6 +26,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. @@ -97,7 +104,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/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h index 2910890abc..0376df4d9b 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h @@ -46,7 +46,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), @@ -215,7 +214,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. @@ -223,7 +222,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 bcb8b04941..aa766a8eca 100644 --- a/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp +++ b/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp @@ -16,6 +16,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; @@ -116,6 +118,61 @@ 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(unsigned nof_ports, + 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) +{ + // 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, @@ -173,7 +230,7 @@ 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( + equalize_zf_single_tx_layer_reduction( nof_rx_ports, 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 f29c27b9d2..d6f96d4be2 100644 --- a/lib/phy/upper/equalization/equalize_zf_1xn.h +++ b/lib/phy/upper/equalization/equalize_zf_1xn.h @@ -74,12 +74,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); @@ -106,12 +102,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)); From 88425e81a1dacf768476ecee1c9f2fb561049d7a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 29 Jul 2024 09:19:50 +0200 Subject: [PATCH 51/66] phy: review channel equalizer --- include/srsran/phy/support/re_buffer.h | 7 ++++--- lib/phy/support/resource_grid_mapper_impl.cpp | 2 +- .../channel_processors/pusch/pusch_demodulator_impl.h | 2 +- .../equalization/channel_equalizer_generic_impl.cpp | 9 +++++---- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/srsran/phy/support/re_buffer.h b/include/srsran/phy/support/re_buffer.h index 2423ef2573..f068d78009 100644 --- a/include/srsran/phy/support/re_buffer.h +++ b/include/srsran/phy/support/re_buffer.h @@ -278,7 +278,7 @@ 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: @@ -350,8 +350,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/lib/phy/support/resource_grid_mapper_impl.cpp b/lib/phy/support/resource_grid_mapper_impl.cpp index 68cf3da2a0..7d0293837e 100644 --- a/lib/phy/support/resource_grid_mapper_impl.cpp +++ b/lib/phy/support/resource_grid_mapper_impl.cpp @@ -272,7 +272,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 0376df4d9b..054024431e 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_demodulator_impl.h @@ -214,7 +214,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. diff --git a/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp b/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp index aa766a8eca..9446ce4a74 100644 --- a/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp +++ b/lib/phy/upper/equalization/channel_equalizer_generic_impl.cpp @@ -119,14 +119,15 @@ void equalize_zf_single_tx_layer<1>(unsigned /**/, } template -void equalize_zf_single_tx_layer_reduction(unsigned nof_ports, - span eq_symbols, +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()); @@ -146,7 +147,7 @@ void equalize_zf_single_tx_layer_reduction(unsigned 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_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])) { @@ -231,7 +232,7 @@ void channel_equalizer_generic_impl::equalize(span e // Single transmit layer and any number of receive ports. if (nof_tx_layers == 1) { equalize_zf_single_tx_layer_reduction( - nof_rx_ports, eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var_estimates, tx_scaling); + eq_symbols, eq_noise_vars, ch_symbols, ch_estimates, noise_var_estimates, tx_scaling); return; } From fd359ac670e571380609d59e7c8ff461accd2849 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Thu, 25 Jul 2024 16:05:13 +0200 Subject: [PATCH 52/66] nru: add support for Rel.16 flags/fields in NR-U DL User Data --- include/srsran/nru/nru_message.h | 21 ++++- lib/nru/nru_packing.cpp | 36 +++++++- tests/unittests/nru/nru_packing_test.cpp | 103 ++++++++++++++++++++--- 3 files changed, 144 insertions(+), 16 deletions(-) diff --git a/include/srsran/nru/nru_message.h b/include/srsran/nru/nru_message.h index 7c4da3957a..4097cd87ec 100644 --- a/include/srsran/nru/nru_message.h +++ b/include/srsran/nru/nru_message.h @@ -72,6 +72,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. @@ -89,13 +100,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/lib/nru/nru_packing.cpp b/lib/nru/nru_packing.cpp index a4da22f47d..ac70042e51 100644 --- a/lib/nru/nru_packing.cpp +++ b/lib/nru/nru_packing.cpp @@ -75,14 +75,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); @@ -121,6 +130,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; }; @@ -145,8 +159,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)); @@ -174,6 +197,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/tests/unittests/nru/nru_packing_test.cpp b/tests/unittests/nru/nru_packing_test.cpp index fdec07a125..80e4c0fa26 100644 --- a/tests/unittests/nru/nru_packing_test.cpp +++ b/tests/unittests/nru/nru_packing_test.cpp @@ -53,7 +53,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) @@ -78,7 +78,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) @@ -108,7 +108,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) @@ -130,11 +130,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) @@ -160,7 +243,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) @@ -186,7 +269,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) @@ -228,7 +311,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) @@ -245,7 +328,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) @@ -262,7 +345,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) @@ -280,7 +363,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) From 10d683b93465b1f44b5ebe798d43383c685dd45c Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Mon, 29 Jul 2024 17:02:17 +0200 Subject: [PATCH 53/66] prach_detector: new test vectors --- .../prach_detector_test_data.h | 98 ++++++++----------- .../prach_detector_test_data.tar.gz | 4 +- 2 files changed, 45 insertions(+), 57 deletions(-) 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 5e6dcb25e4..3e7f93490a 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 @@ -10,7 +10,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" @@ -53,60 +53,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/prach_detector_test_data.tar.gz b/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.tar.gz index c5d30157f8..dd3e8a24a7 100644 --- a/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.tar.gz +++ b/tests/unittests/phy/upper/channel_processors/prach_detector_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aaada60fc3f550f1f38ee31ffa14145ad29a12f53a2bce497c69946f0b44e8a -size 2321434 +oid sha256:db5825acea29a3deb534a0adafddb5323284fd01447b4c74a14e5ea90f418d82 +size 1625180 From 27c9a884207722f07d5307f51ac39daf970f6f96 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 26 Jul 2024 16:04:37 +0200 Subject: [PATCH 54/66] paging: use allocator with fallback for the paging --- lib/mac/mac_dl/paging_pdu_assembler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mac/mac_dl/paging_pdu_assembler.cpp b/lib/mac/mac_dl/paging_pdu_assembler.cpp index 39d3ff62da..62905bf84b 100644 --- a/lib/mac/mac_dl/paging_pdu_assembler.cpp +++ b/lib/mac/mac_dl/paging_pdu_assembler.cpp @@ -39,7 +39,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{}; From 7cc3a82e24128e80228690a23afdf9890aa3e8b6 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 30 Jul 2024 11:24:34 +0200 Subject: [PATCH 55/66] phy: fix TSAN in unit test --- tests/unittests/phy/support/resource_grid_test_doubles.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unittests/phy/support/resource_grid_test_doubles.h b/tests/unittests/phy/support/resource_grid_test_doubles.h index 405074c5fd..e5f2c886f1 100644 --- a/tests/unittests/phy/support/resource_grid_test_doubles.h +++ b/tests/unittests/phy/support/resource_grid_test_doubles.h @@ -209,7 +209,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. From fd6ce07c2855ed0a0a29e13539aec5808bf1d47b Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 10:15:55 +0200 Subject: [PATCH 56/66] cu_cp_unit: fix comments in slicing section --- apps/units/cu_cp/cu_cp_unit_config_cli11_schema.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 e62333203d..db9a793860 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 @@ -467,10 +467,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()); From dc18e790290ef99ca3c9e227f2217676e7359bc3 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 15:04:02 +0200 Subject: [PATCH 57/66] du_mgr: populate RRM policy member fields in logical channel configuration for DRBs --- .../converters/scheduler_configuration_helpers.cpp | 5 ++++- lib/du_manager/converters/scheduler_configuration_helpers.h | 3 ++- lib/du_manager/procedures/ue_configuration_procedure.cpp | 4 +++- lib/du_manager/procedures/ue_creation_procedure.cpp | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index 2c9f672cc2..8c86b188d1 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -73,7 +73,8 @@ srsran::srs_du::make_sched_cell_config_req(du_cell_index_t cell_index, return sched_req; } -sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const du_ue& ue_ctx) +sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const du_ue& ue_ctx, + const plmn_identity& ue_plmn_id) { sched_ue_config_request sched_cfg; @@ -100,6 +101,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_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 73d5cce7d3..3fb860b232 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.h +++ b/lib/du_manager/converters/scheduler_configuration_helpers.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/ran/plmn_identity.h" #include "srsran/scheduler/scheduler_configurator.h" namespace srsran { @@ -26,7 +27,7 @@ sched_cell_configuration_request_message make_sched_cell_config_req(du_cell_inde span si_payload_sizes); // Create scheduler UE Configuration Request based on DU UE configuration context. -sched_ue_config_request create_scheduler_ue_config_request(const du_ue& u); +sched_ue_config_request create_scheduler_ue_config_request(const du_ue& u, const plmn_identity& ue_plmn_id); } // namespace srs_du } // namespace srsran \ No newline at end of file diff --git a/lib/du_manager/procedures/ue_configuration_procedure.cpp b/lib/du_manager/procedures/ue_configuration_procedure.cpp index 3e7f7fe31c..3826643427 100644 --- a/lib/du_manager/procedures/ue_configuration_procedure.cpp +++ b/lib/du_manager/procedures/ue_configuration_procedure.cpp @@ -231,8 +231,10 @@ async_task ue_configuration_procedure::update_m lc_ch.dl_bearer = &bearer.connector.mac_tx_sdu_notifier; } + // Fetch the DU cell configuration of the primary cell UE is connected to. + const auto& cell_cfg = du_params.ran.cells[ue->pcell_index]; // Create Scheduler UE Reconfig Request that will be embedded in the mac configuration request. - mac_ue_reconf_req.sched_cfg = create_scheduler_ue_config_request(*ue); + mac_ue_reconf_req.sched_cfg = create_scheduler_ue_config_request(*ue, cell_cfg.nr_cgi.plmn_id); return du_params.mac.ue_cfg.handle_ue_reconfiguration_request(mac_ue_reconf_req); } diff --git a/lib/du_manager/procedures/ue_creation_procedure.cpp b/lib/du_manager/procedures/ue_creation_procedure.cpp index ed3feabe61..9690800566 100644 --- a/lib/du_manager/procedures/ue_creation_procedure.cpp +++ b/lib/du_manager/procedures/ue_creation_procedure.cpp @@ -201,8 +201,10 @@ async_task ue_creation_procedure::create_mac_ue() } mac_ue_create_msg.ul_ccch_msg = not req.ul_ccch_msg.empty() ? &req.ul_ccch_msg : nullptr; + // Fetch the DU cell configuration of the primary cell UE is connected to. + const auto& cell_cfg = du_params.ran.cells[ue_ctx->pcell_index]; // Create Scheduler UE Config Request that will be embedded in the mac UE creation request. - mac_ue_create_msg.sched_cfg = create_scheduler_ue_config_request(*ue_ctx); + mac_ue_create_msg.sched_cfg = create_scheduler_ue_config_request(*ue_ctx, cell_cfg.nr_cgi.plmn_id); // Request MAC to create new UE. return du_params.mac.ue_cfg.handle_ue_create_request(mac_ue_create_msg); From af04457df125e48069498be4396596ea4d825fec Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 15:18:31 +0200 Subject: [PATCH 58/66] du,du_high_unit: add option to set RAN slices and their scheduling parameters --- .../flexible_du/du_high/du_high_config.h | 19 +++++++++ .../du_high/du_high_config_cli11_schema.cpp | 42 +++++++++++++++++++ .../du_high/du_high_config_translators.cpp | 18 ++++++++ .../du_high/du_high_config_translators.h | 6 +++ include/srsran/du/du_cell_config.h | 4 ++ 5 files changed, 89 insertions(+) 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 ced6501bae..619d548023 100644 --- a/apps/units/flexible_du/du_high/du_high_config.h +++ b/apps/units/flexible_du/du_high/du_high_config.h @@ -27,6 +27,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" @@ -486,6 +487,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 number of PRBs to be allocated to this group. + unsigned min_prb = 0; + /// Sets the maximum number of PRBs to be allocated to this group. + unsigned max_prb = MAX_NOF_PRBS; +}; + +/// 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. @@ -540,6 +557,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 99e5e0b698..b2f5299c46 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 @@ -1027,6 +1027,31 @@ 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", slice_sched_params.min_prb, "Minimum number of PRBs to be allocated to the slice") + ->capture_default_str() + ->check(CLI::Range(0U, (unsigned)MAX_NOF_PRBS)); + add_option(app, "--max_prb", slice_sched_params.max_prb, "Maximum number of PRBs to be allocated to the slice") + ->capture_default_str() + ->check(CLI::Range(1U, (unsigned)MAX_NOF_PRBS)); +} + +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)); @@ -1180,6 +1205,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 ecd91f0991..ff47678f26 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 @@ -603,6 +603,9 @@ 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. + out_cell.rrm_policy_members = generate_du_slicing_rrm_policy_config(base_cell.plmn, base_cell.slice_cfg); + 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:{}", @@ -667,6 +670,21 @@ 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(const std::string& plmn, + span slice_cfg) +{ + std::vector rrm_policy_cfgs; + 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 = cfg.sched_cfg.min_prb; + rrm_policy_cfgs.back().max_prb = cfg.sched_cfg.max_prb; + } + 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 b18e2978e3..ac755be42e 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 @@ -9,6 +9,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" @@ -44,4 +46,8 @@ 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(const std::string& plmn, span slice_cfg); + } // namespace srsran diff --git a/include/srsran/du/du_cell_config.h b/include/srsran/du/du_cell_config.h index d70cfdd25e..8432d79dc2 100644 --- a/include/srsran/du/du_cell_config.h +++ b/include/srsran/du/du_cell_config.h @@ -20,6 +20,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 { @@ -167,6 +168,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 From d0d20a7414294bd6a1f93364073a7617621ff857 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 15:19:59 +0200 Subject: [PATCH 59/66] gnb: handle case of slicing parameters provided in DU and CU-CP --- apps/gnb/gnb.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 4c86583b24..8664a961e1 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -172,6 +172,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. @@ -213,6 +233,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. From 82d6c81955c7653dabefacd320317d3d660bb503 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 15:21:13 +0200 Subject: [PATCH 60/66] f1ap,du_mgr: populate slices information in F1 setup request --- include/srsran/f1ap/du/f1ap_du_connection_manager.h | 2 ++ .../converters/f1ap_configuration_helpers.cpp | 3 +++ lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp | 13 +++++++++++++ 3 files changed, 18 insertions(+) diff --git a/include/srsran/f1ap/du/f1ap_du_connection_manager.h b/include/srsran/f1ap/du/f1ap_du_connection_manager.h index 2948062128..6d0a16aa39 100644 --- a/include/srsran/f1ap/du/f1ap_du_connection_manager.h +++ b/include/srsran/f1ap/du/f1ap_du_connection_manager.h @@ -16,6 +16,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 @@ -35,6 +36,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/lib/du_manager/converters/f1ap_configuration_helpers.cpp b/lib/du_manager/converters/f1ap_configuration_helpers.cpp index fbb390ac0c..f98f67bacb 100644 --- a/lib/du_manager/converters/f1ap_configuration_helpers.cpp +++ b/lib/du_manager/converters/f1ap_configuration_helpers.cpp @@ -642,6 +642,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/f1ap/du/procedures/f1ap_du_setup_procedure.cpp b/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp index fa816efacc..44adf0a9dd 100644 --- a/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp +++ b/lib/f1ap/du/procedures/f1ap_du_setup_procedure.cpp @@ -101,6 +101,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; From ae2461bb67955316c5a34a223ec19f8f28d68ac9 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Mon, 22 Jul 2024 15:21:36 +0200 Subject: [PATCH 61/66] du_mgr: pass RRM policy members to the scheduler --- lib/du_manager/converters/scheduler_configuration_helpers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index 8c86b188d1..b4d02c88a0 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -70,6 +70,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; } From f04870364318828e854156ab7e8588442a5165f9 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Wed, 24 Jul 2024 13:21:07 +0200 Subject: [PATCH 62/66] du_mgr: store the NR Cell Global Identity of the UE's serving cell in DU UE context --- .../converters/scheduler_configuration_helpers.cpp | 5 ++--- .../converters/scheduler_configuration_helpers.h | 4 ++-- lib/du_manager/du_ue/du_ue.h | 10 ++++++++-- .../procedures/ue_configuration_procedure.cpp | 4 +--- lib/du_manager/procedures/ue_creation_procedure.cpp | 8 ++++---- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index b4d02c88a0..7c73486711 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -75,8 +75,7 @@ srsran::srs_du::make_sched_cell_config_req(du_cell_index_t cell_index, return sched_req; } -sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const du_ue& ue_ctx, - const plmn_identity& ue_plmn_id) +sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const du_ue& ue_ctx) { sched_ue_config_request sched_cfg; @@ -104,7 +103,7 @@ sched_ue_config_request srsran::srs_du::create_scheduler_ue_config_request(const 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_plmn_id.to_string(); + 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 3fb860b232..5c8b66eb2f 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.h +++ b/lib/du_manager/converters/scheduler_configuration_helpers.h @@ -27,7 +27,7 @@ sched_cell_configuration_request_message make_sched_cell_config_req(du_cell_inde span si_payload_sizes); // Create scheduler UE Configuration Request based on DU UE configuration context. -sched_ue_config_request create_scheduler_ue_config_request(const du_ue& u, const plmn_identity& ue_plmn_id); +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 dd8bad2042..197c468236 100644 --- a/lib/du_manager/du_ue/du_ue.h +++ b/lib/du_manager/du_ue/du_ue.h @@ -21,8 +21,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_) { } @@ -30,6 +34,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_configuration_procedure.cpp b/lib/du_manager/procedures/ue_configuration_procedure.cpp index 3826643427..3e7f7fe31c 100644 --- a/lib/du_manager/procedures/ue_configuration_procedure.cpp +++ b/lib/du_manager/procedures/ue_configuration_procedure.cpp @@ -231,10 +231,8 @@ async_task ue_configuration_procedure::update_m lc_ch.dl_bearer = &bearer.connector.mac_tx_sdu_notifier; } - // Fetch the DU cell configuration of the primary cell UE is connected to. - const auto& cell_cfg = du_params.ran.cells[ue->pcell_index]; // Create Scheduler UE Reconfig Request that will be embedded in the mac configuration request. - mac_ue_reconf_req.sched_cfg = create_scheduler_ue_config_request(*ue, cell_cfg.nr_cgi.plmn_id); + mac_ue_reconf_req.sched_cfg = create_scheduler_ue_config_request(*ue); return du_params.mac.ue_cfg.handle_ue_reconfiguration_request(mac_ue_reconf_req); } diff --git a/lib/du_manager/procedures/ue_creation_procedure.cpp b/lib/du_manager/procedures/ue_creation_procedure.cpp index 9690800566..99308f3a51 100644 --- a/lib/du_manager/procedures/ue_creation_procedure.cpp +++ b/lib/du_manager/procedures/ue_creation_procedure.cpp @@ -98,8 +98,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() @@ -201,10 +203,8 @@ async_task ue_creation_procedure::create_mac_ue() } mac_ue_create_msg.ul_ccch_msg = not req.ul_ccch_msg.empty() ? &req.ul_ccch_msg : nullptr; - // Fetch the DU cell configuration of the primary cell UE is connected to. - const auto& cell_cfg = du_params.ran.cells[ue_ctx->pcell_index]; // Create Scheduler UE Config Request that will be embedded in the mac UE creation request. - mac_ue_create_msg.sched_cfg = create_scheduler_ue_config_request(*ue_ctx, cell_cfg.nr_cgi.plmn_id); + mac_ue_create_msg.sched_cfg = create_scheduler_ue_config_request(*ue_ctx); // Request MAC to create new UE. return du_params.mac.ue_cfg.handle_ue_create_request(mac_ue_create_msg); From 644f984d25f52f4c2646177b459ad98d86db834e Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Wed, 24 Jul 2024 14:12:01 +0200 Subject: [PATCH 63/66] du_high_unit: use min. and max. PRB ratios in slice scheduling configuration --- .../flexible_du/du_high/du_high_config.h | 8 +++---- .../du_high/du_high_config_cli11_schema.cpp | 14 ++++++++---- .../du_high/du_high_config_translators.cpp | 22 +++++++++++-------- .../du_high/du_high_config_translators.h | 4 +++- 4 files changed, 30 insertions(+), 18 deletions(-) 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 619d548023..37057a6339 100644 --- a/apps/units/flexible_du/du_high/du_high_config.h +++ b/apps/units/flexible_du/du_high/du_high_config.h @@ -489,10 +489,10 @@ struct du_high_unit_prach_config { /// Slice scheduling configuration for a cell. struct du_high_unit_cell_slice_sched_config { - /// Sets the minimum number of PRBs to be allocated to this group. - unsigned min_prb = 0; - /// Sets the maximum number of PRBs to be allocated to this group. - unsigned max_prb = MAX_NOF_PRBS; + /// 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. 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 b2f5299c46..a0319abc8f 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 @@ -1030,12 +1030,18 @@ static void configure_cli11_sib_args(CLI::App& app, du_high_unit_sib_config& sib 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", slice_sched_params.min_prb, "Minimum number of PRBs to be allocated to the slice") + 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, (unsigned)MAX_NOF_PRBS)); - add_option(app, "--max_prb", slice_sched_params.max_prb, "Maximum number of PRBs to be allocated to the slice") + ->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, (unsigned)MAX_NOF_PRBS)); + ->check(CLI::Range(1U, 100U)); } static void configure_cli11_slicing_args(CLI::App& app, du_high_unit_cell_slice_config& slice_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 ff47678f26..22c7163bba 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 @@ -604,7 +604,8 @@ std::vector srsran::generate_du_cell_config(const du_high_unit_c } // Slicing configuration. - out_cell.rrm_policy_members = generate_du_slicing_rrm_policy_config(base_cell.plmn, base_cell.slice_cfg); + 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 " @@ -671,16 +672,19 @@ static mac_lc_config generate_mac_lc_config(const du_high_unit_mac_lc_config& in } std::vector -srsran::generate_du_slicing_rrm_policy_config(const std::string& plmn, - span slice_cfg) +srsran::generate_du_slicing_rrm_policy_config(span plmns, + span slice_cfg, + unsigned nof_cell_crbs) { std::vector rrm_policy_cfgs; - 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 = cfg.sched_cfg.min_prb; - rrm_policy_cfgs.back().max_prb = cfg.sched_cfg.max_prb; + 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; } 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 ac755be42e..b7670f871e 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 @@ -48,6 +48,8 @@ void ntn_augment_rlc_parameters(const ntn_config& ntn_cfg, std::map -generate_du_slicing_rrm_policy_config(const std::string& plmn, span slice_cfg); +generate_du_slicing_rrm_policy_config(span plmns, + span slice_cfg, + unsigned nof_cell_crbs); } // namespace srsran From 63c0ef446f9d6a1f89eb90481e5e03592cec39f6 Mon Sep 17 00:00:00 2001 From: asaezper Date: Tue, 30 Jul 2024 13:01:19 +0200 Subject: [PATCH 64/66] ci: fix tdd pattern conf for viavi tests --- .gitlab/ci/e2e/.env | 2 +- tests/e2e/tests/iperf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index e648aee215..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.14 +RETINA_VERSION=0.51.15 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 diff --git a/tests/e2e/tests/iperf.py b/tests/e2e/tests/iperf.py index 1a2a5435b0..b104554417 100644 --- a/tests/e2e/tests/iperf.py +++ b/tests/e2e/tests/iperf.py @@ -382,7 +382,7 @@ def test_zmq_2x2_mimo( direction=direction, global_timing_advance=-1, time_alignment_calibration=0, - always_download_artifacts=False, + always_download_artifacts=True, rx_to_tx_latency=2, enable_dddsu=True, ) From f54f6071b6f5961d817018f4b18adc8b54066d8d Mon Sep 17 00:00:00 2001 From: asaezper Date: Tue, 30 Jul 2024 14:49:39 +0200 Subject: [PATCH 65/66] ci: disable n300 tests --- .gitlab/ci/e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 1c42fa705e..9aa85018e5 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -565,6 +565,7 @@ validate n300 config: variables: MARKERS: "rf_n300" TESTBED: "android_n300" + allow_failure: true ################################################################################ # Android @@ -602,6 +603,7 @@ android n300: extends: android x300 variables: TESTBED: "android_n300" + allow_failure: true ################################################################################ # VIAVI From c7e75d43bfef7b8e11b2703e61111d6010f64563 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 26 Jul 2024 14:15:13 +0200 Subject: [PATCH 66/66] adt: methods to check the capacity and current size of the byte buffer pool --- include/srsran/adt/byte_buffer.h | 7 +++++++ lib/support/byte_buffer.cpp | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index 30a5a83c6e..c24229ded5 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -29,6 +29,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/lib/support/byte_buffer.cpp b/lib/support/byte_buffer.cpp index 7771e93fd3..93a2c7af16 100644 --- a/lib/support/byte_buffer.cpp +++ b/lib/support/byte_buffer.cpp @@ -41,6 +41,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