diff --git a/.clang-tidy b/.clang-tidy index 5af5cd29f0..7e8be7d9cb 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -22,6 +22,7 @@ Checks: '-*, -misc-unused-parameters, -misc-use-anonymous-namespace, -misc-non-private-member-variables-in-classes, + -misc-include-cleaner, modernize-*, -modernize-avoid-c-arrays, -modernize-use-trailing-return-type, diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index a99c25ce7d..48542b216b 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -544,7 +544,7 @@ intermediate commits: SAVE_ARTIFACTS: "True" script: - git config advice.detachedHead false - - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME + - git fetch origin --depth=20 $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME - | TEST_MODE=none for rev in $(git rev-list --reverse origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME..origin/$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME) @@ -1777,8 +1777,6 @@ basic avx512 dpdk: extends: .build_and_unit rules: - if: $CI_DESCRIPTION =~ /Nightly E2E Tests/ - when: manual - allow_failure: true retry: 2 interruptible: false variables: diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 49f81799ad..ec9af7bca3 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -517,8 +517,6 @@ android n300: viavi: stage: rf extends: .e2e-run - when: manual - allow_failure: true variables: GROUP: "viavi" TESTBED: "viavi" diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index fa24f2da95..196f3f05b5 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.44.2 +RETINA_VERSION=0.45.0 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 diff --git a/.gitlab/ci/e2e/retina_request_android_n300.yml b/.gitlab/ci/e2e/retina_request_android_n300.yml index f12e2deec2..873c851e08 100644 --- a/.gitlab/ci/e2e/retina_request_android_n300.yml +++ b/.gitlab/ci/e2e/retina_request_android_n300.yml @@ -30,15 +30,15 @@ requirements: arch: amd64 cpu: - requests: 12 - limits: 12 + requests: 10 + limits: 10 memory: - requests: "24G" - limits: "24G" + requests: "14G" + limits: "14G" ephemeral-storage: requests: "6G" limits: "6G" - taints: ["retina"] + taints: ["manual-testing"] resources: - type: sdr model: n3xx diff --git a/.gitlab/ci/e2e/retina_request_android_x300.yml b/.gitlab/ci/e2e/retina_request_android_x300.yml index 12ec6e9acc..20608eaee9 100644 --- a/.gitlab/ci/e2e/retina_request_android_x300.yml +++ b/.gitlab/ci/e2e/retina_request_android_x300.yml @@ -30,15 +30,15 @@ requirements: arch: amd64 cpu: - requests: 12 - limits: 12 + requests: 10 + limits: 10 memory: - requests: "24G" - limits: "24G" + requests: "14G" + limits: "14G" ephemeral-storage: requests: "6G" limits: "6G" - taints: ["retina"] + taints: ["manual-testing"] resources: - type: sdr model: x300 diff --git a/.gitlab/ci/e2e/retina_request_test_mode.yml b/.gitlab/ci/e2e/retina_request_test_mode.yml index 0b16ca52c0..9329d00e3e 100644 --- a/.gitlab/ci/e2e/retina_request_test_mode.yml +++ b/.gitlab/ci/e2e/retina_request_test_mode.yml @@ -23,7 +23,8 @@ limits: "6G" resources: - type: zmq - nof_ant: 4 + nof_antennas_dl: 4 + nof_antennas_ul: 4 environment: - PATH: ${PATH}:/builds/softwareradiosystems/srsgnb/build/apps/gnb shared_files: diff --git a/.gitlab/ci/e2e/retina_request_viavi.yml b/.gitlab/ci/e2e/retina_request_viavi.yml index c68e4c1e54..4b24cf4157 100644 --- a/.gitlab/ci/e2e/retina_request_viavi.yml +++ b/.gitlab/ci/e2e/retina_request_viavi.yml @@ -12,13 +12,13 @@ requirements: arch: amd64 cpu: - requests: 18 + requests: 20 memory: requests: "64G" limits: "64G" hugepages-1Gi: - requests: 2Gi - limits: 2Gi + requests: 4Gi + limits: 4Gi ephemeral-storage: requests: "20G" limits: "20G" diff --git a/.gitlab/ci/e2e/retina_request_zmq.yml b/.gitlab/ci/e2e/retina_request_zmq.yml index 12b5fea347..a8c3c2bdab 100644 --- a/.gitlab/ci/e2e/retina_request_zmq.yml +++ b/.gitlab/ci/e2e/retina_request_zmq.yml @@ -41,10 +41,9 @@ requests: 1 memory: requests: "8G" - limits: "8G" ephemeral-storage: - requests: "6G" - limits: "6G" + requests: "15G" + limits: "15G" resources: - type: zmq environment: diff --git a/.gitlab/ci/e2e/retina_request_zmq_4x4_mimo.yml b/.gitlab/ci/e2e/retina_request_zmq_4x4_mimo.yml index 1602839879..9801ad2927 100644 --- a/.gitlab/ci/e2e/retina_request_zmq_4x4_mimo.yml +++ b/.gitlab/ci/e2e/retina_request_zmq_4x4_mimo.yml @@ -22,7 +22,8 @@ limits: "6G" resources: - type: zmq - nof_ant: 4 + nof_antennas_dl: 4 + nof_antennas_ul: 4 - type: license model: amarisoft-5g shared_files: @@ -41,13 +42,13 @@ requests: 1 memory: requests: "8G" - limits: "8G" ephemeral-storage: requests: "6G" limits: "6G" resources: - type: zmq - nof_ant: 4 + nof_antennas_dl: 4 + nof_antennas_ul: 4 environment: - PATH: ${PATH}:/builds/softwareradiosystems/srsgnb/build/apps/gnb shared_files: diff --git a/.gitlab/run_viavi_pipeline.py b/.gitlab/run_viavi_pipeline.py index 6a0ba4c0b1..0745b36ec0 100644 --- a/.gitlab/run_viavi_pipeline.py +++ b/.gitlab/run_viavi_pipeline.py @@ -26,7 +26,7 @@ def main(): loglevel = args.loglevel INFRASTRUCTURE_TAG = "on-prem-amd64-avx2-avx512" - OS_NAME = "ubuntu-22.04" + OS_NAME = "ubuntu-24.04" COMPILER = "gcc" TESTMODE = "none" diff --git a/CMakeLists.txt b/CMakeLists.txt index a0b3087240..0e668da523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ endif (ENABLE_ASAN) if (ENABLE_TSAN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") + add_definitions(-DENABLE_TSAN) endif (ENABLE_TSAN) if (ENABLE_GCOV) diff --git a/apps/examples/du/du_example.cpp b/apps/examples/du/du_example.cpp index 06c0f7663e..6ff3ab1dcb 100644 --- a/apps/examples/du/du_example.cpp +++ b/apps/examples/du/du_example.cpp @@ -241,7 +241,7 @@ class dummy_cu_cp_handler : public f1c_connection_client 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x0c, 0xa8, 0x18, 0x06, 0x20, 0x00}; // Unpack the pre-canned Msg4, that contains the DL-CCCH RRC setup message. - byte_buffer msg4_pdu(span{msg4, sizeof(msg4)}); + byte_buffer msg4_pdu = byte_buffer::create(span{msg4, sizeof(msg4)}).value(); asn1::cbit_ref r_bref{msg4_pdu}; asn1::rrc_nr::dl_ccch_msg_s msg4_rrc; msg4_rrc.unpack(r_bref); diff --git a/apps/gnb/adapters/ngap_adapter.cpp b/apps/gnb/adapters/ngap_adapter.cpp index 608559d288..382908efa4 100644 --- a/apps/gnb/adapters/ngap_adapter.cpp +++ b/apps/gnb/adapters/ngap_adapter.cpp @@ -51,6 +51,16 @@ class ngap_gateway_local_stub final : public ngap_gateway_connector { srsran_assert(msg_handler != nullptr, "Adapter is disconnected"); + if (pcap_writer.is_write_enabled()) { + byte_buffer packed_pdu; + asn1::bit_ref bref{packed_pdu}; + if (msg.pdu.pack(bref) == asn1::SRSASN_SUCCESS) { + pcap_writer.push_pdu(std::move(packed_pdu)); + } else { + logger.warning("Failed to encode NGAP Tx PDU."); + } + } + if (msg.pdu.type().value == asn1::ngap::ngap_pdu_c::types_opts::init_msg and msg.pdu.init_msg().value.type().value == asn1::ngap::ngap_elem_procs_o::init_msg_c::types_opts::ng_setup_request) { diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 538d7d4620..77fa474e37 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -483,13 +483,13 @@ int main(int argc, char** argv) cu_up_cfg.ctrl_executor = workers.cu_up_ctrl_exec; cu_up_cfg.cu_up_e2_exec = workers.cu_up_e2_exec; cu_up_cfg.ue_exec_pool = workers.cu_up_exec_mapper.get(); - cu_up_cfg.io_ul_executor = workers.cu_up_ul_exec; // Optionally select separate exec for UL IO - cu_up_cfg.e1ap.e1ap_conn_client = &e1ap_gw; - cu_up_cfg.f1u_gateway = f1u_conn->get_f1u_cu_up_gateway(); - cu_up_cfg.epoll_broker = epoll_broker.get(); - cu_up_cfg.gtpu_pcap = gtpu_p.get(); - cu_up_cfg.timers = cu_timers; - cu_up_cfg.qos = generate_cu_up_qos_config(gnb_cfg); + cu_up_cfg.io_ul_executor = workers.cu_up_io_ul_exec; // Optionally select separate exec for UL IO + cu_up_cfg.e1ap.e1ap_conn_client = &e1ap_gw; + cu_up_cfg.f1u_gateway = f1u_conn->get_f1u_cu_up_gateway(); + cu_up_cfg.epoll_broker = epoll_broker.get(); + cu_up_cfg.gtpu_pcap = gtpu_p.get(); + cu_up_cfg.timers = cu_timers; + cu_up_cfg.qos = generate_cu_up_qos_config(gnb_cfg); // create and start CU-UP std::unique_ptr cu_up_obj = create_cu_up(cu_up_cfg); diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 833a3b0b22..90a18c778f 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -819,11 +819,11 @@ struct pcap_appconfig { /// Metrics report configuration. struct metrics_appconfig { - struct { + struct rlc_metrics { unsigned report_period = 0; // RLC report period in ms bool json_enabled = false; } rlc; - struct { + struct pdcp_metrics { unsigned report_period = 0; // PDCP report period in ms } pdcp; unsigned cu_cp_statistics_report_period = 1; // Statistics report period in seconds @@ -833,6 +833,7 @@ struct metrics_appconfig { std::string addr = "127.0.0.1"; uint16_t port = 55555; bool autostart_stdout_metrics = false; + unsigned stdout_metrics_period = 1000; // Statistics report period in milliseconds }; /// Lower physical layer thread profiles. diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index 299e45d2a7..12166cbbfc 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -223,6 +223,11 @@ static void configure_cli11_metrics_args(CLI::App& app, metrics_appconfig& metri app.add_option( "--autostart_stdout_metrics", metrics_params.autostart_stdout_metrics, "Autostart stdout metrics reporting") ->capture_default_str(); + + app.add_option("--stdout_metrics_period", + metrics_params.stdout_metrics_period, + "DU statistics report period in milliseconds. This metrics sets the console output period.") + ->capture_default_str(); } static void configure_cli11_slicing_args(CLI::App& app, s_nssai_t& slice_params) @@ -1968,11 +1973,17 @@ static void configure_cli11_hal_args(CLI::App& app, optional& con static error_type is_valid_cpu_index(unsigned cpu_idx) { - os_sched_affinity_bitmask one_cpu_mask(cpu_idx); + std::string error_message = fmt::format("Invalid CPU core selected '{}'. Valid CPU ids: {}", + cpu_idx, + os_sched_affinity_bitmask::available_cpus().get_cpu_ids()); + + os_sched_affinity_bitmask one_cpu_mask; + if (cpu_idx >= one_cpu_mask.size()) { + return error_message; + } + one_cpu_mask.set(cpu_idx); if (not one_cpu_mask.subtract(os_sched_affinity_bitmask::available_cpus()).empty()) { - return fmt::format("Invalid CPU core selected '{}'. Valid CPU ids: {}", - cpu_idx, - os_sched_affinity_bitmask::available_cpus().get_cpu_ids()); + return error_message; } return default_success_t(); } diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index 64f4e520c7..1f8ec84309 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1806,6 +1806,7 @@ scheduler_expert_config srsran::generate_scheduler_expert_config(const gnb_appco // Logging and tracing. out_cfg.log_broadcast_messages = config.log_cfg.broadcast_enabled; + out_cfg.metrics_report_period = std::chrono::milliseconds{config.metrics_cfg.stdout_metrics_period}; const error_type error = is_scheduler_expert_config_valid(out_cfg); if (!error) { diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index fc4196e57a..f6ceeb2c99 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -22,7 +22,6 @@ #include "gnb_worker_manager.h" #include "lib/du_high/du_high_executor_strategies.h" -#include "srsran/phy/upper/channel_coding/ldpc/ldpc.h" #include "srsran/ran/pdsch/pdsch_constants.h" #include "srsran/support/event_tracing.h" @@ -96,6 +95,35 @@ void worker_manager::create_prio_worker(const std::string& } } +void append_pcap_strands(std::vector& strand_list, const pcap_appconfig& pcap_cfg) +{ + using namespace execution_config_helper; + + // Default configuration for each pcap writer strand. + strand base_strand_cfg{{{"pcap_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}}}; + + // These layers have very low throughput, so no point in instantiating more than one strand. + // This means that there is no parallelization in pcap writing across these layers. + if (pcap_cfg.e2ap.enabled or pcap_cfg.f1ap.enabled or pcap_cfg.ngap.enabled or pcap_cfg.e1ap.enabled) { + strand_list.emplace_back(base_strand_cfg); + } + + if (pcap_cfg.gtpu.enabled) { + base_strand_cfg.queues[0].name = "gtpu_pcap_exec"; + strand_list.emplace_back(base_strand_cfg); + } + + if (pcap_cfg.mac.enabled) { + base_strand_cfg.queues[0].name = "mac_pcap_exec"; + strand_list.emplace_back(base_strand_cfg); + } + + if (pcap_cfg.rlc.enabled) { + base_strand_cfg.queues[0].name = "rlc_pcap_exec"; + strand_list.emplace_back(base_strand_cfg); + } +} + void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) { using namespace execution_config_helper; @@ -120,7 +148,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) {"high_prio_exec", task_priority::max}, // used for control plane and timer management. {"cu_up_strand", // used to serialize all CU-UP tasks, while CU-UP does not support multithreading. task_priority::max, - {}, // define strands below. + {}, // define CU-UP strands below. task_worker_queue_size}}, std::chrono::microseconds{100}, os_thread_realtime_priority::no_realtime(), @@ -130,21 +158,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) std::vector& cu_up_strands = non_rt_pool.executors[2].strands; // Configuration of strands for PCAP writing. These strands will use the low priority executor. - // The low priority executor will be used for PCAP writing via dedicated strands. - strand strand_cfg{{{"pcap_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}}}; - low_prio_strands.emplace_back(strand_cfg); - if (appcfg.pcap_cfg.gtpu.enabled) { - strand_cfg.queues[0].name = "gtpu_pcap_exec"; - low_prio_strands.emplace_back(strand_cfg); - } - if (appcfg.pcap_cfg.mac.enabled) { - strand_cfg.queues[0].name = "mac_pcap_exec"; - low_prio_strands.emplace_back(strand_cfg); - } - if (appcfg.pcap_cfg.rlc.enabled) { - strand_cfg.queues[0].name = "rlc_pcap_exec"; - low_prio_strands.emplace_back(strand_cfg); - } + append_pcap_strands(low_prio_strands, appcfg.pcap_cfg); // Configuration of strand for the control plane handling (CU-CP and DU-high control plane). This strand will // support two priority levels, the highest being for timer management. @@ -152,19 +166,33 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) {"ctrl_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}}}; high_prio_strands.push_back(cp_strand); + // Setup strands for the data plane of all the instantiated DUs. + // One strand per DU, each with multiple priority levels. + for (unsigned i = 0; i != nof_cells; ++i) { + high_prio_strands.push_back(strand{ + {{fmt::format("du_rb_prio_exec#{}", i), concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, + {fmt::format("du_rb_ul_exec#{}", i), concurrent_queue_policy::lockfree_mpmc, appcfg.cu_up_cfg.gtpu_queue_size}, + {fmt::format("du_rb_dl_exec#{}", i), + concurrent_queue_policy::lockfree_mpmc, + appcfg.cu_up_cfg.gtpu_queue_size}}}); + } + // Configuration of strands for user plane handling (CU-UP and DU-low user plane). Given that the CU-UP doesn't // currently support multithreading, these strands will point to a strand that interfaces with the non-RT thread pool. // Each UE strand will have three queues, one for timer management and configuration, one for DL data plane and one // for UL data plane. - const unsigned nof_up_strands = 1; // TODO: Fix, once CU-UP supports new gnb-cu exec mapper. - for (unsigned i = 0; i != nof_up_strands; ++i) { + cu_up_strands.push_back( + strand{{{"cu_up_ctrl_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, + {"cu_up_io_ul_exec", concurrent_queue_policy::lockfree_spsc, task_worker_queue_size}}}); + const unsigned nof_cu_up_ue_strands = 16; + for (unsigned i = 0; i != nof_cu_up_ue_strands; ++i) { cu_up_strands.push_back( strand{{{fmt::format("ue_up_ctrl_exec#{}", i), concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, {fmt::format("ue_up_ul_exec#{}", i), concurrent_queue_policy::lockfree_mpmc, appcfg.cu_up_cfg.gtpu_queue_size}, // TODO: Consider separate param for size of UL queue if needed. {fmt::format("ue_up_dl_exec#{}", i), - concurrent_queue_policy::lockfree_mpmc, + concurrent_queue_policy::lockfree_spsc, appcfg.cu_up_cfg.gtpu_queue_size}}}); } @@ -219,21 +247,21 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) cu_cp_exec = exec_map.at("ctrl_exec"); cu_cp_e2_exec = exec_map.at("ctrl_exec"); metrics_hub_exec = exec_map.at("ctrl_exec"); - cu_up_ctrl_exec = exec_map.at("ue_up_ctrl_exec#0"); - cu_up_ul_exec = exec_map.at("ue_up_ul_exec#0"); - cu_up_dl_exec = exec_map.at("ue_up_dl_exec#0"); - cu_up_e2_exec = exec_map.at("ue_up_ctrl_exec#0"); + cu_up_ctrl_exec = exec_map.at("cu_up_ctrl_exec"); + cu_up_io_ul_exec = exec_map.at("cu_up_io_ul_exec"); + cu_up_e2_exec = exec_map.at("cu_up_ctrl_exec"); // Create CU-UP execution mapper object. - std::vector ue_up_dl_execs(nof_up_strands, nullptr); - std::vector ue_up_ul_execs = {nof_up_strands, nullptr}; - std::vector ue_up_ctrl_execs = {nof_up_strands, nullptr}; - for (unsigned i = 0; i != nof_up_strands; ++i) { + std::vector ue_up_dl_execs(nof_cu_up_ue_strands, nullptr); + std::vector ue_up_ul_execs = {nof_cu_up_ue_strands, nullptr}; + std::vector ue_up_ctrl_execs = {nof_cu_up_ue_strands, nullptr}; + for (unsigned i = 0; i != nof_cu_up_ue_strands; ++i) { ue_up_dl_execs[i] = exec_map.at(fmt::format("ue_up_dl_exec#{}", i)); ue_up_ul_execs[i] = exec_map.at(fmt::format("ue_up_ul_exec#{}", i)); ue_up_ctrl_execs[i] = exec_map.at(fmt::format("ue_up_ctrl_exec#{}", i)); } - cu_up_exec_mapper = make_cu_up_executor_mapper(ue_up_dl_execs, ue_up_ul_execs, ue_up_ctrl_execs); + cu_up_exec_mapper = srs_cu_up::make_cu_up_executor_pool( + *exec_map.at("cu_up_ctrl_exec"), ue_up_dl_execs, ue_up_ul_execs, ue_up_ctrl_execs); // Instantiate DU-high executor mapper. du_high_executors.resize(nof_cells); @@ -245,9 +273,10 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) using exec_list = std::initializer_list; auto cell_exec_mapper = std::make_unique(exec_list{exec_map.at("cell_exec#" + cell_id_str)}, exec_list{exec_map.at("slot_exec#" + cell_id_str)}); - auto ue_exec_mapper = std::make_unique(exec_list{exec_map.at("ue_up_ctrl_exec#0")}, - exec_list{exec_map.at("ue_up_ul_exec#0")}, - exec_list{exec_map.at("ue_up_dl_exec#0")}); + auto ue_exec_mapper = + std::make_unique(exec_list{exec_map.at(fmt::format("du_rb_prio_exec#{}", i))}, + exec_list{exec_map.at(fmt::format("du_rb_ul_exec#{}", i))}, + exec_list{exec_map.at(fmt::format("du_rb_dl_exec#{}", i))}); du_item.du_high_exec_mapper = std::make_unique(std::move(cell_exec_mapper), std::move(ue_exec_mapper), *exec_map.at("ctrl_exec"), diff --git a/apps/gnb/gnb_worker_manager.h b/apps/gnb/gnb_worker_manager.h index 6ec87a3564..dcbe0c1213 100644 --- a/apps/gnb/gnb_worker_manager.h +++ b/apps/gnb/gnb_worker_manager.h @@ -50,10 +50,9 @@ struct worker_manager { /// - e1ap_cu_cp::handle_message calls cu-cp ctrl exec /// - e1ap_cu_up::handle_message calls cu-up ue exec - task_executor* cu_cp_exec = nullptr; - task_executor* cu_up_ctrl_exec = nullptr; ///< CU-UP executor for control - task_executor* cu_up_dl_exec = nullptr; ///< CU-UP executor for DL data flow - task_executor* cu_up_ul_exec = nullptr; ///< CU-UP executor for UL data flow + task_executor* cu_cp_exec = nullptr; + task_executor* cu_up_ctrl_exec = nullptr; ///< CU-UP executor for control + task_executor* cu_up_io_ul_exec = nullptr; ///< CU-UP executor for UL data flow std::vector lower_phy_tx_exec; std::vector lower_phy_rx_exec; std::vector lower_phy_dl_exec; @@ -75,7 +74,7 @@ struct worker_manager { task_executor* cu_up_e2_exec = nullptr; task_executor* metrics_hub_exec = nullptr; - std::unique_ptr cu_up_exec_mapper; + std::unique_ptr cu_up_exec_mapper; du_high_executor_mapper& get_du_high_executor_mapper(unsigned du_index); diff --git a/apps/gnb/helpers/metrics_plotter_stdout.cpp b/apps/gnb/helpers/metrics_plotter_stdout.cpp index 33f5200b70..62622be582 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.cpp +++ b/apps/gnb/helpers/metrics_plotter_stdout.cpp @@ -52,11 +52,21 @@ static std::string scaled_fmt_integer(uint64_t num) return "Invalid number"; } +static std::string scaled_time(std::chrono::microseconds t) +{ + if (t.count() < 1000) { + return fmt::format("{:>4}us", t.count()); + } + return fmt::format("{:>4}ms", std::chrono::duration_cast(t).count()); +} + static void print_header() { fmt::print("\n"); - fmt::print(" -----------------DL-----------------------|------------------UL--------------------\n"); - fmt::print(" pci rnti cqi ri mcs brate ok nok (%) dl_bs | pusch mcs brate ok nok (%) bsr\n"); + fmt::print( + " |--------------------DL---------------------|-------------------UL------------------------------\n"); + fmt::print( + " pci rnti | cqi ri mcs brate ok nok (%) dl_bs | pusch mcs brate ok nok (%) bsr ta phr\n"); } static std::string float_to_string(float f, int digits, int field_width) @@ -138,9 +148,9 @@ void metrics_plotter_stdout::report_metrics(span ue_ fmt::print("{:>4}", ue.pci); fmt::print("{:>5x}", to_value(ue.rnti)); if (!iszero(ue.cqi)) { - fmt::print(" {:>3}", int(ue.cqi)); + fmt::print(" | {:>3}", int(ue.cqi)); } else { - fmt::print(" {:>3.3}", "n/a"); + fmt::print(" | {:>3.3}", "n/a"); } fmt::print(" {:>2}", int(ue.ri)); @@ -185,6 +195,16 @@ void metrics_plotter_stdout::report_metrics(span ue_ fmt::print(" {:>3}%", 0); } fmt::print(" {}", scaled_fmt_integer(ue.bsr)); + if (ue.last_ta.has_value()) { + fmt::print("{}", scaled_time(ue.last_ta.value())); + } else { + fmt::print(" n/a"); + } + if (ue.last_phr.has_value()) { + fmt::print(" {:>4}", ue.last_phr.value()); + } else { + fmt::print(" n/a"); + } fmt::print("\n"); } diff --git a/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index f453f7dec9..3c2d2be56f 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -201,13 +201,6 @@ class byte_buffer /// Explicit copy ctor. User should use copy() method for copy assignments. explicit byte_buffer(const byte_buffer&) noexcept = default; - /// Creates a byte_buffer with content provided by a span of bytes. - byte_buffer(span bytes) - { - if (not append(bytes)) { - clear(); - } - } /// Creates a byte_buffer with contents provided by a span of bytes. static expected create(span bytes) { @@ -218,22 +211,12 @@ class byte_buffer return buf; } - /// Creates a byte_buffer with data initialized via a initializer list. - byte_buffer(std::initializer_list lst) : byte_buffer(span{lst.begin(), lst.size()}) {} /// Creates a byte_buffer with data initialized via a initializer list. static expected create(std::initializer_list lst) { return create(span(lst.begin(), lst.size())); } - /// Creates a byte_buffer with data assigned from a range of bytes. - template - byte_buffer(It other_begin, It other_end) - { - if (not append(other_begin, other_end)) { - clear(); - } - } /// Creates a byte_buffer with data assigned from a range of bytes. template static expected create(It other_begin, It other_end) @@ -251,33 +234,23 @@ class byte_buffer byte_buffer(fallback_allocation_tag tag, span other = {}) noexcept; byte_buffer(fallback_allocation_tag tag, const byte_buffer& other) noexcept; - /// Copy assignment is disabled. Use std::move, .copy() or .deep_copy() instead. + /// Copy assignment operator is disabled. Use std::move, .copy() or .deep_copy() instead. byte_buffer& operator=(const byte_buffer&) noexcept = delete; - /// Move assignment of byte_buffer. It avoids unnecessary reference counting increment. + /// Move assignment operator of byte_buffer. It avoids unnecessary reference counting increment. byte_buffer& operator=(byte_buffer&& other) noexcept = default; - /// Assignment of span of bytes. - byte_buffer& operator=(span bytes) noexcept + /// Performs a deep copy (byte by bytes) of this byte_buffer. + expected deep_copy() const { - clear(); - if (not append(bytes)) { - clear(); + if (ctrl_blk_ptr == nullptr) { + return byte_buffer{}; } - return *this; - } - /// Performs a deep copy (byte by bytes) of this byte_buffer. - /// In case of a failure an empty byte_buffer is returned. - byte_buffer deep_copy() const - { byte_buffer buf; - if (ctrl_blk_ptr != nullptr) { - for (node_t* seg = ctrl_blk_ptr->segments.head; seg != nullptr; seg = seg->next) { - if (not buf.append(span{seg->data(), seg->length()})) { - buf.clear(); - break; - } + for (node_t* seg = ctrl_blk_ptr->segments.head; seg != nullptr; seg = seg->next) { + if (not buf.append(span{seg->data(), seg->length()})) { + return default_error_t{}; } } return buf; @@ -495,7 +468,7 @@ class byte_buffer_slice byte_buffer_slice(byte_buffer_slice&&) noexcept = default; - byte_buffer_slice(span bytes) : byte_buffer_slice(byte_buffer{bytes}) {} + /// Creates a byte buffer slice from a span of bytes. static expected create(span bytes) { auto buf = byte_buffer::create(bytes); @@ -505,7 +478,7 @@ class byte_buffer_slice return byte_buffer_slice(std::move(buf.value())); } - byte_buffer_slice(std::initializer_list bytes) : byte_buffer_slice(byte_buffer{bytes}) {} + /// Creates a byte buffer slice from a list of bytes. static expected create(std::initializer_list bytes) { auto buf = byte_buffer::create(bytes); diff --git a/include/srsran/adt/byte_buffer_chain.h b/include/srsran/adt/byte_buffer_chain.h index 894e1759bf..f36e5031fc 100644 --- a/include/srsran/adt/byte_buffer_chain.h +++ b/include/srsran/adt/byte_buffer_chain.h @@ -133,6 +133,13 @@ class byte_buffer_chain buffer_offset_it_t it; }; + struct block_deleter { + void operator()(void* p); + }; + + /// Creates an empty byte_buffer_chain. + byte_buffer_chain(void* mem); + public: using value_type = uint8_t; using reference = uint8_t&; @@ -144,8 +151,7 @@ class byte_buffer_chain using const_iterator = iter_impl; /// Creates an empty byte_buffer_chain. - byte_buffer_chain(); - static expected create() { return byte_buffer_chain{}; } + static expected create(); ~byte_buffer_chain() { @@ -157,8 +163,8 @@ class byte_buffer_chain /// Default move constructor. byte_buffer_chain(byte_buffer_chain&& other) noexcept : - byte_count(std::exchange(other.byte_count, 0U)), mem_block(std::move(other.mem_block)), + byte_count(std::exchange(other.byte_count, 0U)), max_slices(std::exchange(other.max_slices, 0U)), slice_count(std::exchange(other.slice_count, 0U)), slices_ptr(std::exchange(other.slices_ptr, nullptr)) @@ -167,43 +173,32 @@ class byte_buffer_chain byte_buffer_chain(const byte_buffer_chain&) = delete; - /// Conversion from byte_buffer to byte_buffer_chain. - explicit byte_buffer_chain(byte_buffer buf_) : byte_buffer_chain() - { - bool ret = append(std::move(buf_)); - (void)ret; - } /// Creates a byte_buffer_chain from a byte_buffer. static expected create(byte_buffer buf_) { - byte_buffer_chain buf; - if (not buf.append(std::move(buf_))) { + auto buf = create(); + if (buf.is_error()) { + return default_error_t{}; + } + if (not buf.value().append(std::move(buf_))) { return default_error_t{}; } return buf; } - /// Conversion from byte_buffer_slice to byte_buffer_chain. - byte_buffer_chain(byte_buffer_slice&& buf_) : byte_buffer_chain() - { - bool ret = append(std::move(buf_)); - (void)ret; - } /// Creates a byte_buffer_chain from a byte_buffer_slice. static expected create(byte_buffer_slice buf_) { - byte_buffer_chain buf; - if (not buf.append(std::move(buf_))) { + auto buf = create(); + if (buf.is_error()) { + return default_error_t{}; + } + if (not buf.value().append(std::move(buf_))) { return default_error_t{}; } return buf; } - /// Conversion from byte_buffer with specified offset and size to byte_buffer_chain. - byte_buffer_chain(byte_buffer buf_, size_t start, size_t sz) : - byte_buffer_chain(byte_buffer_slice(std::move(buf_), start, sz)) - { - } /// Creates a byte_buffer_chain from byte_buffer with specified offset and size to byte_buffer_chain. static expected create(byte_buffer buf_, size_t start, size_t sz) { @@ -230,14 +225,12 @@ class byte_buffer_chain byte_buffer_chain& operator=(const byte_buffer_chain&) noexcept = delete; /// Performs a deep copy of this byte_buffer_chain into a byte_buffer. - /// In case of a failure an empty byte_buffer is returned. - byte_buffer deep_copy() const + expected deep_copy() const { byte_buffer buf; for (const byte_buffer_slice& slice : slices()) { if (not buf.append(slice)) { - buf.clear(); - break; + return default_error_t{}; } } return buf; @@ -388,14 +381,10 @@ class byte_buffer_chain } private: - struct block_deleter { - void operator()(void* p); - }; - - /// Total number of bytes stored in this container. - size_t byte_count = 0; /// Memory block managed by a memory pool, where the slices are stored. std::unique_ptr mem_block; + /// Total number of bytes stored in this container. + size_t byte_count = 0; /// Maximum number of byte_buffer_slices that this container can hold. size_t max_slices = 0; /// Total number of byte_buffer_slices stored in this container. diff --git a/include/srsran/cu_up/cu_up_executor_pool.h b/include/srsran/cu_up/cu_up_executor_pool.h index 1d3a3d700e..c2b7a65370 100644 --- a/include/srsran/cu_up/cu_up_executor_pool.h +++ b/include/srsran/cu_up/cu_up_executor_pool.h @@ -23,37 +23,54 @@ #pragma once #include "srsran/adt/span.h" +#include "srsran/support/async/async_task.h" #include "srsran/support/executors/task_executor.h" namespace srsran { +namespace srs_cu_up { -/// \brief Interface used to access different executors used in the CU-UP. -/// -/// Tasks dispatched to executors with the same key will be executed sequentially. -class cu_up_executor_pool +/// \brief This class holds the executors available to a given UE in the CU-UP. +class ue_executor_mapper { public: - using ptr = std::unique_ptr>; + virtual ~ue_executor_mapper() = default; - virtual ~cu_up_executor_pool() = default; + /// \brief Initiate the shutdown of the executors associated with the respective UE context. + /// \return Returns an asynchronous task that is only completed when all the UE executors finished their pending + /// tasks. + virtual async_task stop() = 0; + + /// \brief Returns the task executor appropriate for the control aspects of the UE context (e.g. timers, deletion). + virtual task_executor& ctrl_executor() = 0; - /// \brief Creates a task executor to handle UL PDUs in the user plane. + /// \brief Returns the task executor to handle UL PDUs in the user plane. /// /// The returned executor should be of low priority, but optimized for high computational loads. - virtual ptr create_ul_pdu_executor() = 0; + virtual task_executor& ul_pdu_executor() = 0; - /// \brief Creates a task executor to handle DL PDUs in the user plane. + /// \brief Returns the task executor to handle DL PDUs in the user plane. /// /// The returned executor should be of low priority, but optimized for high computational loads. - virtual ptr create_dl_pdu_executor() = 0; + virtual task_executor& dl_pdu_executor() = 0; +}; + +/// \brief Interface used to access different executors used in the CU-UP. +/// +/// Tasks dispatched to executors with the same key will be executed sequentially. +class cu_up_executor_pool +{ +public: + virtual ~cu_up_executor_pool() = default; - /// \brief Creates a task executor appropriate for the control plane. - virtual ptr create_ctrl_executor() = 0; + /// \brief Instantiate executors for a created UE in the CU-UP. + virtual std::unique_ptr create_ue_executor_mapper() = 0; }; /// \brief Creates an executor mapper for the CU-UP. -std::unique_ptr make_cu_up_executor_mapper(span dl_pdu_executors, - span ul_pdu_executors, - span ctrl_executors); +std::unique_ptr make_cu_up_executor_pool(task_executor& cu_up_main_executor, + span dl_pdu_executors, + span ul_pdu_executors, + span ctrl_executors); +} // namespace srs_cu_up } // namespace srsran \ No newline at end of file diff --git a/include/srsran/f1ap/du/f1ap_du_ue_context_update.h b/include/srsran/f1ap/du/f1ap_du_ue_context_update.h index 7e363bde5e..dbbb655e31 100644 --- a/include/srsran/f1ap/du/f1ap_du_ue_context_update.h +++ b/include/srsran/f1ap/du/f1ap_du_ue_context_update.h @@ -27,6 +27,7 @@ #include "srsran/ran/du_types.h" #include "srsran/ran/five_qi.h" #include "srsran/ran/lcid.h" +#include "srsran/ran/qos/qos_info.h" #include "srsran/ran/up_transport_layer_info.h" namespace srsran { @@ -51,10 +52,13 @@ struct f1ap_ue_context_creation_response { /// \brief DRB to be setup in the UE context. struct f1ap_drb_to_setup { - drb_id_t drb_id; - optional lcid; - drb_rlc_mode mode; - five_qi_t five_qi; + drb_id_t drb_id; + optional lcid; + drb_rlc_mode mode; + five_qi_t five_qi; + uint8_t arp_priority_level; + /// GBR flow information is present only for GBR QoS flows. See TS 38.473, clause 9.3.1.45. + optional gbr_flow_info; std::vector uluptnl_info_list; }; diff --git a/include/srsran/f1u/common/nru_message.h b/include/srsran/f1u/common/nru_message.h index 80d27e5d0d..3426240fec 100644 --- a/include/srsran/f1u/common/nru_message.h +++ b/include/srsran/f1u/common/nru_message.h @@ -46,7 +46,7 @@ struct nru_pdcp_sn_discard_block { uint8_t block_size = 0; }; -typedef static_vector nru_pdcp_sn_discard_blocks; +using nru_pdcp_sn_discard_blocks = static_vector; /// Range of consecutive NR-U SNs that have been lost. Part of NR-U DL Data Delivery Status (PDU Type 1). /// @@ -60,7 +60,7 @@ struct nru_lost_nru_sn_range { uint32_t nru_sn_end = 0; }; -typedef static_vector nru_lost_nru_sn_ranges; +using nru_lost_nru_sn_ranges = static_vector; /// NR-U DL User Data (PDU Type 0). /// @@ -145,7 +145,7 @@ struct nru_dl_message { /// NR-U UL message exchanged from node the peer node (DU) to the node holding a PDCP entity (CU-UP). struct nru_ul_message { /// Transport PDU, e.g. PDCP PDU. - byte_buffer_chain t_pdu; + optional t_pdu; /// NR-U DL Data Delivery Status. optional data_delivery_status; /// NR-U Assistance Information. diff --git a/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h b/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h index 1d249f7b29..b14c8718e7 100644 --- a/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h +++ b/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h @@ -30,6 +30,7 @@ #include "srsran/f1u/du/f1u_rx_pdu_handler.h" #include "srsran/f1u/du/f1u_tx_pdu_notifier.h" #include "srsran/ran/up_transport_layer_info.h" +#include namespace srsran { class f1u_dl_local_adapter : public srs_cu_up::f1u_tx_pdu_notifier @@ -42,12 +43,14 @@ class f1u_dl_local_adapter : public srs_cu_up::f1u_tx_pdu_notifier void attach_du_handler(srs_du::f1u_rx_pdu_handler& handler_, const up_transport_layer_info& dl_tnl_info_) { + std::unique_lock lock(handler_mutex); handler = &handler_; dl_tnl_info.emplace(dl_tnl_info_); } void detach_du_handler(const up_transport_layer_info& dl_tnl_info_) { + std::unique_lock lock(handler_mutex); if (dl_tnl_info == dl_tnl_info_) { handler = nullptr; dl_tnl_info.reset(); @@ -60,6 +63,7 @@ class f1u_dl_local_adapter : public srs_cu_up::f1u_tx_pdu_notifier void on_new_pdu(nru_dl_message msg) override { + std::unique_lock lock(handler_mutex); if (handler == nullptr) { logger.log_info("Cannot handle NR-U DL message. DU bearer does not exist."); return; @@ -69,20 +73,12 @@ class f1u_dl_local_adapter : public srs_cu_up::f1u_tx_pdu_notifier }; private: - srs_cu_up::f1u_bearer_logger logger; - srs_du::f1u_rx_pdu_handler* handler = nullptr; - optional dl_tnl_info; -}; - -class f1u_tx_delivery_local_adapter : public srs_cu_up::f1u_rx_delivery_notifier -{ -public: - void attach_du_handler(srs_du::f1u_rx_pdu_handler& handler_) { handler = &handler_; } - void on_transmit_notification(uint32_t highest_pdcp_sn) override {} - void on_delivery_notification(uint32_t highest_pdcp_sn) override {} + srs_cu_up::f1u_bearer_logger logger; -private: srs_du::f1u_rx_pdu_handler* handler = nullptr; + std::mutex handler_mutex; + + optional dl_tnl_info; }; class f1u_ul_local_adapter : public srs_du::f1u_tx_pdu_notifier @@ -92,11 +88,22 @@ class f1u_ul_local_adapter : public srs_du::f1u_tx_pdu_notifier logger("DU-F1-U", {ue_index, drb_id, dl_tnl_info}) { } - void attach_cu_handler(srs_cu_up::f1u_rx_pdu_handler& handler_) { handler = &handler_; } - void detach_cu_handler() { handler = nullptr; } + + void attach_cu_handler(srs_cu_up::f1u_rx_pdu_handler& handler_) + { + std::unique_lock lock(handler_mutex); + handler = &handler_; + } + + void detach_cu_handler() + { + std::unique_lock lock(handler_mutex); + handler = nullptr; + } void on_new_pdu(nru_ul_message msg) override { + std::unique_lock lock(handler_mutex); if (handler == nullptr) { logger.log_info("Cannot handle NR-U UL message. CU-UP bearer does not exist."); return; @@ -105,8 +112,10 @@ class f1u_ul_local_adapter : public srs_du::f1u_tx_pdu_notifier }; private: + srs_du::f1u_bearer_logger logger; + srs_cu_up::f1u_rx_pdu_handler* handler = nullptr; - srs_du::f1u_bearer_logger logger; + std::mutex handler_mutex; }; } // namespace srsran diff --git a/include/srsran/fapi/message_builders.h b/include/srsran/fapi/message_builders.h index 9892454cd9..c23e3a2bf4 100644 --- a/include/srsran/fapi/message_builders.h +++ b/include/srsran/fapi/message_builders.h @@ -84,11 +84,7 @@ class tx_precoding_and_beamforming_pdu_builder class dl_ssb_pdu_builder { public: - explicit dl_ssb_pdu_builder(dl_ssb_pdu& pdu_) : pdu(pdu_), v3(pdu_.ssb_maintenance_v3) - { - v3.ss_pbch_block_power_scaling = std::numeric_limits::min(); - v3.beta_pss_profile_sss = std::numeric_limits::min(); - } + explicit dl_ssb_pdu_builder(dl_ssb_pdu& pdu_) : pdu(pdu_), v3(pdu_.ssb_maintenance_v3) {} /// Sets the basic parameters for the fields of the SSB/PBCH PDU. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.4, in table SSB/PBCH PDU. @@ -170,39 +166,6 @@ class dl_ssb_pdu_builder return *this; } - /// Sets the SSB power information and returns a reference to the builder. - /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.4, in table SSB/PBCH PDU maintenance FAPIv3. - dl_ssb_pdu_builder& set_maintenance_v3_tx_power_info(optional power_scaling_ss_pbch_dB, - optional pss_to_sss_ratio_dB) - { - // Power scaling in SS-PBCH in hundredths of dBs. - int ss_block_power = (power_scaling_ss_pbch_dB) ? static_cast(power_scaling_ss_pbch_dB.value() * 100) : -32768; - srsran_assert(ss_block_power <= std::numeric_limits::max(), - "SS PBCH block power scaling ({}) exceeds the maximum ({}).", - ss_block_power, - std::numeric_limits::max()); - srsran_assert(ss_block_power >= std::numeric_limits::min(), - "SS PBCH block power scaling ({}) does not reach the minimum ({}).", - ss_block_power, - std::numeric_limits::min()); - v3.ss_pbch_block_power_scaling = static_cast(ss_block_power); - - // SSS to PSS ratio in thousandths of dBs. - int beta_pss = (pss_to_sss_ratio_dB) ? static_cast(pss_to_sss_ratio_dB.value() * 1000) : -32768; - srsran_assert(beta_pss <= std::numeric_limits::max(), - "PSS to SSS ratio ({}) exceeds the maximum ({}).", - beta_pss, - std::numeric_limits::max()); - srsran_assert(beta_pss >= std::numeric_limits::min(), - "PSS to SSS ratio ({}) does not reach the minimum ({}).", - beta_pss, - std::numeric_limits::min()); - - v3.beta_pss_profile_sss = static_cast(beta_pss); - - return *this; - } - /// Returns a transmission precoding and beamforming PDU builder of this SSB PDU. tx_precoding_and_beamforming_pdu_builder get_tx_precoding_and_beamforming_pdu_builder() { @@ -226,10 +189,7 @@ class dl_dci_pdu_builder dl_pdcch_pdu_parameters_v4::dci_params& pdu_v4_) : pdu(pdu_), pdu_v3(pdu_v3_), pdu_v4(pdu_v4_) { - pdu_v3.pdcch_data_power_offset_profile_sss = - std::numeric_limits::min(); - pdu_v3.pdcch_dmrs_power_offset_profile_sss = - std::numeric_limits::min(); + pdu_v3.collocated_AL16_candidate = false; } /// Sets the basic parameters for the fields of the DL DCI PDU. @@ -251,22 +211,9 @@ class dl_dci_pdu_builder /// Sets the transmission power info parameters for the fields of the DL DCI PDU. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.1, in table DL DCI PDU. - dl_dci_pdu_builder& set_tx_power_info_parameter(optional power_control_offset_ss_profile_nr_dB) + dl_dci_pdu_builder& set_tx_power_info_parameter(int power_control_offset_ss_dB) { - int value = (power_control_offset_ss_profile_nr_dB) - ? static_cast(power_control_offset_ss_profile_nr_dB.value()) - : -127; - - srsran_assert(value <= std::numeric_limits::max(), - "SS profile NR ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - srsran_assert(value >= std::numeric_limits::min(), - "SS profile NR ({}) does not reach the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu.power_control_offset_ss_profile_nr = static_cast(value); + pdu.power_control_offset_ss_profile_nr = power_control_offset_ss_dB; return *this; } @@ -280,52 +227,6 @@ class dl_dci_pdu_builder return *this; } - /// Sets the maintenance v3 DCI parameters of the PDCCH PDU. - /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.1, in table PDCCH PDU maintenance FAPIv3. - dl_dci_pdu_builder& set_maintenance_v3_dci_parameters(bool collocated_al16_candidate_present, - optional pdcch_dmrs_power_offset_profile_sss_dB, - optional pdcch_data_power_offset_profile_sss_dB) - { - pdu_v3.collocated_AL16_candidate = collocated_al16_candidate_present; - - static constexpr int USE_OTHER_FIELDS = - std::numeric_limits::min(); - - int value = (pdcch_dmrs_power_offset_profile_sss_dB) - ? static_cast(pdcch_dmrs_power_offset_profile_sss_dB.value() * 1000) - : USE_OTHER_FIELDS; - - srsran_assert(value <= std::numeric_limits::max(), - "PDCCH DMRS power offset profile SSS ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - srsran_assert(value >= std::numeric_limits::min(), - "PDCCH DMRS power offset profile SSS ({}) is under the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu_v3.pdcch_dmrs_power_offset_profile_sss = - static_cast(value); - - value = (pdcch_data_power_offset_profile_sss_dB) - ? static_cast(pdcch_data_power_offset_profile_sss_dB.value() * 1000) - : USE_OTHER_FIELDS; - - srsran_assert(value <= std::numeric_limits::max(), - "PDCCH data power offset profile SSS ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - srsran_assert(value >= std::numeric_limits::min(), - "PDCCH data power offset profile SSS ({}) is under the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu_v3.pdcch_data_power_offset_profile_sss = - static_cast(value); - - return *this; - } - /// Sets the DCI parameters of the PDCCH parameters v4. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.1, in table PDCCH PDU parameters FAPIv4. dl_dci_pdu_builder& set_parameters_v4_dci(uint16_t nid_pdcch_dmrs) @@ -608,19 +509,11 @@ class dl_pdsch_pdu_builder /// Sets the Tx Power info parameters for the fields of the PDSCH PDU. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.2, in table PDSCH PDU. - dl_pdsch_pdu_builder& set_tx_power_info_parameters(optional power_control_offset_profile_nr, - nzp_csi_rs_epre_to_ssb ss_profile_nr) + dl_pdsch_pdu_builder& set_tx_power_info_parameters(int power_control_offset, + power_control_offset_ss power_control_offset_ss) { - unsigned power_profile_nr = - power_control_offset_profile_nr ? static_cast(power_control_offset_profile_nr.value() + 8U) : 255U; - - srsran_assert(power_profile_nr <= std::numeric_limits::max(), - "Power control offset Profile NR value exceeds the maximum ({}).", - power_profile_nr); - - pdu.power_control_offset_profile_nr = static_cast(power_profile_nr); - - pdu.power_control_offset_ss_profile_nr = ss_profile_nr; + pdu.power_control_offset_profile_nr = power_control_offset; + pdu.power_control_offset_ss_profile_nr = power_control_offset_ss; return *this; } @@ -730,44 +623,6 @@ class dl_pdsch_pdu_builder return *this; } - /// Sets the maintenance v3 Tx power info parameters for the fields of the PDSCH PDU. - /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.2, in table PDSCH maintenance parameters v3. - dl_pdsch_pdu_builder& set_maintenance_v3_tx_power_info_parameters(optional dmrs_power_offset_profile_sss, - optional data_power_offset_profile_sss) - { - static constexpr int USE_OTHER_FIELDS = std::numeric_limits::min(); - - int value = (dmrs_power_offset_profile_sss) ? static_cast(dmrs_power_offset_profile_sss.value() * 1000) - : USE_OTHER_FIELDS; - - srsran_assert(value <= std::numeric_limits::max(), - "PDSCH DMRS power offset profile SSS ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - srsran_assert(value >= std::numeric_limits::min(), - "PDSCH DMRS power offset profile SSS ({}) is under the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = static_cast(value); - - value = (data_power_offset_profile_sss) ? static_cast(data_power_offset_profile_sss.value() * 1000) - : USE_OTHER_FIELDS; - - srsran_assert(value <= std::numeric_limits::max(), - "PDSCH data power offset profile SSS ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - srsran_assert(value >= std::numeric_limits::min(), - "PDSCH data power offset profile SSS ({}) is under the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu.pdsch_maintenance_v3.pdsch_data_power_offset_profile_sss = static_cast(value); - - return *this; - } - /// Sets the maintenance v3 CBG retx control parameters for the fields of the PDSCH PDU. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.2, in table PDSCH maintenance parameters v3. dl_pdsch_pdu_builder& set_maintenance_v3_cbg_tx_crtl_parameters(uint8_t max_num_cbg_per_tb) @@ -777,31 +632,6 @@ class dl_pdsch_pdu_builder return *this; } - /// Sets the PDSCH-PTRS Tx power info parameter for the fields of the PDSCH PDU. - /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.2, in table PDSCH PTRS maintenance - /// parameters v3. - dl_pdsch_pdu_builder& set_ptrs_maintenance_v3_tx_power_info_parameters(optional ptrs_power_offset_profile_sss) - { - static constexpr int USE_OTHER_FIELDS = std::numeric_limits::min(); - - int value = ptrs_power_offset_profile_sss ? static_cast(ptrs_power_offset_profile_sss.value() * 1000) - : USE_OTHER_FIELDS; - - srsran_assert(value <= std::numeric_limits::max(), - "PDSCH PTRS power offset profile SSS ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - - srsran_assert(value >= std::numeric_limits::min(), - "PDSCH PTRS power offset profile SSS ({}) is under the minimum ({}).", - value, - std::numeric_limits::min()); - - pdu.ptrs_maintenance_v3.pdsch_ptrs_power_offset_profile_sss = static_cast(value); - - return *this; - } - /// Sets the PDSCH maintenance v4 basic parameters for the fields of the PDSCH PDU. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.2, in table PDSCH maintenance FAPIv4. dl_pdsch_pdu_builder& set_maintenance_v4_basic_parameters(uint8_t coreset_rm_pattern_bitmap_by_reference_bitmap_size, @@ -888,43 +718,11 @@ class dl_csi_rs_pdu_builder /// Sets the CSI-RS PDU tx power info parameters and returns a reference to the builder. /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.3 in table CSI-RS PDU. - dl_csi_rs_pdu_builder& set_tx_power_info_parameters(optional power_control_offset_profile_nr, - nzp_csi_rs_epre_to_ssb ss_profile_nr) + dl_csi_rs_pdu_builder& set_tx_power_info_parameters(int power_control_offset, + power_control_offset_ss power_control_offset_ss) { - pdu.power_control_offset_ss_profile_nr = ss_profile_nr; - - unsigned value = (power_control_offset_profile_nr) - ? static_cast(power_control_offset_profile_nr.value() + 8U) - : std::numeric_limits::max(); - - srsran_assert(value <= std::numeric_limits::max(), - "Ratio of PDSCH EPRE to NZP CSI-RS EPRE ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - - pdu.power_control_offset_profile_nr = static_cast(value); - - return *this; - } - - /// Sets the CSI-RS PDU mainterance v3 tx power info parameters and returns a reference to the builder. - /// \note These parameters are specified in SCF-222 v4.0 section 3.4.2.3 in table CSI-RS PDU. - dl_csi_rs_pdu_builder& set_maintenance_v3_tx_power_info_parameters(optional profile_sss_dB) - { - int value = - (profile_sss_dB) ? static_cast(profile_sss_dB.value() * 1000.F) : std::numeric_limits::min(); - - srsran_assert(value <= std::numeric_limits::max(), - "Ratio of CSI-RS EPRE to SSS EPRE ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::max()); - - srsran_assert(value >= std::numeric_limits::min(), - "Ratio of CSI-RS EPRE to SSS EPRE ({}) exceeds the maximum ({}).", - value, - std::numeric_limits::min()); - - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss = static_cast(value); + pdu.power_control_offset_ss_profile_nr = power_control_offset_ss; + pdu.power_control_offset_profile_nr = power_control_offset; return *this; } diff --git a/include/srsran/fapi/messages.h b/include/srsran/fapi/messages.h index fe4af9feb9..834d43687a 100644 --- a/include/srsran/fapi/messages.h +++ b/include/srsran/fapi/messages.h @@ -112,8 +112,6 @@ struct dl_pdcch_pdu_maintenance_v3 { struct maintenance_info { uint16_t dci_index; uint8_t collocated_AL16_candidate; - int16_t pdcch_dmrs_power_offset_profile_sss; - int16_t pdcch_data_power_offset_profile_sss; }; static_vector info; @@ -159,7 +157,6 @@ struct dl_dci_pdu { uint8_t cce_index; uint8_t aggregation_level; tx_precoding_and_beamforming_pdu precoding_and_beamforming; - uint8_t beta_pdcch_1_0; int8_t power_control_offset_ss_profile_nr; dci_payload payload; // Vendor specific parameters. @@ -227,18 +224,11 @@ struct dl_pdsch_maintenance_parameters_v3 { //: TODO: determine max size of this array static_vector lte_crs_rm_pattern; static_vector csi_for_rm; - int16_t pdsch_dmrs_power_offset_profile_sss; - int16_t pdsch_data_power_offset_profile_sss; uint8_t max_num_cbg_per_tb; //: TODO: determine max size of this array. static_vector cbg_tx_information; }; -/// PDSCH PTRS maintenance parameters added in FAPIv3. -struct dl_pdsch_ptrs_maintenance_v3 { - int16_t pdsch_ptrs_power_offset_profile_sss; -}; - struct dl_pdsch_parameters_v4 { uint8_t coreset_rm_pattern_bitmap_size_by_ref; //: TODO: determine max size of this array @@ -263,11 +253,33 @@ struct dl_pdsch_codeword { enum class low_papr_dmrs_type : uint8_t { independent_cdm_group, dependent_cdm_group }; enum class resource_allocation_type : uint8_t { type_0, type_1 }; enum class vrb_to_prb_mapping_type : uint8_t { non_interleaved, interleaved_rb_size2, interleaved_rb_size4 }; -enum class nzp_csi_rs_epre_to_ssb : uint8_t { dB_minus_3, dB0, dB3, dB6, L1_use_profile_sss = 255 }; enum class inline_tb_crc_type : uint8_t { data_payload, control_message }; enum class pdsch_ref_point_type : uint8_t { point_a, subcarrier_0 }; enum class dmrs_cfg_type : uint8_t { type_1, type_2 }; +/// Power control offset SS defined as 'ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE' as per SCF-222 v4.0 +/// section 2.2.4.5. +enum class power_control_offset_ss : uint8_t { dB_minus_3, dB0, dB3, dB6 }; + +/// Converts the given value to a power control offset SS value. +inline power_control_offset_ss to_power_control_offset_ss(int value) +{ + switch (value) { + case -3: + return power_control_offset_ss::dB_minus_3; + case 0: + return power_control_offset_ss::dB0; + case 3: + return power_control_offset_ss::dB3; + case 6: + return power_control_offset_ss::dB6; + default: + srsran_assert(0, "Invalid power control offset SS '{}'", value); + break; + } + return power_control_offset_ss::dB0; +} + /// Downlink PDSCH PDU information. struct dl_pdsch_pdu { static constexpr unsigned BITMAP_SIZE = 2U; @@ -317,13 +329,12 @@ struct dl_pdsch_pdu { uint8_t nr_of_symbols; // :TODO: PTRS tx_precoding_and_beamforming_pdu precoding_and_beamforming; - uint8_t power_control_offset_profile_nr; - nzp_csi_rs_epre_to_ssb power_control_offset_ss_profile_nr; + int power_control_offset_profile_nr; + power_control_offset_ss power_control_offset_ss_profile_nr; uint8_t is_last_cb_present; inline_tb_crc_type is_inline_tb_crc; std::array dl_tb_crc_cw; dl_pdsch_maintenance_parameters_v3 pdsch_maintenance_v3; - dl_pdsch_ptrs_maintenance_v3 ptrs_maintenance_v3; // :TODO: Rel16 PDSCH params v3 dl_pdsch_parameters_v4 pdsch_parameters_v4; /// Vendor specific parameters. @@ -333,7 +344,6 @@ struct dl_pdsch_pdu { /// CSI-RS maintenance parameters added in FAPIv3. struct dl_csi_rs_maintenance_v3 { uint16_t csi_rs_pdu_index; - int16_t csi_rs_power_offset_profile_sss; }; /// Downlink CSI-RS PDU information. @@ -350,8 +360,8 @@ struct dl_csi_rs_pdu { csi_rs_cdm_type cdm_type; csi_rs_freq_density_type freq_density; uint16_t scramb_id; - uint8_t power_control_offset_profile_nr; - nzp_csi_rs_epre_to_ssb power_control_offset_ss_profile_nr; + int power_control_offset_profile_nr; + power_control_offset_ss power_control_offset_ss_profile_nr; tx_precoding_and_beamforming_pdu precoding_and_beamforming; dl_csi_rs_maintenance_v3 csi_rs_maintenance_v3; //: TODO: csi params v4 @@ -381,8 +391,6 @@ struct dl_ssb_maintenance_v3 { ssb_pattern_case case_type; subcarrier_spacing scs; uint8_t L_max; - int16_t ss_pbch_block_power_scaling; - int16_t beta_pss_profile_sss; }; /// PSS EPRE to SSS EPRE in a SS/PBCH block. diff --git a/include/srsran/instrumentation/traces/du_traces.h b/include/srsran/instrumentation/traces/du_traces.h index be3feed6bc..bed426f5c5 100644 --- a/include/srsran/instrumentation/traces/du_traces.h +++ b/include/srsran/instrumentation/traces/du_traces.h @@ -27,15 +27,22 @@ namespace srsran { /// Set to true for enabling layer 1 trace. +#ifndef SRSRAN_L1_TRACE constexpr bool L1_TRACE_ENABLED = false; +#else +constexpr bool L1_TRACE_ENABLED = true; +#endif /// Set to true for enabling layer 2 trace. +#ifndef SRSRAN_L2_TRACE constexpr bool L2_TRACE_ENABLED = false; - +#else +constexpr bool L2_TRACE_ENABLED = true; +#endif /// L1 event tracing. This tracer is used to analyze latencies in the L1 processing. extern file_event_tracer l1_tracer; /// L2 event tracing. This tracer is used to analyze latencies in the L2 processing of slot indications. extern file_event_tracer l2_tracer; -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/include/srsran/instrumentation/traces/up_traces.h b/include/srsran/instrumentation/traces/up_traces.h index a907e1fd5f..af5793828e 100644 --- a/include/srsran/instrumentation/traces/up_traces.h +++ b/include/srsran/instrumentation/traces/up_traces.h @@ -26,7 +26,12 @@ namespace srsran { +/// Set to true for enabling user-plane related traces. +#ifndef SRSRAN_UP_TRACE constexpr bool UP_TRACE_ENABLED = false; +#else +constexpr bool UP_TRACE_ENABLED = true; +#endif /// UP event tracing. This tracer is used to analyze latencies in the CU-UP/DU high processing /// of the user plane traffic. diff --git a/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h new file mode 100644 index 0000000000..f28d252fae --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/bounded_bitset.h" +#include "srsran/adt/complex.h" +#include "srsran/adt/span.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h" +#include "srsran/ran/resource_block.h" +#include "srsran/ran/subcarrier_spacing.h" + +namespace srsran { + +/// Time alignment estimator interface. +class time_alignment_estimator +{ +public: + /// \brief Maximum number of symbols that can be used for estimating the time alignment. + /// + /// It is equal to the maximum number of subcarriers that can be contained in an OFDM symbol. + static constexpr unsigned max_nof_symbols = MAX_NOF_PRBS * NOF_SUBCARRIERS_PER_RB; + + /// Default destructor. + virtual ~time_alignment_estimator() = default; + + /// \brief Estimates the time alignment from frequency domain symbols. + /// \param[in] symbols Complex frequency domain symbols. + /// \param[in] mask Distribution of the complex symbols within an OFDM symbol. + /// \param[in] scs Subcarrier spacing. + /// \return The measured time alignment. + /// \remark An assertion is triggered if the number of symbols is not equal to the number of active elements in the + /// mask. + virtual time_alignment_measurement + estimate(span symbols, bounded_bitset mask, subcarrier_spacing scs) = 0; +}; + +} // namespace srsran diff --git a/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h new file mode 100644 index 0000000000..ba8b217d55 --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/phy/generic_functions/generic_functions_factories.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h" +#include + +namespace srsran { + +/// Time alignment estimator factory interface. +class time_alignment_estimator_factory +{ +public: + /// Default destructor. + virtual ~time_alignment_estimator_factory() = default; + + /// Creates a time alignment estimator. + virtual std::unique_ptr create() = 0; +}; + +/// Creates a time alignment estimator factory based on DFT. +std::shared_ptr +create_time_alignment_estimator_dft_factory(std::shared_ptr dft_proc_factory); + +} // namespace srsran diff --git a/include/srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h b/include/srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h new file mode 100644 index 0000000000..fd5812af7e --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h @@ -0,0 +1,39 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +namespace srsran { + +/// Collects the time alignment measurement metrics. +struct time_alignment_measurement { + /// Actual time alignment measurement in seconds. + double time_alignment; + /// Time measurement resolution in seconds. + double resolution; + /// Minimum measurement. + double min; + /// Maximum measurement. + double max; +}; + +} // namespace srsran diff --git a/include/srsran/phy/upper/channel_processors/channel_processor_factories.h b/include/srsran/phy/upper/channel_processors/channel_processor_factories.h index 8c116c1049..780e8f91bd 100644 --- a/include/srsran/phy/upper/channel_processors/channel_processor_factories.h +++ b/include/srsran/phy/upper/channel_processors/channel_processor_factories.h @@ -185,7 +185,8 @@ create_pdsch_lite_processor_factory_sw(std::shared_ptr dmrs_factory); std::shared_ptr create_pdsch_processor_pool(std::shared_ptr, - unsigned max_nof_processors); + unsigned max_nof_processors, + bool blocking = false); class prach_detector_factory { diff --git a/include/srsran/phy/upper/channel_processors/pusch/factories.h b/include/srsran/phy/upper/channel_processors/pusch/factories.h index 2bb2613038..15ad50de11 100644 --- a/include/srsran/phy/upper/channel_processors/pusch/factories.h +++ b/include/srsran/phy/upper/channel_processors/pusch/factories.h @@ -110,7 +110,8 @@ std::shared_ptr create_pusch_processor_factory_sw(pusch_processor_factory_sw_configuration& config); std::shared_ptr create_pusch_processor_pool(std::shared_ptr factory, - unsigned max_nof_processors); + unsigned max_nof_processors, + bool blocking = false); class ulsch_demultiplex_factory { diff --git a/include/srsran/phy/upper/signal_processors/signal_processor_factories.h b/include/srsran/phy/upper/signal_processors/signal_processor_factories.h index 15be73c9cb..0d99fdf199 100644 --- a/include/srsran/phy/upper/signal_processors/signal_processor_factories.h +++ b/include/srsran/phy/upper/signal_processors/signal_processor_factories.h @@ -2,6 +2,7 @@ #include "port_channel_estimator_parameters.h" #include "srsran/phy/generic_functions/generic_functions_factories.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h" #include "srsran/phy/upper/sequence_generators/sequence_generator_factories.h" #include "srsran/phy/upper/signal_processors/dmrs_pbch_processor.h" #include "srsran/phy/upper/signal_processors/dmrs_pdcch_processor.h" @@ -97,7 +98,7 @@ class port_channel_estimator_factory }; std::shared_ptr -create_port_channel_estimator_factory_sw(std::shared_ptr dft_f); +create_port_channel_estimator_factory_sw(std::shared_ptr ta_estimator_factory); class pss_processor_factory { diff --git a/include/srsran/phy/upper/signal_processors/srs/formatters.h b/include/srsran/phy/upper/signal_processors/srs/formatters.h new file mode 100644 index 0000000000..387cb9ebfb --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/formatters.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_result.h" +#include "srsran/ran/srs/srs_resource_formatter.h" +#include "srsran/support/format_utils.h" + +namespace fmt { + +/// \brief Custom formatter for \c srsran::srs_estimator_configuration. +template <> +struct formatter { + /// Helper used to parse formatting options and format fields. + srsran::delimited_formatter helper; + + /// Default constructor. + formatter() = default; + + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return helper.parse(ctx); + } + + template + auto format(const srsran::srs_estimator_configuration& config, FormatContext& ctx) + -> decltype(std::declval().out()) + { + helper.format_if_verbose(ctx, "slot={}", config.slot); + helper.format_always(ctx, "{}", config.resource); + helper.format_if_verbose(ctx, "ports=[{}]", srsran::span(config.ports)); + + return ctx.out(); + } +}; + +} // namespace fmt \ No newline at end of file diff --git a/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h b/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h new file mode 100644 index 0000000000..7bbc81b056 --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +namespace srsran { + +struct srs_estimator_configuration; +struct srs_estimator_result; +class resource_grid_reader; + +/// Propagation channel estimator interface based on Sounding Reference Signals (SRS). +class srs_estimator +{ +public: + /// Default destructor. + virtual ~srs_estimator() = default; + + /// \brief Estimates the SRS propagation channel. + /// + /// \param[in] grid Received resource grid containing the SRS. + /// \param[in] config Sounding Reference Signal parameters. + /// \return The propagation channel estimation results. + virtual srs_estimator_result estimate(const resource_grid_reader& grid, + const srs_estimator_configuration& config) = 0; +}; + +} // namespace srsran \ No newline at end of file diff --git a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h new file mode 100644 index 0000000000..5edc5a017f --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/static_vector.h" +#include "srsran/ran/slot_point.h" +#include "srsran/ran/srs/srs_constants.h" +#include "srsran/ran/srs/srs_resource_configuration.h" +#include + +namespace srsran { + +/// Parameters required to receive the Sounding Reference Signals described in 3GPP TS38.211 Section 6.4.1.4. +struct srs_estimator_configuration { + /// Numerology, SFN and slot index. + slot_point slot; + /// SRS resource configuration. + srs_resource_configuration resource; + /// Receive port list. + static_vector ports; +}; + +} // namespace srsran diff --git a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h new file mode 100644 index 0000000000..11713a07b9 --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/phy/upper/sequence_generators/sequence_generator_factories.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator.h" +#include + +namespace srsran { + +/// Sounding Reference Signal propagation channel estimator factory. +class srs_estimator_factory +{ +public: + /// Default destructor. + virtual ~srs_estimator_factory() = default; + + /// Creates a Sounding Reference Signal based propagation channel estimator. + virtual std::unique_ptr create() = 0; +}; + +/// Create a generic SRS propagation channel estimator factory. +std::shared_ptr +create_srs_estimator_generic_factory(std::shared_ptr sequence_generator_factory); + +} // namespace srsran diff --git a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h new file mode 100644 index 0000000000..fe5aec745b --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h @@ -0,0 +1,40 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/ran/phy_time_unit.h" +#include "srsran/ran/srs/srs_channel_matrix.h" + +namespace srsran { + +/// Sounding Reference Signals propagation channel estimation results. +struct srs_estimator_result { + /// Wideband estimated channel matrix. + srs_channel_matrix channel_matrix; + /// Wideband measured noise variance. + float noise_variance; + /// Measured time alignment. + phy_time_unit time_align; +}; + +} // namespace srsran diff --git a/include/srsran/ran/pucch/srs_configuration.h b/include/srsran/ran/pucch/srs_configuration.h index 62e0b2c291..b9970202e3 100644 --- a/include/srsran/ran/pucch/srs_configuration.h +++ b/include/srsran/ran/pucch/srs_configuration.h @@ -28,7 +28,7 @@ namespace srsran { -/// Used to configure sounding reference signal transmissions or to configure sounding reference signal +/// Used to configure Sounding Reference Signal transmissions or to configure Sounding Reference Signal /// measurements for CLI. /// \remark See TS 38.331, "SRS-Config". struct srs_config { diff --git a/include/srsran/ran/qos/five_qi_qos_mapping.h b/include/srsran/ran/qos/five_qi_qos_mapping.h new file mode 100644 index 0000000000..511b071575 --- /dev/null +++ b/include/srsran/ran/qos/five_qi_qos_mapping.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/optional.h" +#include "srsran/ran/five_qi.h" + +namespace srsran { + +/// \brief Resource Type determines whether QoS Flow is of type Guaranteed Bit Rate (GBR), Delay-critical GBR or +/// non-GBR. See TS 23.501, clause 5.7.3.2 Resource Type. +enum class qos_flow_resource_type { gbr, non_gbr, delay_critical_gbr }; + +/// \brief Represents 5G QoS characteristics associated with 5QI. +struct qos_characteristics { + qos_flow_resource_type res_type; + /// The Priority Level associated with 5G QoS characteristics indicates a priority in scheduling resources among QoS + /// Flows. The lowest Priority Level value corresponds to the highest priority. See TS 23.501, clause 5.7.3.3. + uint8_t qos_priority_level; + /// The Packet Delay Budget (PDB) defines an upper bound for the time that a packet may be delayed between the UE and + /// the UPF that terminates the N6 interface. For a certain 5QI the value of the PDB is the same in UL and DL. See + /// TS 23.501, clause 5.7.3.4. + unsigned packet_delay_budget_ms; + /// The Packet Error Rate (PER) defines an upper bound for the rate of PDUs (e.g. IP packets) that have been processed + /// by the sender of a link layer protocol (e.g. RLC in RAN of a 3GPP access) but that are not successfully delivered + /// by the corresponding receiver to the upper layer (e.g. PDCP in RAN of a 3GPP access). Thus, the PER defines an + /// upper bound for a rate of non-congestion related packet losses. See TS 23.501, clause 5.7.3.5. + double packet_error_rate; + /// Each GBR QoS Flow shall be associated with an Averaging window. The Averaging window represents the duration over + /// which the GFBR and MFBR shall be calculated (e.g. in the (R)AN, UPF, UE). See TS 23.501, clause 5.7.3.6. + optional average_window_ms; + /// Each GBR QoS Flow with Delay-critical resource type shall be associated with a Maximum Data Burst Volume (MDBV). + /// MDBV denotes the largest amount of data that the 5G-AN is required to serve within a period of 5G-AN PDB (i.e. + /// 5G-AN part of the PDB). See TS 23.501, clause 5.7.3.7. + optional max_data_burst_volume_bytes; +}; + +/// \brief Returns the standardized 5QI to QoS characteristics mapping from TS 23.501, table 5.7.4-1 based on given 5QI. +/// \param[in] nof_layers Number of layers. +/// \return The standardized 5QI to QoS characteristics mapping from TS 23.501, table 5.7.4-1. +qos_characteristics get_5qi_to_qos_characteristics_mapping(five_qi_t five_qi); + +} // namespace srsran diff --git a/include/srsran/ran/qos/qos_info.h b/include/srsran/ran/qos/qos_info.h new file mode 100644 index 0000000000..d5cddebbb8 --- /dev/null +++ b/include/srsran/ran/qos/qos_info.h @@ -0,0 +1,45 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +namespace srsran { + +/// \brief QoS parameters for a GBR QoS flow or GBR bearer for downlink and uplink. See TS 38.473, clause 9.3.1.46. +struct gbr_qos_info_t { + /// Maximum Bit Rate in DL. + uint64_t max_flow_dl_bitrate; + /// Maximum Bit Rate in UL. + uint64_t max_flow_ul_bitrate; + /// Guaranteed Bit Rate (provided there is data to deliver) in DL. + uint64_t guaranteed_flow_dl_bitrate; + /// Guaranteed Bit Rate (provided there is data to deliver) in UL. + uint64_t guaranteed_flow_ul_bitrate; + /// Indicates the maximum rate for lost packets that can be tolerated in the DL. Expressed in ratio of lost packets + /// per number of packets sent, expressed in tenth of percent.Values {0,...,1000}. + optional max_packet_loss_rate_dl; + /// Indicates the maximum rate for lost packets that can be tolerated in the UL. Expressed in ratio of lost packets + /// per number of packets sent, expressed in tenth of percent.Values {0,...,1000}. + optional max_packet_loss_rate_ul; +}; + +} // namespace srsran diff --git a/include/srsran/ran/srs/srs_bandwidth_configuration.h b/include/srsran/ran/srs/srs_bandwidth_configuration.h index c29be4b303..9e6a18a46c 100644 --- a/include/srsran/ran/srs/srs_bandwidth_configuration.h +++ b/include/srsran/ran/srs/srs_bandwidth_configuration.h @@ -30,7 +30,7 @@ namespace srsran { /// /// The parameters are used in TS38.211 Section 6.4.1.4.3 and they are derived from TS38.211 Table 6.4.1.4.3-1. struct srs_configuration { - /// Sounding reference signal bandwidth in physical resource blocks, corresponds to the parameter \f$m_{SRS,b}\f$. + /// Sounding Reference Signal bandwidth in physical resource blocks, corresponds to the parameter \f$m_{SRS,b}\f$. unsigned m_srs; /// Number of frequency hopping locations, corresponds to parameter \f$N_{b}\f$. unsigned N; diff --git a/include/srsran/ran/srs/srs_channel_matrix.h b/include/srsran/ran/srs/srs_channel_matrix.h index 10af3027bd..abefe0e51d 100644 --- a/include/srsran/ran/srs/srs_channel_matrix.h +++ b/include/srsran/ran/srs/srs_channel_matrix.h @@ -29,6 +29,7 @@ #include "srsran/srsvec/copy.h" #include "srsran/srsvec/sc_prod.h" #include "srsran/support/srsran_assert.h" +#include #include #include @@ -60,14 +61,13 @@ class srs_channel_matrix srs_constants::max_nof_rx_ports); srsran_assert(nof_tx_ports <= srs_constants::max_nof_tx_ports, "The number of transmit ports (i.e., {}) exceeds the maximum (i.e., {}).", - nof_rx_ports, - srs_constants::max_nof_rx_ports); + nof_tx_ports, + srs_constants::max_nof_tx_ports); } /// \brief Constructs a channel matrix with the desired number of receive and transmit ports. /// - /// Creates a channel matrix with the specified dimensions, and sets its contents to the provided coefficients - /// values. + /// Creates a channel matrix with the specified dimensions, and sets its contents to the provided coefficients. /// /// \param[in] coefficients Channel coefficient list, arranged by i) receive port and ii) transmit port. /// \param[in] nof_rx_ports Number of receive ports. @@ -136,10 +136,12 @@ class srs_channel_matrix return *this; } - /// \brief Overload equality comparison operator. - /// \param[in] other Channel matrix to compare against. - /// \return \c true if both channel matrices are exactly the same, \c false otherwise. - bool operator==(const srs_channel_matrix& other) const + /// \brief Near equal comparison method. + /// \param[in] other Channel matrix to compare against. + /// \param[in] tolerance Maximum absolute error tolerated for considering two propagation channel coefficients equal. + /// \return \c true if the absolute error between both channel matrices is lower than \c tolerance, \c false + /// otherwise. + bool is_near(const srs_channel_matrix& other, float tolerance) const { unsigned nof_rx_ports = get_nof_rx_ports(); unsigned nof_tx_ports = get_nof_tx_ports(); @@ -151,9 +153,10 @@ class srs_channel_matrix return false; } - for (unsigned i_layer = 0; i_layer != nof_rx_ports; ++i_layer) { - for (unsigned i_port = 0; i_port != nof_tx_ports; ++i_port) { - if (get_coefficient(i_layer, i_port) != other.get_coefficient(i_layer, i_port)) { + for (unsigned i_rx_port = 0; i_rx_port != nof_rx_ports; ++i_rx_port) { + for (unsigned i_tx_port = 0; i_tx_port != nof_tx_ports; ++i_tx_port) { + float error = std::abs(get_coefficient(i_rx_port, i_tx_port) - other.get_coefficient(i_rx_port, i_tx_port)); + if (error > tolerance) { return false; } } @@ -162,9 +165,6 @@ class srs_channel_matrix return true; } - /// Overload inequality comparison operator. - bool operator!=(const srs_channel_matrix& other) const { return !(*this == other); } - /// Gets the current number of receive ports. unsigned get_nof_rx_ports() const { return data.get_dimension_size(dims::rx_port); } diff --git a/include/srsran/ran/srs/srs_information.h b/include/srsran/ran/srs/srs_information.h new file mode 100644 index 0000000000..2b51bd53c3 --- /dev/null +++ b/include/srsran/ran/srs/srs_information.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srs_resource_configuration.h" +namespace srsran { + +/// \brief Collects Sounding Reference Signal information. +/// +/// Contains the derived parameters that are used for the SRS sequence generation and mapping, as per TS38.211 Sections +/// 6.4.1.4.2 and 6.4.1.4.3. +/// +/// The parameters describe the sequence and its allocation for a certain transmission port and OFDM symbol. +struct srs_information { + /// Sequence length, parameter \f$M_{sc,b}^{SRS}\f$. + unsigned sequence_length; + /// Sequence group, parameter \f$u\f$. + unsigned sequence_group; + /// Sequence number, parameter \f$v\f$. + unsigned sequence_number; + /// Sequence cyclic shift, parameter \f$\alpha\f$. + float alpha; + /// First subcarrier used for mapping the sequence within the BWP, parameter \f$k_{0}^{(p_i)}\f$. + unsigned mapping_initial_subcarrier; + /// Comb size, parameter \f$K_{TC}\f$. + unsigned comb_size; +}; + +/// \brief Get Sounding Reference Signal information. +/// \param resource SRS resource configuration. +/// \param i_antenna_port Transmit antenna 0-based port index. +/// \param i_symbol OFDM symbol index within the slot. +/// \return The SRS information. +/// \remark An assertion is triggered if one or more resource parameters are invalid or not supported. +srs_information +get_srs_information(const srs_resource_configuration& resource, unsigned i_antenna_port, unsigned i_symbol); + +} // namespace srsran diff --git a/include/srsran/ran/srs/srs_resource_configuration.h b/include/srsran/ran/srs/srs_resource_configuration.h new file mode 100644 index 0000000000..705177cc77 --- /dev/null +++ b/include/srsran/ran/srs/srs_resource_configuration.h @@ -0,0 +1,137 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/bounded_integer.h" +#include "srsran/adt/optional.h" +#include "srsran/ran/srs/srs_constants.h" +#include + +namespace srsran { + +/// \brief Parameters required to receive the Sounding Reference Signals described in 3GPP TS38.211 Section 6.4.1.4. +/// +/// Higher layer parameters mentioned in this structure are contained in the 3GPP TS38.331 Section 6.3.2 Information +/// Element \e SRS-Resource. +struct srs_resource_configuration { + /// Enumeration for attributes that accept only one, two, or four. + enum class one_two_four_enum : uint8_t { one = 1, two = 2, four = 4 }; + /// Frequency hopping selection. + enum class group_or_sequence_hopping_enum : uint8_t { neither = 0, group_hopping, sequence_hopping }; + /// Enumeration for the comb size. + enum class comb_size_enum : uint8_t { two = 2, four = 4 }; + + /// Collects parameters related to the SRS transmission periodicity. + struct periodicity_and_offset { + /// Periodicity in slots, parameter \f$T_{SRS}\f$. + uint16_t periodicity; + /// Offset within the periodicity, parameter \f$T_{offset}\f$. + uint16_t offset; + }; + + /// Number of transmit antenna ports, parameter \f$N^{SRS}_{ap}\f$. + one_two_four_enum nof_antenna_ports; + /// \brief Consecutive number of OFDM symbols used for the transmission, parameter \f$N^{SRS}_{symb}\f$. + /// + /// It is given by the higher layer parameter \e nrofSymbols contained in the higher layer parameter + /// \e resourceMapping. + one_two_four_enum nof_symbols; + /// \brief Starting position in the time domain, parameter \f$l_0\f$. + /// + /// The parameter is given by \f$l_0=N^{slot}_{symb}-1-l_{offset}\f$ where the offset \f$l_0\in\{0,1,...,5\}\f$ + /// counts symbols backwards from the end of the slot and is given by the field \e startPosition contained in the + /// higher layer parameter \e resourceMapping. + /// + /// The valid range is {0...13}. + /// + /// The number of symbols plus the start symbol must not exceed the number of symbols in one slot. + bounded_integer start_symbol; + /// \brief Bandwidth configuration index, parameter \f$C_{SRS}\f$. + /// + /// It is given by the field \e c-SRS contained in the higher-layer parameter \e freqHopping. + /// + /// The valid range is {0...63}. + bounded_integer configuration_index; + /// \brief Sequence identifier to initialize the pseudo-random group and sequence hopping, parameter + /// \f$n^{SRS}_{ID}\f$. + /// + /// It is given by the higher-layer parameter \e sequenceId. + /// + /// The valid range is {0...1023}. + bounded_integer sequence_id; + /// \brief Bandwidth index, parameter \f$B_{SRS}\f$. + /// + /// It is given by the field \e b-SRS contained in the higher-layer parameter \e freqHopping. + /// + /// The valid range is {0...3}. + bounded_integer bandwidth_index; + /// \brief Comb size, parameter \f$K_{TC}\f$. + /// + /// It is given by the higher-layer field \e transmissionComb. + /// + /// Valid values are 2 and 4. + comb_size_enum comb_size; + /// \brief Comb offset, parameter \f$\bar{k}_{TC}\f$. + /// + /// It is given by the higher-layer field \e combOffset-n2 or \e combOffset-n4 contained in the parameter + /// \e transmissionComb. + /// + /// The valid range is {0...\f$K_{TC}-1\f$}. + bounded_integer comb_offset; + /// \brief Cyclic shift, parameter \f$n^{CS}_{SRS}\f$. + /// + /// It is given by the field \e cyclicShift contained in the higher-layer parameter \e transmissionComb. + /// + /// The valid range is: + /// - {0...7} if \f$K_{TC} = 2\f$; and + /// - {0...11} if \f$K_{TC} = 4\f$. + bounded_integer cyclic_shift; + /// \brief Frequency domain position, parameter \f$n_{RRC}\f$. + /// + /// It is given by the higher layer parameter \e freqDomainPosition. + /// + /// The valid range is {0...67}. + bounded_integer freq_position; + /// \brief Frequency domain shift, parameter \f$n_{shift}\f$. + /// + /// It is given by the higher layer parameter \e freqDomainShift. + /// + /// The valid range is {0...268}. + bounded_integer freq_shift; + /// \brief Frequency hopping, parameter \f$b_{hop}\f$. + /// + /// It is given by the field \e b-hop contained in the higher layer parameter \e freqHopping. + /// + /// The valid range is {0...3}. + bounded_integer freq_hopping; + /// \brief Group or sequence hopping configuration. + /// + /// It is given by the higher layer parameter \e groupOrSequenceHopping. + group_or_sequence_hopping_enum hopping; + /// \brief Set if frequency hopping is enabled and the SRS resource is either periodic or semi-persistent. + /// + /// The periodicity and offset are given by the higher layer parameter \e resourceType. + optional periodicity; +}; + +} // namespace srsran diff --git a/include/srsran/ran/srs/srs_resource_formatter.h b/include/srsran/ran/srs/srs_resource_formatter.h new file mode 100644 index 0000000000..690e4f59ad --- /dev/null +++ b/include/srsran/ran/srs/srs_resource_formatter.h @@ -0,0 +1,73 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/ran/srs/srs_resource_configuration.h" +#include "srsran/support/format_utils.h" + +namespace fmt { + +/// \brief Custom formatter for \c srsran::srs_resource_configuration. +template <> +struct formatter { + /// Helper used to parse formatting options and format fields. + srsran::delimited_formatter helper; + + /// Default constructor. + formatter() = default; + + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return helper.parse(ctx); + } + + template + auto format(const srsran::srs_resource_configuration& resource, FormatContext& ctx) + -> decltype(std::declval().out()) + { + helper.format_if_verbose(ctx, "nof_antenna_ports={}", resource.nof_antenna_ports); + helper.format_if_verbose(ctx, "nof_symbols={}", resource.nof_symbols); + helper.format_if_verbose(ctx, "start_symbol={}", resource.start_symbol); + helper.format_if_verbose(ctx, "configuration_index={}", resource.configuration_index); + helper.format_if_verbose(ctx, "sequence_id={}", resource.sequence_id); + helper.format_if_verbose(ctx, "bandwidth_index={}", resource.bandwidth_index); + helper.format_if_verbose(ctx, "comb_size={}", resource.comb_size); + helper.format_if_verbose(ctx, "comb_offset={}", resource.comb_offset); + helper.format_if_verbose(ctx, "cyclic_shift={}", resource.cyclic_shift); + helper.format_if_verbose(ctx, "freq_position={}", resource.freq_position); + helper.format_if_verbose(ctx, "freq_shift={}", resource.freq_shift); + helper.format_if_verbose(ctx, "freq_hopping={}", resource.freq_hopping); + helper.format_if_verbose(ctx, "hopping={}", resource.hopping); + if (resource.periodicity.has_value()) { + helper.format_if_verbose( + ctx, "periodicity={}/{}", resource.periodicity->periodicity, resource.periodicity->offset); + } else { + helper.format_if_verbose(ctx, "periodicity=na"); + } + + return ctx.out(); + } +}; + +} // namespace fmt \ No newline at end of file diff --git a/include/srsran/ran/tdd/tdd_ul_dl_config.h b/include/srsran/ran/tdd/tdd_ul_dl_config.h index 35d522bd85..bda1867e3e 100644 --- a/include/srsran/ran/tdd/tdd_ul_dl_config.h +++ b/include/srsran/ran/tdd/tdd_ul_dl_config.h @@ -89,10 +89,24 @@ ofdm_symbol_range get_active_tdd_dl_symbols(const tdd_ul_dl_config_common& cfg, /// \brief Calculates the number of active UL symbols in the current slot_index. ofdm_symbol_range get_active_tdd_ul_symbols(const tdd_ul_dl_config_common& cfg, unsigned slot_index, cyclic_prefix cp); +/// \brief Finds the next TDD slot index with DL symbols within the TDD period, starting from the given slot index. +/// \return The slot index, if found, or an empty optional otherwise. The case of empty optional would the case of +/// start_slot_index being past the last DL slot within the period. +optional find_next_tdd_dl_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index = 0); + +/// \brief Finds the next TDD slot index with all UL symbols, starting from the given slot index. +/// \return The slot index, if found, or an empty optional otherwise. The case of empty optional would the case of +/// start_slot_index being past the last full DL slot within the period. +optional find_next_tdd_full_dl_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index = 0); + /// \brief Finds the next TDD slot index with UL symbols, starting from the given slot index. +/// \return The slot index, if found, or an empty optional otherwise. The case of empty optional would the case of +/// start_slot_index being >= TDD period in slots. optional find_next_tdd_ul_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index = 0); /// \brief Finds the next TDD slot index with all UL symbols, starting from the given slot index. +/// \return The slot index, if found, or an empty optional otherwise. The case of empty optional would the case of +/// start_slot_index being >= TDD period in slots. optional find_next_tdd_full_ul_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index = 0); } // namespace srsran diff --git a/include/srsran/scheduler/sched_consts.h b/include/srsran/scheduler/sched_consts.h index 76f59e80be..e9a1d5b6b1 100644 --- a/include/srsran/scheduler/sched_consts.h +++ b/include/srsran/scheduler/sched_consts.h @@ -53,7 +53,10 @@ const unsigned SCHEDULER_MAX_K0 = 15; const unsigned SCHEDULER_MAX_K1 = 15; /// [Implementation defined] Maximum allowed slot offset between DCI and its scheduled first PUSCH. Values {0,..,32}. -const unsigned SCHEDULER_MAX_K2 = 15; +/// \remark As per TS 38.306, \c ul-SchedulingOffset field in \c ueCapabilityInformation indicates whether the UE +/// supports UL scheduling slot offset (K2) greater than 12. In order to support UEs not supporting k2 > 12, we restrict +/// maximum value of k2 to 12. +const unsigned SCHEDULER_MAX_K2 = 12; /// Maximum value of NTN cell specific Koffset. See TS 38.331 const unsigned NTN_CELL_SPECIFIC_KOFFSET_MAX = 512; diff --git a/include/srsran/scheduler/scheduler_configurator.h b/include/srsran/scheduler/scheduler_configurator.h index 85e141cf18..dcff799f19 100644 --- a/include/srsran/scheduler/scheduler_configurator.h +++ b/include/srsran/scheduler/scheduler_configurator.h @@ -30,6 +30,8 @@ #include "srsran/ran/pci.h" #include "srsran/ran/phy_time_unit.h" #include "srsran/ran/prach/prach_constants.h" +#include "srsran/ran/qos/five_qi_qos_mapping.h" +#include "srsran/ran/qos/qos_info.h" #include "srsran/ran/rnti.h" #include "srsran/ran/sib/sib_configuration.h" #include "srsran/ran/slot_pdu_capacity_constants.h" @@ -114,6 +116,16 @@ struct sched_ue_resource_alloc_config { unsigned max_pusch_harq_retxs = 4; }; +/// QoS parameters associated with a DRB provided to the scheduler. +struct sched_drb_qos_info { + /// Logical Channel ID. + lcid_t lcid; + /// QoS characteristics associated with the logical channel. + qos_characteristics qos_info; + /// QoS information present only for GBR QoS flows. + optional gbr_qos_info; +}; + /// Request for a new UE configuration provided to the scheduler during UE creation or reconfiguration. struct sched_ue_config_request { /// List of configured Logical Channels. See \c mac-LogicalChannelConfig, TS38.331. @@ -124,6 +136,8 @@ struct sched_ue_config_request { optional> cells; /// Resource allocation configuration for the given UE. optional res_alloc_cfg; + /// List of QoS information for DRBs. + std::vector drb_qos_list; }; /// Request to create a new UE in scheduler. diff --git a/include/srsran/scheduler/scheduler_metrics.h b/include/srsran/scheduler/scheduler_metrics.h index 03d2b80bd5..a3c26250b0 100644 --- a/include/srsran/scheduler/scheduler_metrics.h +++ b/include/srsran/scheduler/scheduler_metrics.h @@ -22,6 +22,7 @@ #pragma once +#include "srsran/adt/optional.h" #include "srsran/adt/span.h" #include "srsran/ran/pci.h" #include "srsran/ran/rnti.h" @@ -31,25 +32,27 @@ namespace srsran { /// \brief Snapshot of the metrics for a UE. struct scheduler_ue_metrics { - pci_t pci; - unsigned nof_prbs; - rnti_t rnti; - uint8_t cqi; - uint8_t ri; - sch_mcs_index dl_mcs; - double dl_prbs_used; - double dl_brate_kbps; - unsigned dl_nof_ok; - unsigned dl_nof_nok; - float pusch_snr_db; - float pucch_snr_db; - sch_mcs_index ul_mcs; - double ul_prbs_used; - double ul_brate_kbps; - unsigned ul_nof_ok; - unsigned ul_nof_nok; - unsigned bsr; - unsigned dl_bs; + pci_t pci; + unsigned nof_prbs; + rnti_t rnti; + uint8_t cqi; + uint8_t ri; + sch_mcs_index dl_mcs; + double dl_prbs_used; + double dl_brate_kbps; + unsigned dl_nof_ok; + unsigned dl_nof_nok; + float pusch_snr_db; + float pucch_snr_db; + sch_mcs_index ul_mcs; + double ul_prbs_used; + double ul_brate_kbps; + unsigned ul_nof_ok; + unsigned ul_nof_nok; + unsigned bsr; + unsigned dl_bs; + optional last_ta; + optional last_phr; }; /// \brief Notifier interface used by scheduler to report UE metrics. diff --git a/include/srsran/srsvec/unwrap.h b/include/srsran/srsvec/unwrap.h new file mode 100644 index 0000000000..24d332baf2 --- /dev/null +++ b/include/srsran/srsvec/unwrap.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/// \file +/// \brief Phase angle unwrapping declarations. + +#pragma once + +#include "srsran/adt/complex.h" +#include "srsran/adt/span.h" + +namespace srsran { +namespace srsvec { + +/// \brief Computes the unwrapped arguments (phase angles) of a list of complex numbers. +/// +/// \param[out] arguments Output list of unwrapped arguments. +/// \param[in] cplx_numbers Input list of complex numbers. +/// +/// \warning The input and output lists should have the same length. +/// \warning The memory allocated for input and output should be disjoint. +void unwrap_arguments(span arguments, span cplx_numbers); + +} // namespace srsvec +} // namespace srsran diff --git a/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h b/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h index 799ad29ab5..f6e18a2aee 100644 --- a/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h +++ b/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h @@ -22,6 +22,10 @@ #pragma once +#ifdef ENABLE_TSAN +#include "sanitizer/tsan_interface.h" +#endif + #include "cameron314/concurrentqueue.h" #include "memory_block_list.h" #include "srsran/adt/static_vector.h" @@ -167,6 +171,9 @@ class fixed_size_memory_block_pool free_memory_block_list batch; if (central_mem_cache.try_dequeue(w_ctx->consumer_token, batch)) { w_ctx->local_cache.push_back(batch); +#ifdef ENABLE_TSAN + __tsan_acquire((void*)w_ctx->local_cache.back().head); +#endif node = w_ctx->local_cache.back().try_pop(); validate_node_address(node); } @@ -189,6 +196,9 @@ class fixed_size_memory_block_pool // Push block to local cache. w_ctx->local_cache.back().push(p); +#ifdef ENABLE_TSAN + __tsan_release(p); +#endif if (w_ctx->local_cache.size() >= max_local_batches and w_ctx->local_cache.back().size() >= block_batch_size) { // Local cache is full. Rebalance by sending batches of blocks to central cache. @@ -210,7 +220,10 @@ class fixed_size_memory_block_pool } /// Get central cache current size in number of memory blocks. - size_t get_central_cache_approx_size() const { return central_mem_cache.size_approx() * block_batch_size; } + size_t get_central_cache_approx_size() const + { + return central_mem_cache.size_approx() * block_batch_size; + } /// Get thread local cache current size in number of memory blocks. size_t get_local_cache_size() { @@ -278,7 +291,10 @@ class fixed_size_memory_block_pool } /// Number of batches of memory blocks stored in the pool. - size_t nof_total_batches() const { return (nof_blocks + block_batch_size - 1) / block_batch_size; } + size_t nof_total_batches() const + { + return (nof_blocks + block_batch_size - 1) / block_batch_size; + } void validate_node_address(void* node) { diff --git a/include/srsran/support/test_utils.h b/include/srsran/support/test_utils.h index 53f5cc0666..ac0e4ce178 100644 --- a/include/srsran/support/test_utils.h +++ b/include/srsran/support/test_utils.h @@ -283,6 +283,8 @@ class test_rgen return uniform_int(std::numeric_limits::min(), std::numeric_limits::max()); } + static bool bernoulli(double p) { return std::bernoulli_distribution(p)(get()); } + /// \brief Return a vector of integers with specified size filled with random values. template static std::vector random_vector(size_t sz) diff --git a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp index b799e32091..a65b0d1ac3 100644 --- a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp +++ b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp @@ -94,7 +94,10 @@ void inter_cu_handover_target_routine::operator()( CORO_EARLY_RETURN(generate_handover_resource_allocation_response(false)); } - fill_e1ap_bearer_context_setup_request(security_cfg.value()); + if (!fill_e1ap_bearer_context_setup_request(security_cfg.value())) { + logger.warning("ue={}: \"{}\" failed to fill context at CU-UP", request.ue_index, name()); + CORO_EARLY_RETURN(generate_handover_resource_allocation_response(false)); + } // Call E1AP procedure CORO_AWAIT_VALUE(bearer_context_setup_response, @@ -260,16 +263,27 @@ inter_cu_handover_target_routine::generate_security_keys(security::security_cont return cfg; } -void inter_cu_handover_target_routine::fill_e1ap_bearer_context_setup_request(const security::sec_as_config& sec_info) +bool inter_cu_handover_target_routine::fill_e1ap_bearer_context_setup_request(const security::sec_as_config& sec_info) { bearer_context_setup_request.ue_index = request.ue_index; // security info bearer_context_setup_request.security_info.security_algorithm.ciphering_algo = sec_info.cipher_algo; bearer_context_setup_request.security_info.security_algorithm.integrity_protection_algorithm = sec_info.integ_algo; - bearer_context_setup_request.security_info.up_security_key.encryption_key = sec_info.k_enc; + auto k_enc_buffer = byte_buffer::create(sec_info.k_enc); + if (k_enc_buffer.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + return false; + } + bearer_context_setup_request.security_info.up_security_key.encryption_key = std::move(k_enc_buffer.value()); if (sec_info.k_int.has_value()) { - bearer_context_setup_request.security_info.up_security_key.integrity_protection_key = sec_info.k_int.value(); + auto k_int_buffer = byte_buffer::create(sec_info.k_int.value()); + if (k_int_buffer.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + return false; + } + bearer_context_setup_request.security_info.up_security_key.integrity_protection_key = + std::move(k_int_buffer.value()); } bearer_context_setup_request.ue_dl_aggregate_maximum_bit_rate = request.ue_aggr_max_bit_rate.ue_aggr_max_bit_rate_dl; @@ -286,6 +300,8 @@ void inter_cu_handover_target_routine::fill_e1ap_bearer_context_setup_request(co request.pdu_session_res_setup_list_ho_req, ue_manager.get_ue_config(), default_security_indication); + + return true; } void inter_cu_handover_target_routine::create_srb1() diff --git a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.h b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.h index c209d029be..3807c4cc95 100644 --- a/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.h +++ b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.h @@ -45,7 +45,7 @@ class inter_cu_handover_target_routine static const char* name() { return "Inter CU Handover Target Routine"; } private: - void fill_e1ap_bearer_context_setup_request(const security::sec_as_config& sec_info); + bool fill_e1ap_bearer_context_setup_request(const security::sec_as_config& sec_info); optional generate_security_keys(security::security_context& sec_context); void create_srb1(); ngap_handover_resource_allocation_response generate_handover_resource_allocation_response(bool success); diff --git a/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp b/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp index 7d42c4df6e..302a3ff786 100644 --- a/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp +++ b/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp @@ -118,7 +118,10 @@ void pdu_session_resource_setup_routine::operator()( // sanity check passed, decide whether we have to create a Bearer Context at the CU-UP or modify an existing one. if (next_config.initial_context_creation) { // prepare BearerContextSetupRequest - fill_e1ap_bearer_context_setup_request(bearer_context_setup_request); + if (!fill_e1ap_bearer_context_setup_request(bearer_context_setup_request)) { + logger.warning("ue={}: \"{}\" failed to fill bearer context at CU-UP", setup_msg.ue_index, name()); + CORO_EARLY_RETURN(handle_pdu_session_resource_setup_result(false)); + } // call E1AP procedure CORO_AWAIT_VALUE(bearer_context_setup_response, @@ -410,7 +413,7 @@ pdu_session_resource_setup_routine::handle_pdu_session_resource_setup_result(boo return response_msg; } -void pdu_session_resource_setup_routine::fill_e1ap_bearer_context_setup_request( +bool pdu_session_resource_setup_routine::fill_e1ap_bearer_context_setup_request( e1ap_bearer_context_setup_request& e1ap_request) { e1ap_request.ue_index = setup_msg.ue_index; @@ -418,9 +421,19 @@ void pdu_session_resource_setup_routine::fill_e1ap_bearer_context_setup_request( // security info e1ap_request.security_info.security_algorithm.ciphering_algo = security_cfg.cipher_algo; e1ap_request.security_info.security_algorithm.integrity_protection_algorithm = security_cfg.integ_algo; - e1ap_request.security_info.up_security_key.encryption_key = security_cfg.k_enc; + auto k_enc_buffer = byte_buffer::create(security_cfg.k_enc); + if (k_enc_buffer.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + return false; + } + e1ap_request.security_info.up_security_key.encryption_key = std::move(k_enc_buffer.value()); if (security_cfg.k_int.has_value()) { - e1ap_request.security_info.up_security_key.integrity_protection_key = security_cfg.k_int.value(); + auto k_int_buffer = byte_buffer::create(security_cfg.k_int.value()); + if (k_int_buffer.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + return false; + } + e1ap_request.security_info.up_security_key.integrity_protection_key = std::move(k_int_buffer.value()); } e1ap_request.ue_dl_aggregate_maximum_bit_rate = setup_msg.ue_aggregate_maximum_bit_rate_dl; @@ -437,6 +450,8 @@ void pdu_session_resource_setup_routine::fill_e1ap_bearer_context_setup_request( setup_msg.pdu_session_res_setup_items, ue_cfg, default_security_indication); + + return true; } // Helper to fill a Bearer Context Modification request if it is the initial E1AP message diff --git a/lib/cu_cp/routines/pdu_session_resource_setup_routine.h b/lib/cu_cp/routines/pdu_session_resource_setup_routine.h index a0d6e98287..717498f3c7 100644 --- a/lib/cu_cp/routines/pdu_session_resource_setup_routine.h +++ b/lib/cu_cp/routines/pdu_session_resource_setup_routine.h @@ -64,7 +64,7 @@ class pdu_session_resource_setup_routine static const char* name() { return "PDU Session Resource Setup Routine"; } private: - void fill_e1ap_bearer_context_setup_request(e1ap_bearer_context_setup_request& e1ap_request); + bool fill_e1ap_bearer_context_setup_request(e1ap_bearer_context_setup_request& e1ap_request); void fill_initial_e1ap_bearer_context_modification_request(e1ap_bearer_context_modification_request& e1ap_request); cu_cp_pdu_session_resource_setup_response handle_pdu_session_resource_setup_result(bool success); diff --git a/lib/cu_up/CMakeLists.txt b/lib/cu_up/CMakeLists.txt index dc3819b53c..bc7aa7ae30 100644 --- a/lib/cu_up/CMakeLists.txt +++ b/lib/cu_up/CMakeLists.txt @@ -19,7 +19,7 @@ # set(SOURCES - cu_up_executor_mapper.cpp + cu_up_executor_pool.cpp cu_up_factory.cpp cu_up_impl.cpp ue_manager.cpp diff --git a/lib/cu_up/cu_up_executor_mapper.cpp b/lib/cu_up/cu_up_executor_mapper.cpp deleted file mode 100644 index 39a65b77ed..0000000000 --- a/lib/cu_up/cu_up_executor_mapper.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright 2021-2024 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "srsran/cu_up/cu_up_executor_pool.h" - -using namespace srsran; - -class cu_up_executor_mapper_impl : public cu_up_executor_pool -{ -public: - cu_up_executor_mapper_impl(span dl_executors, - span ul_executors, - span ctrl_executors) - { - dl_execs.assign(dl_executors.begin(), dl_executors.end()); - ul_execs.assign(ul_executors.begin(), ul_executors.end()); - ctrl_execs.assign(ctrl_executors.begin(), ctrl_executors.end()); - } - - ptr create_dl_pdu_executor() override - { - return {dl_execs[round_robin_dl_index.fetch_add(1, std::memory_order_relaxed) % dl_execs.size()], - [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } - - ptr create_ul_pdu_executor() override - { - return {ul_execs[round_robin_ul_index.fetch_add(1, std::memory_order_relaxed) % ul_execs.size()], - [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } - - ptr create_ctrl_executor() override - { - return {ctrl_execs[round_robin_ctrl_index.fetch_add(1, std::memory_order_relaxed) % ctrl_execs.size()], - [this](task_executor* p) { - if (p != nullptr) { - dealloc_ctrl_executor(p); - } - }}; - } - -private: - void dealloc_pdu_executor(task_executor* exec) - { - // do nothing. - } - void dealloc_ctrl_executor(task_executor* exec) - { - // do nothing. - } - - std::vector dl_execs; - std::vector ul_execs; - std::vector ctrl_execs; - - std::atomic round_robin_dl_index{0}; - std::atomic round_robin_ul_index{0}; - std::atomic round_robin_ctrl_index{0}; -}; - -std::unique_ptr srsran::make_cu_up_executor_mapper(span dl_executors, - span ul_executors, - span ctrl_executors) -{ - return std::make_unique(dl_executors, ul_executors, ctrl_executors); -} diff --git a/lib/cu_up/cu_up_executor_pool.cpp b/lib/cu_up/cu_up_executor_pool.cpp new file mode 100644 index 0000000000..95a7e9f894 --- /dev/null +++ b/lib/cu_up/cu_up_executor_pool.cpp @@ -0,0 +1,155 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsran/cu_up/cu_up_executor_pool.h" +#include "srsran/support/async/execute_on.h" + +using namespace srsran; +using namespace srs_cu_up; + +class cu_up_executor_pool_impl final : public cu_up_executor_pool +{ + struct ue_executor_context { + task_executor& ctrl_exec; + task_executor& ul_exec; + task_executor& dl_exec; + + ue_executor_context(task_executor& ctrl_exec_, task_executor& ul_exec_, task_executor& dl_exec_) : + ctrl_exec(ctrl_exec_), ul_exec(ul_exec_), dl_exec(dl_exec_) + { + } + }; + +public: + /// Implementation of the UE executor mapper. + class ue_executor_mapper_impl final : public ue_executor_mapper + { + public: + ue_executor_mapper_impl(cu_up_executor_pool_impl& parent_, ue_executor_context& ctxt_) : + parent(parent_), ctxt(&ctxt_) + { + } + + ~ue_executor_mapper_impl() override { parent.release_ue_executors(*ctxt); } + + async_task stop() override + { + ue_executor_context* ctxt_tmp = nullptr; + return launch_async([this, ctxt_tmp](coro_context>& ctx) mutable { + CORO_BEGIN(ctx); + + // Switch to the UE execution context. + CORO_AWAIT(defer_to(ctxt->ctrl_exec)); + + // Make executors inaccessible via the ue_executor_mapper_impl public interface. + // Any public access after this point should assert. + ctxt_tmp = std::exchange(ctxt, nullptr); + + // Synchronize with remaining executors to ensure there are no more pending tasks for this UE. + CORO_AWAIT(defer_to(ctxt_tmp->ul_exec)); + CORO_AWAIT(defer_to(ctxt_tmp->dl_exec)); + + // Return back to main control execution context. + CORO_AWAIT(execute_on(parent.main_exec)); + + // Finally, deregister UE executors. + parent.release_ue_executors(*ctxt_tmp); + + CORO_RETURN(); + }); + } + + task_executor& ctrl_executor() override + { + srsran_assert(ctxt != nullptr, "UE executor mapper already stopped"); + return ctxt->ctrl_exec; + } + task_executor& ul_pdu_executor() override + { + srsran_assert(ctxt != nullptr, "UE executor mapper already stopped"); + return ctxt->ul_exec; + } + task_executor& dl_pdu_executor() override + { + srsran_assert(ctxt != nullptr, "UE executor mapper already stopped"); + return ctxt->dl_exec; + } + + private: + cu_up_executor_pool_impl& parent; + ue_executor_context* ctxt; + }; + + cu_up_executor_pool_impl(task_executor& cu_up_main_exec, + span dl_executors, + span ul_executors, + span ctrl_executors) : + main_exec(cu_up_main_exec) + { + srsran_assert(ctrl_executors.size() > 0, "At least one DL executor must be specified"); + if (dl_executors.empty()) { + dl_executors = ctrl_executors; + } else { + srsran_assert(dl_executors.size() == ctrl_executors.size(), + "If specified, the number of DL executors must be equal to the number of control executors"); + } + if (ul_executors.empty()) { + ul_executors = ctrl_executors; + } else { + srsran_assert(ul_executors.size() == ctrl_executors.size(), + "If specified, the number of UL executors must be equal to the number of control executors"); + } + + for (unsigned i = 0; i != ctrl_executors.size(); ++i) { + execs.emplace_back(*ctrl_executors[i], *ul_executors[i], *dl_executors[i]); + } + } + + std::unique_ptr create_ue_executor_mapper() override + { + return std::make_unique( + *this, execs[round_robin_index.fetch_add(1, std::memory_order_relaxed) % execs.size()]); + } + +private: + void release_ue_executors(ue_executor_context& ue_execs) + { + // do nothing. + } + + // Main executor of the CU-UP. + task_executor& main_exec; + + // List of UE executor mapper contexts created. + std::vector execs; + + std::atomic round_robin_index{0}; +}; + +std::unique_ptr srsran::srs_cu_up::make_cu_up_executor_pool(task_executor& cu_up_main_executor, + span dl_pdu_executors, + span ul_pdu_executors, + span ctrl_executors) +{ + return std::make_unique( + cu_up_main_executor, dl_pdu_executors, ul_pdu_executors, ctrl_executors); +} diff --git a/lib/cu_up/cu_up_impl.cpp b/lib/cu_up/cu_up_impl.cpp index 57bf6f0112..643926ece0 100644 --- a/lib/cu_up/cu_up_impl.cpp +++ b/lib/cu_up/cu_up_impl.cpp @@ -68,15 +68,16 @@ cu_up::cu_up(const cu_up_configuration& config_) : cfg(config_), main_ctrl_loop( demux_msg.gtpu_pcap = cfg.gtpu_pcap; ngu_demux = create_gtpu_demux(demux_msg); - dl_exec = cfg.ue_exec_pool->create_dl_pdu_executor(); - report_error_if_not(dl_exec != nullptr, "Could not create CU-UP executor for control TEID"); + ctrl_exec_mapper = cfg.ue_exec_pool->create_ue_executor_mapper(); + report_error_if_not(ctrl_exec_mapper != nullptr, "Could not create CU-UP executor for control TEID"); // Create GTP-U echo and register it at demux gtpu_echo_creation_message ngu_echo_msg = {}; ngu_echo_msg.gtpu_pcap = cfg.gtpu_pcap; ngu_echo_msg.tx_upper = >pu_gw_adapter; ngu_echo = create_gtpu_echo(ngu_echo_msg); - ngu_demux->add_tunnel(GTPU_PATH_MANAGEMENT_TEID, *dl_exec, ngu_echo->get_rx_upper_layer_interface()); + ngu_demux->add_tunnel( + GTPU_PATH_MANAGEMENT_TEID, ctrl_exec_mapper->dl_pdu_executor(), ngu_echo->get_rx_upper_layer_interface()); // Connect layers gw_data_gtpu_demux_adapter.connect_gtpu_demux(*ngu_demux); diff --git a/lib/cu_up/cu_up_impl.h b/lib/cu_up/cu_up_impl.h index 15f53cc507..bf9a880090 100644 --- a/lib/cu_up/cu_up_impl.h +++ b/lib/cu_up/cu_up_impl.h @@ -44,7 +44,7 @@ class cu_up final : public cu_up_interface { public: explicit cu_up(const cu_up_configuration& cfg_); - ~cu_up(); + ~cu_up() override; // cu_up_interface void start() override; @@ -80,7 +80,7 @@ class cu_up final : public cu_up_interface srslog::basic_logger& logger = srslog::fetch_basic_logger("CU-UP", false); // Holds DL executor for the control TEID. - std::unique_ptr> dl_exec; + std::unique_ptr ctrl_exec_mapper; // Components std::atomic e1ap_connected = {false}; diff --git a/lib/cu_up/ue_context.h b/lib/cu_up/ue_context.h index 3f46ec0f18..b24439b6e3 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -47,22 +47,20 @@ struct ue_context_cfg { class ue_context : public pdu_session_manager_ctrl { public: - ue_context(ue_index_t index_, - ue_context_cfg cfg_, - e1ap_control_message_handler& e1ap_, - network_interface_config& net_config_, - n3_interface_config& n3_config_, - std::unique_ptr> ue_dl_exec_, - std::unique_ptr> ue_ul_exec_, - std::unique_ptr> ue_ctrl_exec_, - timer_factory ue_dl_timer_factory_, - timer_factory ue_ul_timer_factory_, - timer_factory ue_ctrl_timer_factory_, - f1u_cu_up_gateway& f1u_gw_, - gtpu_teid_pool& f1u_teid_allocator_, - gtpu_tunnel_tx_upper_layer_notifier& gtpu_tx_notifier_, - gtpu_demux_ctrl& gtpu_rx_demux_, - dlt_pcap& gtpu_pcap) : + ue_context(ue_index_t index_, + ue_context_cfg cfg_, + e1ap_control_message_handler& e1ap_, + network_interface_config& net_config_, + n3_interface_config& n3_config_, + std::unique_ptr ue_exec_mapper_, + timer_factory ue_dl_timer_factory_, + timer_factory ue_ul_timer_factory_, + timer_factory ue_ctrl_timer_factory_, + f1u_cu_up_gateway& f1u_gw_, + gtpu_teid_pool& f1u_teid_allocator_, + gtpu_tunnel_tx_upper_layer_notifier& gtpu_tx_notifier_, + gtpu_demux_ctrl& gtpu_rx_demux_, + dlt_pcap& gtpu_pcap) : index(index_), cfg(std::move(cfg_)), logger("CU-UP", {index_}), @@ -81,13 +79,11 @@ class ue_context : public pdu_session_manager_ctrl f1u_teid_allocator_, gtpu_tx_notifier_, gtpu_rx_demux_, - *ue_dl_exec_, - *ue_ul_exec_, - *ue_ctrl_exec_, + ue_exec_mapper_->dl_pdu_executor(), + ue_exec_mapper_->ul_pdu_executor(), + ue_exec_mapper_->ctrl_executor(), gtpu_pcap), - ue_dl_exec(std::move(ue_dl_exec_)), - ue_ul_exec(std::move(ue_ul_exec_)), - ue_ctrl_exec(std::move(ue_ctrl_exec_)), + ue_exec_mapper(std::move(ue_exec_mapper_)), ue_dl_timer_factory(ue_dl_timer_factory_), ue_ul_timer_factory(ue_ul_timer_factory_), ue_ctrl_timer_factory(ue_ctrl_timer_factory_) @@ -105,6 +101,8 @@ class ue_context : public pdu_session_manager_ctrl } ~ue_context() override = default; + async_task stop() { return ue_exec_mapper->stop(); } + // pdu_session_manager_ctrl pdu_session_setup_result setup_pdu_session(const e1ap_pdu_session_res_to_setup_item& session) override { @@ -134,9 +132,7 @@ class ue_context : public pdu_session_manager_ctrl e1ap_control_message_handler& e1ap; pdu_session_manager_impl pdu_session_manager; - std::unique_ptr> ue_dl_exec; - std::unique_ptr> ue_ul_exec; - std::unique_ptr> ue_ctrl_exec; + std::unique_ptr ue_exec_mapper; timer_factory ue_dl_timer_factory; timer_factory ue_ul_timer_factory; @@ -154,7 +150,7 @@ class ue_context : public pdu_session_manager_ctrl e1ap.handle_bearer_context_inactivity_notification(msg); }; - if (!ue_ctrl_exec->execute(std::move(fn))) { + if (!ue_exec_mapper->ctrl_executor().execute(std::move(fn))) { logger.log_warning("Could not handle expired UE inactivity handler, queue is full. ue={}", index); } } diff --git a/lib/cu_up/ue_manager.cpp b/lib/cu_up/ue_manager.cpp index a0523881bf..f84d16b182 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -46,7 +46,8 @@ ue_manager::ue_manager(network_interface_config& net_config_, exec_pool(exec_pool_), gtpu_pcap(gtpu_pcap_), timers(timers_), - logger(logger_) + logger(logger_), + task_sched(MAX_NOF_UES) { } @@ -72,14 +73,12 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) // Create UE executors // TODO, these should be created within the same function, so that UL, DL and CTRL executors // can point to the same executor. - std::unique_ptr> ue_dl_exec = exec_pool.create_dl_pdu_executor(); - std::unique_ptr> ue_ul_exec = exec_pool.create_ul_pdu_executor(); - std::unique_ptr> ue_ctrl_exec = exec_pool.create_ctrl_executor(); + std::unique_ptr ue_exec_mapper = exec_pool.create_ue_executor_mapper(); // Create executor-specific timer factories - timer_factory ue_dl_timer_factory = {timers, *ue_dl_exec}; - timer_factory ue_ul_timer_factory = {timers, *ue_ul_exec}; - timer_factory ue_ctrl_timer_factory = {timers, *ue_ctrl_exec}; + timer_factory ue_dl_timer_factory = {timers, ue_exec_mapper->dl_pdu_executor()}; + timer_factory ue_ul_timer_factory = {timers, ue_exec_mapper->ul_pdu_executor()}; + timer_factory ue_ctrl_timer_factory = {timers, ue_exec_mapper->ctrl_executor()}; // Create UE object std::unique_ptr new_ctx = std::make_unique(new_idx, @@ -87,9 +86,7 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) e1ap, net_config, n3_config, - std::move(ue_dl_exec), - std::move(ue_ul_exec), - std::move(ue_ctrl_exec), + std::move(ue_exec_mapper), ue_dl_timer_factory, ue_ul_timer_factory, ue_ctrl_timer_factory, @@ -106,15 +103,24 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) void ue_manager::remove_ue(ue_index_t ue_index) { - logger.debug("Scheduling ue_index={} deletion", 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 - // remove UE from database - ue_db.erase(ue_index); + task_sched.schedule([this, ue_index](coro_context>& ctx) { + CORO_BEGIN(ctx); - logger.info("Removed ue_index={}", ue_index); + // 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(); + }); } 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 f45f6131e4..6a98678d5f 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -26,6 +26,7 @@ #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" namespace srsran { @@ -72,6 +73,8 @@ class ue_manager : public ue_manager_ctrl timer_manager& timers; ue_db_t ue_db; srslog::basic_logger& logger; + + fifo_async_task_scheduler task_sched; }; } // namespace srs_cu_up diff --git a/lib/du_high/adapters/mac_test_mode_adapter.cpp b/lib/du_high/adapters/mac_test_mode_adapter.cpp index a2f007b1a9..6ab9bb3c9c 100644 --- a/lib/du_high/adapters/mac_test_mode_adapter.cpp +++ b/lib/du_high/adapters/mac_test_mode_adapter.cpp @@ -27,6 +27,7 @@ #include "srsran/ran/csi_report/csi_report_on_pucch_helpers.h" #include "srsran/scheduler/harq_id.h" #include +#include using namespace srsran; @@ -34,7 +35,7 @@ using namespace srsran; // the largest TB possible. static const unsigned TEST_UE_DL_BUFFER_STATE_UPDATE_SIZE = 10000000; -static mac_rx_data_indication create_test_pdu_with_bsr(slot_point sl_rx, rnti_t test_rnti, harq_id_t harq_id) +static expected create_test_pdu_with_bsr(slot_point sl_rx, rnti_t test_rnti, harq_id_t harq_id) { // - 8-bit R/LCID MAC subheader. // - MAC CE with Long BSR. @@ -46,9 +47,12 @@ static mac_rx_data_indication create_test_pdu_with_bsr(slot_point sl_rx, rnti_t // | Buffer Size 1 | Octet 4 // We pass BSR=254, which according to TS38.321 is the maximum value for the LBSR size. - return mac_rx_data_indication{sl_rx, - to_du_cell_index(0), - mac_rx_pdu_list{mac_rx_pdu{test_rnti, 0, harq_id, byte_buffer{0x3e, 0x02, 0x01, 254}}}}; + auto buf = byte_buffer::create({0x3e, 0x02, 0x01, 254}); + if (buf.is_error()) { + return default_error_t{}; + } + return mac_rx_data_indication{ + sl_rx, to_du_cell_index(0), mac_rx_pdu_list{mac_rx_pdu{test_rnti, 0, harq_id, std::move(buf.value())}}}; } /// \brief Adapter for the MAC SDU TX builder that auto fills the DL buffer state update. @@ -88,7 +92,7 @@ mac_test_mode_cell_adapter::mac_test_mode_cell_adapter(const srs_du::du_test_con pdu_handler(pdu_handler_), slot_handler(slot_handler_), result_notifier(result_notifier_), - dl_bs_notifier(dl_bs_notifier_), + dl_bs_notifier(std::move(dl_bs_notifier_)), logger(srslog::fetch_basic_logger("MAC")), ue_info_mgr(ue_info_mgr_) { @@ -277,7 +281,7 @@ static bool pucch_info_and_uci_ind_match(const pucch_info& pucch, const mac_uci_ } if (pucch.format == pucch_format::FORMAT_1 and variant_holds_alternative(uci_ind.pdu)) { - auto& f1_ind = variant_get(uci_ind.pdu); + const auto& f1_ind = variant_get(uci_ind.pdu); if (f1_ind.sr_info.has_value() != (pucch.format_1.sr_bits != sr_nof_bits::no_sr)) { return false; } @@ -288,7 +292,7 @@ static bool pucch_info_and_uci_ind_match(const pucch_info& pucch, const mac_uci_ } if (pucch.format == pucch_format::FORMAT_2 and variant_holds_alternative(uci_ind.pdu)) { - auto& f2_ind = variant_get(uci_ind.pdu); + const auto& f2_ind = variant_get(uci_ind.pdu); if (f2_ind.sr_info.has_value() != (pucch.format_2.sr_bits != sr_nof_bits::no_sr)) { return false; } @@ -315,7 +319,7 @@ void mac_test_mode_cell_adapter::forward_uci_ind_to_mac(const mac_uci_indication // Update buffer states. for (const mac_uci_pdu& pdu : uci_msg.ucis) { if (ue_info_mgr.is_test_ue(pdu.rnti) and variant_holds_alternative(pdu.pdu)) { - auto& f1_ind = variant_get(pdu.pdu); + const auto& f1_ind = variant_get(pdu.pdu); if (f1_ind.harq_info.has_value()) { // In case of PUCCH F1 with HARQ-ACK bits, we assume that the Msg4 has been received. At this point, we @@ -327,8 +331,13 @@ void mac_test_mode_cell_adapter::forward_uci_ind_to_mac(const mac_uci_indication } if (test_ue_cfg.pusch_active) { + auto rx_pdu = create_test_pdu_with_bsr(uci_msg.sl_rx, pdu.rnti, to_harq_id(0)); + if (rx_pdu.is_error()) { + logger.warning("Unable to create test PDU with BSR"); + continue; + } // In case of PUSCH test mode is enabled, push a BSR to trigger the first PUSCH. - pdu_handler.handle_rx_data_indication(create_test_pdu_with_bsr(uci_msg.sl_rx, pdu.rnti, to_harq_id(0))); + pdu_handler.handle_rx_data_indication(std::move(rx_pdu.value())); } ue_info_mgr.msg4_rxed(pdu.rnti, true); } @@ -355,8 +364,13 @@ void mac_test_mode_cell_adapter::forward_crc_ind_to_mac(const mac_crc_indication continue; } + auto rx_pdu = create_test_pdu_with_bsr(crc_msg.sl_rx, pdu.rnti, to_harq_id(pdu.harq_id)); + if (rx_pdu.is_error()) { + logger.warning("Unable to create test PDU with BSR"); + continue; + } // In case of test mode UE, auto-forward a positive BSR. - pdu_handler.handle_rx_data_indication(create_test_pdu_with_bsr(crc_msg.sl_rx, pdu.rnti, to_harq_id(pdu.harq_id))); + pdu_handler.handle_rx_data_indication(std::move(rx_pdu.value())); } } diff --git a/lib/du_high/du_high_impl.cpp b/lib/du_high/du_high_impl.cpp index f7bea4c661..d9d8e0c001 100644 --- a/lib/du_high/du_high_impl.cpp +++ b/lib/du_high/du_high_impl.cpp @@ -177,14 +177,16 @@ void du_high_impl::start() // If test mode is enabled, create a test-mode UE by injecting a Msg3. if (cfg.test_cfg.test_ue.has_value()) { // Push an UL-CCCH message that will trigger the creation of a UE for testing purposes. - for (auto ue_num = 0; ue_num < cfg.test_cfg.test_ue->nof_ues; ++ue_num) { - mac->get_pdu_handler().handle_rx_data_indication( - mac_rx_data_indication{slot_point{0, 0}, - to_du_cell_index(0), - {mac_rx_pdu{to_rnti(to_value(cfg.test_cfg.test_ue->rnti) + ue_num), - 0, - 0, - {0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}}}}); + for (unsigned ue_num = 0, nof_ues = cfg.test_cfg.test_ue->nof_ues; ue_num != nof_ues; ++ue_num) { + auto rx_buf = byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}); + if (rx_buf.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + continue; + } + mac->get_pdu_handler().handle_rx_data_indication(mac_rx_data_indication{ + slot_point{0, 0}, + to_du_cell_index(0), + {mac_rx_pdu{to_rnti(to_value(cfg.test_cfg.test_ue->rnti) + ue_num), 0, 0, std::move(rx_buf.value())}}}); } } } diff --git a/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index 028d1201a3..9c5a9a672c 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -110,6 +110,9 @@ 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_cfg.drb_qos_list.emplace_back(sched_drb_qos_info{ + .lcid = bearer.second->lcid, .qos_info = bearer.second->qos_info, .gbr_qos_info = bearer.second->gbr_qos_info}); } return sched_cfg; diff --git a/lib/du_manager/du_ue/du_bearer.cpp b/lib/du_manager/du_ue/du_bearer.cpp index 4b6282abd0..93955cbceb 100644 --- a/lib/du_manager/du_ue/du_bearer.cpp +++ b/lib/du_manager/du_ue/du_bearer.cpp @@ -107,6 +107,7 @@ void du_drb_connector::disconnect() // Disconnect MAC <-> RLC interface. mac_rx_sdu_notifier.disconnect(); rlc_tx_buffer_state_notif.disconnect(); + mac_tx_sdu_notifier.disconnect(); } void du_ue_drb::stop() @@ -125,7 +126,9 @@ std::unique_ptr srsran::srs_du::create_drb(du_ue_index_t span uluptnl_info_list, gtpu_teid_pool& teid_pool, const du_manager_params& du_params, - rlc_tx_upper_layer_control_notifier& rlc_rlf_notifier) + rlc_tx_upper_layer_control_notifier& rlc_rlf_notifier, + const qos_characteristics& qos_info, + optional gbr_qos_info) { srsran_assert(not is_srb(lcid), "Invalid DRB LCID={}", lcid); srsran_assert(not uluptnl_info_list.empty(), "Invalid UP TNL Info list"); @@ -144,11 +147,13 @@ std::unique_ptr srsran::srs_du::create_drb(du_ue_index_t std::unique_ptr drb = std::make_unique(); // > Setup DRB config - drb->drb_id = drb_id; - drb->lcid = lcid; - drb->rlc_cfg = rlc_cfg; - drb->f1u_cfg = f1u_cfg; - drb->mac_cfg = mac_cfg; + drb->drb_id = drb_id; + drb->lcid = lcid; + drb->rlc_cfg = rlc_cfg; + drb->f1u_cfg = f1u_cfg; + drb->mac_cfg = mac_cfg; + drb->qos_info = qos_info; + drb->gbr_qos_info = gbr_qos_info; drb->uluptnl_info_list.assign(uluptnl_info_list.begin(), uluptnl_info_list.end()); drb->dluptnl_info_list.assign(dluptnl_info_list.begin(), dluptnl_info_list.end()); diff --git a/lib/du_manager/du_ue/du_bearer.h b/lib/du_manager/du_ue/du_bearer.h index 53ccf2fd27..97b75f1ce8 100644 --- a/lib/du_manager/du_ue/du_bearer.h +++ b/lib/du_manager/du_ue/du_bearer.h @@ -28,6 +28,8 @@ #include "srsran/f1u/du/f1u_config.h" #include "srsran/mac/mac_lc_config.h" #include "srsran/ran/lcid.h" +#include "srsran/ran/qos/five_qi_qos_mapping.h" +#include "srsran/ran/qos/qos_info.h" #include "srsran/ran/up_transport_layer_info.h" #include "srsran/rlc/rlc_config.h" #include "srsran/rlc/rlc_entity.h" @@ -110,6 +112,10 @@ struct du_ue_drb { f1u_config f1u_cfg; std::unique_ptr> drb_f1u; du_drb_connector connector; + /// QoS characteristics to be met by the DRB. + qos_characteristics qos_info; + /// QoS information present only for GBR QoS flows. + optional gbr_qos_info; /// \brief Stops DRB by disconnecting MAC, RLC and F1-U notifiers and stopping the RLC timers. void stop(); @@ -126,7 +132,9 @@ std::unique_ptr create_drb(du_ue_index_t ue_in span uluptnl_info_list, gtpu_teid_pool& teid_pool, const du_manager_params& du_params, - rlc_tx_upper_layer_control_notifier& rlc_rlf_notifier); + rlc_tx_upper_layer_control_notifier& rlc_rlf_notifier, + const qos_characteristics& qos_info, + optional gbr_qos_info); } // namespace srs_du } // namespace srsran diff --git a/lib/du_manager/du_ue/du_ue_adapters.h b/lib/du_manager/du_ue/du_ue_adapters.h index fc0d105ae7..5d99e1d067 100644 --- a/lib/du_manager/du_ue/du_ue_adapters.h +++ b/lib/du_manager/du_ue/du_ue_adapters.h @@ -232,19 +232,22 @@ class mac_sdu_tx_adapter : public mac_sdu_tx_builder public: void connect(rlc_tx_lower_layer_interface& rlc_tx) { rlc_handler = &rlc_tx; } + void disconnect() { connected = false; } + size_t on_new_tx_sdu(span mac_sdu_buf) override { srsran_assert(rlc_handler != nullptr, "MAC Rx SDU notifier is disconnected"); - return rlc_handler->pull_pdu(mac_sdu_buf); + return SRSRAN_LIKELY(connected.load(std::memory_order_relaxed)) ? rlc_handler->pull_pdu(mac_sdu_buf) : 0; } unsigned on_buffer_state_update() override { srsran_assert(rlc_handler != nullptr, "MAC Rx SDU notifier is disconnected"); - return rlc_handler->get_buffer_state(); + return SRSRAN_LIKELY(connected.load(std::memory_order_relaxed)) ? rlc_handler->get_buffer_state() : 0; } private: + std::atomic connected{true}; rlc_tx_lower_layer_interface* rlc_handler = nullptr; }; diff --git a/lib/du_manager/procedures/ue_configuration_procedure.cpp b/lib/du_manager/procedures/ue_configuration_procedure.cpp index 93dcaeaace..87b0c21501 100644 --- a/lib/du_manager/procedures/ue_configuration_procedure.cpp +++ b/lib/du_manager/procedures/ue_configuration_procedure.cpp @@ -158,6 +158,9 @@ void ue_configuration_procedure::update_ue_context() auto f1u_cfg_it = du_params.ran.qos.find(drbtoadd.five_qi); srsran_assert(f1u_cfg_it != du_params.ran.qos.end(), "Undefined F1-U bearer config for {}", drbtoadd.five_qi); + // TODO: Adjust QoS characteristics passed while creating a DRB since one DRB can contain multiple QoS flow of + // varying 5QI. + // Create DU DRB instance. std::unique_ptr drb = create_drb(ue->ue_index, ue->pcell_index, @@ -169,7 +172,9 @@ void ue_configuration_procedure::update_ue_context() drbtoadd.uluptnl_info_list, ue_mng.get_f1u_teid_pool(), du_params, - ue->get_rlc_rlf_notifier()); + ue->get_rlc_rlf_notifier(), + get_5qi_to_qos_characteristics_mapping(drbtoadd.five_qi), + drbtoadd.gbr_flow_info); if (drb == nullptr) { proc_logger.log_proc_warning("Failed to create {}. Cause: Failed to allocate DU UE resources.", drbtoadd.drb_id); continue; diff --git a/lib/e2/common/e2_subscription_manager_impl.cpp b/lib/e2/common/e2_subscription_manager_impl.cpp index 942afc20ed..8e84a1e7e0 100644 --- a/lib/e2/common/e2_subscription_manager_impl.cpp +++ b/lib/e2/common/e2_subscription_manager_impl.cpp @@ -134,9 +134,16 @@ bool e2_subscription_manager_impl::action_supported(const ri_caction_to_be_setup logger.error("Failed to get E2SM interface, RAN function {} not in allowed list", ran_func_id); return false; } + + auto action_def_buf = action.ric_action_definition.deep_copy(); + if (action_def_buf.is_error()) { + logger.warning("Failed to deep copy a byte_buffer"); + return false; + } + if (e2sm->action_supported(action)) { subscriptions[ric_request_id.ric_requestor_id].subscription_info.action_list.push_back( - {action.ric_action_definition.deep_copy(), action.ric_action_id, action.ric_action_type}); + {std::move(action_def_buf.value()), action.ric_action_id, action.ric_action_type}); return true; } diff --git a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp index 30a06e70d6..3654852f76 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp @@ -87,9 +87,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ran_function_desc.ran_function_name.ran_function_e2_sm_oid.resize(oid.size()); ran_function_desc.ran_function_name.ran_function_description.resize(func_description.size()); - ran_function_desc.ran_function_name.ran_function_short_name.from_string(short_name.c_str()); - ran_function_desc.ran_function_name.ran_function_e2_sm_oid.from_string(oid.c_str()); - ran_function_desc.ran_function_name.ran_function_description.from_string(func_description.c_str()); + ran_function_desc.ran_function_name.ran_function_short_name.from_string(short_name); + ran_function_desc.ran_function_name.ran_function_e2_sm_oid.from_string(oid); + ran_function_desc.ran_function_name.ran_function_description.from_string(func_description); ran_function_desc.ext = false; // Add ric_event_trigger_style item. ric_event_trigger_style_item_s ric_event_trigger_style_item; @@ -107,9 +107,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ric_report_style_item.ric_ind_hdr_format_type = 1; ric_report_style_item.ric_ind_msg_format_type = 1; ric_report_style_item.meas_info_action_list.clear(); - for (auto metric : meas_provider.get_supported_metric_names(E2_NODE_LEVEL)) { + for (const auto& metric : meas_provider.get_supported_metric_names(E2_NODE_LEVEL)) { meas_info_action_item_s meas_info_action_item; - meas_info_action_item.meas_name.from_string(metric.c_str()); + meas_info_action_item.meas_name.from_string(metric); meas_info_action_item.meas_id_present = false; ric_report_style_item.meas_info_action_list.push_back(meas_info_action_item); } @@ -122,9 +122,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ric_report_style_item.ric_ind_hdr_format_type = 1; ric_report_style_item.ric_ind_msg_format_type = 1; ric_report_style_item.meas_info_action_list.clear(); - for (auto metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { + for (const auto& metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { meas_info_action_item_s meas_info_action_item; - meas_info_action_item.meas_name.from_string(metric.c_str()); + meas_info_action_item.meas_name.from_string(metric); meas_info_action_item.meas_id_present = false; ric_report_style_item.meas_info_action_list.push_back(meas_info_action_item); } @@ -137,9 +137,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ric_report_style_item.ric_ind_hdr_format_type = 1; ric_report_style_item.ric_ind_msg_format_type = 2; ric_report_style_item.meas_info_action_list.clear(); - for (auto metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { + for (const auto& metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { meas_info_action_item_s meas_info_action_item; - meas_info_action_item.meas_name.from_string(metric.c_str()); + meas_info_action_item.meas_name.from_string(metric); meas_info_action_item.meas_id_present = false; ric_report_style_item.meas_info_action_list.push_back(meas_info_action_item); } @@ -152,9 +152,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ric_report_style_item.ric_ind_hdr_format_type = 1; ric_report_style_item.ric_ind_msg_format_type = 3; ric_report_style_item.meas_info_action_list.clear(); - for (auto metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { + for (const auto& metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { meas_info_action_item_s meas_info_action_item; - meas_info_action_item.meas_name.from_string(metric.c_str()); + meas_info_action_item.meas_name.from_string(metric); meas_info_action_item.meas_id_present = false; ric_report_style_item.meas_info_action_list.push_back(meas_info_action_item); } @@ -167,9 +167,9 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript ric_report_style_item.ric_ind_hdr_format_type = 1; ric_report_style_item.ric_ind_msg_format_type = 3; ric_report_style_item.meas_info_action_list.clear(); - for (auto metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { + for (const auto& metric : meas_provider.get_supported_metric_names(UE_LEVEL)) { meas_info_action_item_s meas_info_action_item; - meas_info_action_item.meas_name.from_string(metric.c_str()); + meas_info_action_item.meas_name.from_string(metric); meas_info_action_item.meas_id_present = false; ric_report_style_item.meas_info_action_list.push_back(meas_info_action_item); } @@ -183,6 +183,6 @@ asn1::unbounded_octstring e2sm_kpm_asn1_packer::pack_ran_function_descript return err_buf; } - asn1::unbounded_octstring ran_function_description(buf.begin(), buf.end()); + asn1::unbounded_octstring ran_function_description(std::move(buf)); return ran_function_description; -} \ No newline at end of file +} diff --git a/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h index 5b6982adbc..015c59f035 100644 --- a/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h +++ b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h @@ -55,15 +55,38 @@ f1ap_drb_to_setup make_drb_to_setup(const Asn1Type& drb_item) { f1ap_drb_to_setup drb_obj; - drb_obj.drb_id = static_cast(drb_item.drb_id); - drb_obj.mode = static_cast(static_cast(drb_item.rlc_mode)); - drb_obj.five_qi = uint_to_five_qi( - drb_item.qos_info.choice_ext().value().drb_info().drb_qos.qos_characteristics.non_dyn_5qi().five_qi); + drb_obj.drb_id = static_cast(drb_item.drb_id); + drb_obj.mode = static_cast(static_cast(drb_item.rlc_mode)); drb_obj.uluptnl_info_list.reserve(drb_item.ul_up_tnl_info_to_be_setup_list.size()); for (const auto& tnl_info : drb_item.ul_up_tnl_info_to_be_setup_list) { drb_obj.uluptnl_info_list.push_back(asn1_to_up_transport_layer_info(tnl_info.ul_up_tnl_info)); } + // TODO: Handle Dynamic 5QI. + drb_obj.five_qi = uint_to_five_qi( + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.qos_characteristics.non_dyn_5qi().five_qi); + drb_obj.arp_priority_level = + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.ngra_nalloc_retention_prio.prio_level; + // TODO: Do not populate gbr_flow_info for non-GBR flows. + if (drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info_present) { + drb_obj.gbr_flow_info.emplace(); + drb_obj.gbr_flow_info.value().max_flow_dl_bitrate = + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_flow_bit_rate_dl; + drb_obj.gbr_flow_info.value().max_flow_ul_bitrate = + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_flow_bit_rate_ul; + drb_obj.gbr_flow_info.value().guaranteed_flow_dl_bitrate = + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.guaranteed_flow_bit_rate_dl; + drb_obj.gbr_flow_info.value().guaranteed_flow_ul_bitrate = + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.guaranteed_flow_bit_rate_ul; + if (drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_packet_loss_rate_dl_present) { + drb_obj.gbr_flow_info.value().max_packet_loss_rate_dl.emplace( + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_packet_loss_rate_dl); + } + if (drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_packet_loss_rate_ul_present) { + drb_obj.gbr_flow_info.value().max_packet_loss_rate_dl.emplace( + drb_item.qos_info.choice_ext().value().drb_info().drb_qos.gbr_qos_flow_info.max_packet_loss_rate_ul); + } + } return drb_obj; } diff --git a/lib/f1u/cu_up/f1u_bearer_impl.cpp b/lib/f1u/cu_up/f1u_bearer_impl.cpp index 66d7cc7274..3314a79c7b 100644 --- a/lib/f1u/cu_up/f1u_bearer_impl.cpp +++ b/lib/f1u/cu_up/f1u_bearer_impl.cpp @@ -61,12 +61,14 @@ void f1u_bearer_impl::handle_pdu(nru_ul_message msg) void f1u_bearer_impl::handle_pdu_impl(nru_ul_message msg) { logger.log_debug("F1-U bearer received PDU"); + // handle T-PDU - if (!msg.t_pdu.empty()) { + if (msg.t_pdu.has_value() && !msg.t_pdu->empty()) { ue_inactivity_timer.run(); // restart inactivity timer due to UL PDU - logger.log_debug("Delivering T-PDU of size={}", msg.t_pdu.length()); - rx_sdu_notifier.on_new_sdu(std::move(msg.t_pdu)); + logger.log_debug("Delivering T-PDU of size={}", msg.t_pdu->length()); + rx_sdu_notifier.on_new_sdu(std::move(*msg.t_pdu)); } + // handle transmit notifications if (msg.data_delivery_status.has_value()) { nru_dl_data_delivery_status& status = msg.data_delivery_status.value(); diff --git a/lib/fapi/validators/dl_csi_pdu.cpp b/lib/fapi/validators/dl_csi_pdu.cpp index 145a5efa64..26a1b53f0e 100644 --- a/lib/fapi/validators/dl_csi_pdu.cpp +++ b/lib/fapi/validators/dl_csi_pdu.cpp @@ -138,31 +138,13 @@ static bool validate_scrambling_id(unsigned value, validator_report& report) return validate_field(MIN_VALUE, MAX_VALUE, value, "Scrambling ID", msg_type, pdu_type, report); } -/// Validates the power control offset SS profile NR and the CSI-RS power offset profile SSS properties of the CSI PDU, -/// as per SCF-222 v4.0 section 3.4.2.3. -static bool validate_power_control_offset_profile_nr(unsigned power_control_offset_ss_profile_nr, - int profile_sss, - validator_report& report) +/// Validates the power control offset SS profile NR property of the CSI PDU, as per SCF-222 v4.0 section 3.4.2.3. +static bool validate_power_control_offset_profile_nr(int power_control_offset, validator_report& report) { - static constexpr unsigned USE_PROFILE_SSS = 255; - static constexpr unsigned MIN_VALUE_PROFILE_NR = 0; - static constexpr unsigned MAX_VALUE_PROFILE_NR = 23; - static constexpr int USE_PROFILE_NR = -32768; - static constexpr int MIN_VALUE_PROFILE_SSS = -32767; - static constexpr int MAX_VALUE_PROFILE_SSS = 32767; - - if (power_control_offset_ss_profile_nr == USE_PROFILE_SSS && MIN_VALUE_PROFILE_SSS <= profile_sss && - profile_sss <= MAX_VALUE_PROFILE_SSS) { - return true; - } - - if (profile_sss == USE_PROFILE_NR && MIN_VALUE_PROFILE_NR <= power_control_offset_ss_profile_nr && - power_control_offset_ss_profile_nr <= MAX_VALUE_PROFILE_NR) { - return true; - } + static constexpr int MIN_VALUE = -8; + static constexpr int MAX_VALUE = 15; - report.append(power_control_offset_ss_profile_nr, "Power control offset", msg_type, pdu_type); - return false; + return validate_field(MIN_VALUE, MAX_VALUE, power_control_offset, "Power control offset", msg_type, pdu_type, report); } /// Validates the power control offset SS profile NR property of the CSI PDU, as per SCF-222 v4.0 section 3.4.2.3. @@ -171,27 +153,9 @@ static bool validate_power_control_offset_ss_profile_nr(unsigned value, validato static constexpr unsigned MIN_VALUE = 0; static constexpr unsigned MAX_VALUE = 3; - if (value == 255) { - return true; - } - return validate_field(MIN_VALUE, MAX_VALUE, value, "Power control offset SS profile NR", msg_type, pdu_type, report); } -/// Validates the power offset profile SSS property of the CSI PDU, as per SCF-222 v4.0 section 3.4.2.3. -static bool validate_power_offset_profile_sss(int value, validator_report& report) -{ - static constexpr int USE_PROFILE_NR = -32768; - static constexpr int MIN_VALUE = -32767; - static constexpr int MAX_VALUE = 32767; - - if (value == USE_PROFILE_NR) { - return true; - } - - return validate_field(MIN_VALUE, MAX_VALUE, value, "Power offset profile SSS", msg_type, pdu_type, report); -} - bool srsran::fapi::validate_dl_csi_pdu(const dl_csi_rs_pdu& pdu, validator_report& report) { bool result = true; @@ -208,12 +172,10 @@ bool srsran::fapi::validate_dl_csi_pdu(const dl_csi_rs_pdu& pdu, validator_repor result &= validate_cdm_type(static_cast(pdu.cdm_type), report); result &= validate_freq_density(static_cast(pdu.freq_density), report); result &= validate_scrambling_id(pdu.scramb_id, report); - result &= validate_power_control_offset_profile_nr( - pdu.power_control_offset_profile_nr, pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss, report); + result &= validate_power_control_offset_profile_nr(pdu.power_control_offset_profile_nr, report); result &= validate_power_control_offset_ss_profile_nr(static_cast(pdu.power_control_offset_ss_profile_nr), report); // NOTE: CSI-RS PDU index will not be validated. - result &= validate_power_offset_profile_sss(pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss, report); return result; } diff --git a/lib/fapi/validators/dl_pdcch_pdu.cpp b/lib/fapi/validators/dl_pdcch_pdu.cpp index 26123ec141..eb5189ee8b 100644 --- a/lib/fapi/validators/dl_pdcch_pdu.cpp +++ b/lib/fapi/validators/dl_pdcch_pdu.cpp @@ -198,32 +198,16 @@ static bool validate_aggregation_level(message_type_id msg_type, unsigned value, return false; } -/// Validates the power control offset SS profile NR and the PDCCH DMRS power offset profile SSS properties of the PDCCH -/// PDU, as per SCF-222 v4.0 section 3.4.2.1. -static bool validate_power_control_offset_profile_nr(message_type_id msg_type, - int power_control_offset_ss_profile_nr, - int dmrs_power_profile_sss, - validator_report& report) +/// Validates the power control offset SS profile NR property of the PDCCH PDU, as per SCF-222 v4.0 section 3.4.2.1. +static bool validate_power_control_offset_ss_profile_nr(message_type_id msg_type, + int power_control_offset_ss, + validator_report& report) { - static constexpr int USE_PROFILE_SSS = -127; - static constexpr int MIN_VALUE_PROFILE_NR = -8; - static constexpr int MAX_VALUE_PROFILE_NR = 8; - static constexpr int USE_PROFILE_NR = -32768; - static constexpr int MIN_VALUE_PROFILE_SSS = -32767; - static constexpr int MAX_VALUE_PROFILE_SSS = 32767; - - if (power_control_offset_ss_profile_nr == USE_PROFILE_SSS && MIN_VALUE_PROFILE_SSS <= dmrs_power_profile_sss && - dmrs_power_profile_sss <= MAX_VALUE_PROFILE_SSS) { - return true; - } - - if (dmrs_power_profile_sss == USE_PROFILE_NR && MIN_VALUE_PROFILE_NR <= power_control_offset_ss_profile_nr && - power_control_offset_ss_profile_nr <= MAX_VALUE_PROFILE_NR) { - return true; - } + static constexpr int MIN_VALUE = -8; + static constexpr int MAX_VALUE = 8; - report.append(dmrs_power_profile_sss, "DMRS Power offset", msg_type, pdu_type); - return false; + return validate_field( + MIN_VALUE, MAX_VALUE, power_control_offset_ss, "Power control offset SS", msg_type, pdu_type, report); } /// Validates the collocated AL16 candidate property of the PDCCH PDU, as per SCF-222 v4.0 section 3.4.2.1. @@ -265,8 +249,7 @@ bool srsran::fapi::validate_dl_pdcch_pdu(message_type_id msg_type, const dl_pdcc // NOTE: N-RNTI PDCCH data field uses the whole range of the variable, so it will not be checked. result &= validate_cce_index(msg_type, dci.cce_index, report); result &= validate_aggregation_level(msg_type, dci.aggregation_level, report); - result &= validate_power_control_offset_profile_nr( - msg_type, dci.power_control_offset_ss_profile_nr, dci_v3.pdcch_dmrs_power_offset_profile_sss, report); + result &= validate_power_control_offset_ss_profile_nr(msg_type, dci.power_control_offset_ss_profile_nr, report); // NOTE: DCI index uses the whole range of the variable, so it will not be checked. result &= validate_collocated_al16_candidate(msg_type, dci_v3.collocated_AL16_candidate, report); // NOTE: PDCCH DMRS power offset profile NR uses the whole range of the variable, so it will not be checked. diff --git a/lib/fapi/validators/dl_pdsch_pdu.cpp b/lib/fapi/validators/dl_pdsch_pdu.cpp index 952312c3db..d64bb0b25a 100644 --- a/lib/fapi/validators/dl_pdsch_pdu.cpp +++ b/lib/fapi/validators/dl_pdsch_pdu.cpp @@ -246,58 +246,31 @@ static bool validate_nr_of_symbols(unsigned value, validator_report& report) return validate_field(MIN_VALUE, MAX_VALUE, value, "PDSCH duration in symbols", msg_type, pdu_type, report); } -/// Validates the ratio of PDSCH EPRE to NZP CSI-RSEPRE and the PDSCH DMRS power offset profile SSS properties of the -/// PDSCH PDU, as per SCF-222 v4.0 section 3.4.2.2. -static bool validate_power_control_offset_profile_nr(unsigned power_control_offset_profile_nr, - int dmrs_power_profile_sss, - validator_report& report) -{ - static constexpr unsigned USE_PROFILE_SSS = 255; - static constexpr unsigned MIN_VALUE_PROFILE_NR = 0; - static constexpr unsigned MAX_VALUE_PROFILE_NR = 23; - static constexpr int USE_PROFILE_NR = -32768; - static constexpr int MIN_VALUE_PROFILE_SSS = -32767; - static constexpr int MAX_VALUE_PROFILE_SSS = 32767; - - if (power_control_offset_profile_nr == USE_PROFILE_SSS && MIN_VALUE_PROFILE_SSS <= dmrs_power_profile_sss && - dmrs_power_profile_sss <= MAX_VALUE_PROFILE_SSS) { - return true; - } - - if (dmrs_power_profile_sss == USE_PROFILE_NR && MIN_VALUE_PROFILE_NR <= power_control_offset_profile_nr && - power_control_offset_profile_nr <= MAX_VALUE_PROFILE_NR) { - return true; - } +/// Validates the ratio of PDSCH EPRE to NZP CSI-RS EPRE property of the PDSCH PDU, as per SCF-222 v4.0 section 3.4.2.2. +static bool validate_power_control_offset_profile_nr(int power_control_offset, validator_report& report) +{ + static constexpr int MIN_VALUE = -8; + static constexpr int MAX_VALUE = 15; - report.append(dmrs_power_profile_sss, "Ratio PDSCH EPRE to NZP CSI-RSEPRE", msg_type, pdu_type); - return false; + return validate_field( + MIN_VALUE, MAX_VALUE, power_control_offset, "Ratio PDSCH EPRE to NZP CSI-RS EPRE", msg_type, pdu_type, report); } -/// Validates the ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE and the PDSCH DMRS power offset profile SSS properties -/// of the PDSCH PDU, as per SCF-222 v4.0 section 3.4.2.2. +/// Validates the ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE property of the PDSCH PDU, as per SCF-222 v4.0 +/// section 3.4.2.2. static bool validate_power_control_offset_ss_profile_nr(unsigned power_control_offset_ss_profile_nr, - int dmrs_power_profile_sss, validator_report& report) { - static constexpr unsigned USE_PROFILE_SSS = 255; - static constexpr unsigned MIN_VALUE_PROFILE_NR = 0; - static constexpr unsigned MAX_VALUE_PROFILE_NR = 3; - static constexpr int USE_PROFILE_NR = -32768; - static constexpr int MIN_VALUE_PROFILE_SSS = -32767; - static constexpr int MAX_VALUE_PROFILE_SSS = 32767; - - if (power_control_offset_ss_profile_nr == USE_PROFILE_SSS && MIN_VALUE_PROFILE_SSS <= dmrs_power_profile_sss && - dmrs_power_profile_sss <= MAX_VALUE_PROFILE_SSS) { - return true; - } - - if (dmrs_power_profile_sss == USE_PROFILE_NR && MIN_VALUE_PROFILE_NR <= power_control_offset_ss_profile_nr && - power_control_offset_ss_profile_nr <= MAX_VALUE_PROFILE_NR) { - return true; - } + static constexpr unsigned MIN_VALUE = 0; + static constexpr unsigned MAX_VALUE = 3; - report.append(dmrs_power_profile_sss, "Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE", msg_type, pdu_type); - return false; + return validate_field(MIN_VALUE, + MAX_VALUE, + power_control_offset_ss_profile_nr, + "Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE", + msg_type, + pdu_type, + report); } /// Validates the is inline TB CRC property of the PDSCH PDU, as per SCF-222 v4.0 section 3.4.2.2. @@ -413,10 +386,8 @@ bool srsran::fapi::validate_dl_pdsch_pdu(const dl_pdsch_pdu& pdu, validator_repo result &= validate_start_symbol_index(pdu.start_symbol_index, report); result &= validate_nr_of_symbols(pdu.nr_of_symbols, report); - result &= validate_power_control_offset_profile_nr( - pdu.power_control_offset_profile_nr, pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss, report); + result &= validate_power_control_offset_profile_nr(pdu.power_control_offset_profile_nr, report); result &= validate_power_control_offset_ss_profile_nr(static_cast(pdu.power_control_offset_ss_profile_nr), - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss, report); if (pdu.pdu_bitmap[dl_pdsch_pdu::PDU_BITMAP_CBG_RETX_CTRL_BIT]) { diff --git a/lib/fapi/validators/dl_ssb_pdu.cpp b/lib/fapi/validators/dl_ssb_pdu.cpp index 3d89bbe317..ae66a20caa 100644 --- a/lib/fapi/validators/dl_ssb_pdu.cpp +++ b/lib/fapi/validators/dl_ssb_pdu.cpp @@ -46,13 +46,8 @@ static bool validate_phy_cell_id(unsigned value, validator_report& report) /// Validates the Beta PSS profine NR property of the SSB PDU, as per SCF-222 v4.0 section 3.4.2.4. static bool validate_beta_pss_profile_nr(unsigned value, validator_report& report) { - static constexpr unsigned MIN_VALUE = 0; - static constexpr unsigned MAX_VALUE = 1; - static constexpr unsigned USE_PROFILE_SSS = 255; - - if (value == USE_PROFILE_SSS) { - return true; - } + static constexpr unsigned MIN_VALUE = 0; + static constexpr unsigned MAX_VALUE = 1; return validate_field(MIN_VALUE, MAX_VALUE, value, "Beta PSS profile NR", msg_type, pdu_type, report); } @@ -114,45 +109,6 @@ static bool validate_subcarrier_spacing(unsigned value, validator_report& report return validate_field(MIN_VALUE, MAX_VALUE, value, "Subcarrier spacing", msg_type, pdu_type, report); } -/// Validates the baseband power scaling for SS-PBCH property of the SSB PDU, as per SCF-222 v4.0 section 3.4.2.4 -/// in table SSB/PBCH PDU maintenance FAPIv3. -static bool validate_ss_pbch_power_scaling(int value, validator_report& report) -{ - static constexpr int L1_DEFINES_PSS_POWER = -32768; - static constexpr int MIN_VALUE = -11000; - static constexpr int MAX_VALUE = 12000; - - if (value == L1_DEFINES_PSS_POWER) { - return true; - } - - return validate_field( - MIN_VALUE, MAX_VALUE, value, "Baseband power scaling applied to SS-PBCH", msg_type, pdu_type, report); -} - -/// Validates the beta PSS profile SSS property of the SSB PDU, as per SCF-222 v4.0 section 3.4.2.4 -/// in table SSB/PBCH PDU maintenance FAPIv3. -static bool validate_beta_pss_profile_sss(const dl_ssb_pdu& pdu, validator_report& report) -{ - static constexpr int BETA_PSS_PROFILE_NR_DEFINES_PSS_POWER = -32768; - static constexpr int MIN_VALUE = -32767; - static constexpr int MAX_VALUE = 32767; - - int power_value = pdu.ssb_maintenance_v3.beta_pss_profile_sss; - if (pdu.beta_pss_profile_nr == beta_pss_profile_type::beta_pss_profile_sss && MIN_VALUE <= power_value && - power_value <= MAX_VALUE) { - return true; - } - - if (pdu.beta_pss_profile_nr != beta_pss_profile_type::beta_pss_profile_sss && - power_value == BETA_PSS_PROFILE_NR_DEFINES_PSS_POWER) { - return true; - } - - report.append(power_value, "Beta PSS profile SSS", msg_type, pdu_type); - return false; -} - /// Validates the LMax property of the SSB PDU, as per SCF-222 v4.0 section 3.4.2.4 in table SSB/PBCH PDU maintenance /// FAPIv3. static bool validate_L_max(unsigned value, validator_report& report) @@ -188,8 +144,6 @@ bool srsran::fapi::validate_dl_ssb_pdu(const dl_ssb_pdu& pdu, validator_report& result &= validate_case(static_cast(pdu.ssb_maintenance_v3.case_type), report); result &= validate_subcarrier_spacing(static_cast(pdu.ssb_maintenance_v3.scs), report); result &= validate_L_max(pdu.ssb_maintenance_v3.L_max, report); - result &= validate_ss_pbch_power_scaling(pdu.ssb_maintenance_v3.ss_pbch_block_power_scaling, report); - result &= validate_beta_pss_profile_sss(pdu, report); return result; } diff --git a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp index 1d0261a406..0630a263ee 100644 --- a/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp +++ b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp @@ -104,16 +104,18 @@ void fapi_to_mac_data_msg_translator::on_rx_data_indication(const fapi::rx_data_ if (fapi_pdu.pdu_length == 0) { continue; } - mac_rx_pdu& pdu = indication.pdus.emplace_back(); - pdu.harq_id = fapi_pdu.harq_id; - pdu.rnti = fapi_pdu.rnti; - pdu.pdu = span(fapi_pdu.data, fapi_pdu.pdu_length); - if (pdu.pdu.empty()) { + + auto pdu_buffer = byte_buffer::create(span(fapi_pdu.data, fapi_pdu.pdu_length)); + if (pdu_buffer.is_error()) { srslog::fetch_basic_logger("FAPI").warning("Unable to allocate memory for MAC RX PDU"); - indication.pdus.pop_back(); // Avoid new buffer allocations for the same FAPI PDU. break; } + + mac_rx_pdu& pdu = indication.pdus.emplace_back(); + pdu.harq_id = fapi_pdu.harq_id; + pdu.rnti = fapi_pdu.rnti; + pdu.pdu = std::move(pdu_buffer.value()); } // Only invoke the MAC when there are successfully decoded PDUs available. diff --git a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp index 5331bc042d..cabdd4dda2 100644 --- a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp +++ b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp @@ -104,27 +104,10 @@ static void add_ssb_pdus_to_dl_request(fapi::dl_tti_request_message_builder& bui } } -static fapi::nzp_csi_rs_epre_to_ssb to_nzp_csi_rs_epre_to_ssb(int value) -{ - switch (value) { - case -3: - return fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3; - case 0: - return fapi::nzp_csi_rs_epre_to_ssb::dB0; - case 3: - return fapi::nzp_csi_rs_epre_to_ssb::dB3; - case 6: - return fapi::nzp_csi_rs_epre_to_ssb::dB6; - default: - return fapi::nzp_csi_rs_epre_to_ssb::dB0; - } -} - static void add_csi_rs_pdus_to_dl_request(fapi::dl_tti_request_message_builder& builder, span csi_rs_list) { for (const auto& pdu : csi_rs_list) { - bool is_nzp_csi = pdu.type == csi_rs_type::CSI_RS_NZP; fapi::dl_csi_rs_pdu_builder csi_builder = builder.add_csi_rs_pdu(pdu.crbs.start(), pdu.crbs.length(), pdu.type, @@ -134,17 +117,12 @@ static void add_csi_rs_pdus_to_dl_request(fapi::dl_tti_request_message_builder& pdu.symbol1, pdu.cdm_type, pdu.freq_density, - (is_nzp_csi) ? pdu.scrambling_id : 0); + pdu.scrambling_id); csi_builder.set_bwp_parameters(pdu.bwp_cfg->scs, pdu.bwp_cfg->cp); - if (is_nzp_csi) { - csi_builder.set_tx_power_info_parameters(pdu.power_ctrl_offset, - to_nzp_csi_rs_epre_to_ssb(pdu.power_ctrl_offset_ss)); - } else { - // ZP-CSI type does not use these values. - csi_builder.set_tx_power_info_parameters(0, fapi::nzp_csi_rs_epre_to_ssb::dB0); - } - csi_builder.set_maintenance_v3_tx_power_info_parameters({}); + + csi_builder.set_tx_power_info_parameters(pdu.power_ctrl_offset, + fapi::to_power_control_offset_ss(pdu.power_ctrl_offset_ss)); } } diff --git a/lib/fapi_adaptor/mac/messages/pdcch.cpp b/lib/fapi_adaptor/mac/messages/pdcch.cpp index 4c88c9dcb0..634825bd43 100644 --- a/lib/fapi_adaptor/mac/messages/pdcch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdcch.cpp @@ -113,13 +113,10 @@ void srsran::fapi_adaptor::convert_pdcch_mac_to_fapi(fapi::dl_pdcch_pdu_builder& to_nof_cces(dci.info->cces.aggr_lvl)); // This parameter is not passed by the MAC, set it to zero. - dci_builder.set_tx_power_info_parameter(0.F); + dci_builder.set_tx_power_info_parameter(dci.info->tx_pwr.pwr_ctrl_offset_ss); fill_precoding_and_beamforming(dci_builder, pm_mapper, cell_nof_prbs); - // These parameters are not passed by the MAC, leave them as disabled. - dci_builder.set_maintenance_v3_dci_parameters(false, {}, {}); - dci_builder.set_parameters_v4_dci(dci.info->n_id_pdcch_dmrs); dci_builder.set_payload(*dci.payload); diff --git a/lib/fapi_adaptor/mac/messages/pdsch.cpp b/lib/fapi_adaptor/mac/messages/pdsch.cpp index b8a141896a..154a445ac3 100644 --- a/lib/fapi_adaptor/mac/messages/pdsch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdsch.cpp @@ -121,12 +121,10 @@ static void fill_time_allocation(fapi::dl_pdsch_pdu_builder& builder, const ofdm builder.set_pdsch_allocation_in_time_parameters(symbols.start(), symbols.length()); } -static void fill_power_parameters(fapi::dl_pdsch_pdu_builder& builder) +static void fill_power_parameters(fapi::dl_pdsch_pdu_builder& builder, const tx_power_pdsch_information& power_params) { - builder.set_tx_power_info_parameters({0}, fapi::nzp_csi_rs_epre_to_ssb::dB0); - - // Default v3 powers. - builder.set_maintenance_v3_tx_power_info_parameters({}, {}); + builder.set_tx_power_info_parameters(power_params.pwr_ctrl_offset, + fapi::to_power_control_offset_ss(power_params.pwr_ctrl_offset_ss)); } static void fill_precoding_and_beamforming(fapi::dl_pdsch_pdu_builder& builder, @@ -175,6 +173,9 @@ static void fill_pdsch_information(fapi::dl_pdsch_pdu_builder& builder, const pd // Time allocation. fill_time_allocation(builder, pdsch_cfg.symbols); + + // Power parameters. + fill_power_parameters(builder, pdsch_cfg.tx_pwr_info); } static void fill_coreset(fapi::dl_pdsch_pdu_builder& builder, @@ -262,8 +263,6 @@ void srsran::fapi_adaptor::convert_pdsch_mac_to_fapi(fapi::dl_pdsch_pdu_builder& builder.set_bwp_parameters( crbs.length(), crbs.start(), mac_pdu.pdsch_cfg.bwp_cfg->scs, mac_pdu.pdsch_cfg.bwp_cfg->cp); - fill_power_parameters(builder); - // Get the VRB-to-PRB mapping from the DCI. bool is_interleaved = mac_pdu.pdsch_cfg.is_interleaved; // Frequency allocation. @@ -322,8 +321,6 @@ void srsran::fapi_adaptor::convert_pdsch_mac_to_fapi(fapi::dl_pdsch_pdu_builder& builder.set_bwp_parameters( crbs.length(), crbs.start(), mac_pdu.pdsch_cfg.bwp_cfg->scs, mac_pdu.pdsch_cfg.bwp_cfg->cp); - fill_power_parameters(builder); - // Get the VRB-to-PRB mapping from the DCI. bool is_interleaved = mac_pdu.pdsch_cfg.is_interleaved; // Frequency allocation. @@ -383,8 +380,6 @@ void srsran::fapi_adaptor::convert_pdsch_mac_to_fapi(fapi::dl_pdsch_pdu_builder& builder.set_bwp_parameters( crbs.length(), crbs.start(), mac_pdu.pdsch_cfg.bwp_cfg->scs, mac_pdu.pdsch_cfg.bwp_cfg->cp); - fill_power_parameters(builder); - // Get the VRB-to-PRB mapping from the DCI. bool is_interleaved = mac_pdu.pdsch_cfg.is_interleaved; // Frequency allocation. @@ -435,8 +430,6 @@ void srsran::fapi_adaptor::convert_pdsch_mac_to_fapi(fapi::dl_pdsch_pdu_builder& builder.set_bwp_parameters( crbs.length(), crbs.start(), mac_pdu.pdsch_cfg.bwp_cfg->scs, mac_pdu.pdsch_cfg.bwp_cfg->cp); - fill_power_parameters(builder); - // Get the VRB-to-PRB mapping from the DCI. bool is_interleaved = mac_pdu.pdsch_cfg.is_interleaved; // Frequency allocation. diff --git a/lib/fapi_adaptor/mac/messages/ssb.cpp b/lib/fapi_adaptor/mac/messages/ssb.cpp index f58fd5aa4e..bc417b986e 100644 --- a/lib/fapi_adaptor/mac/messages/ssb.cpp +++ b/lib/fapi_adaptor/mac/messages/ssb.cpp @@ -59,8 +59,6 @@ void srsran::fapi_adaptor::convert_ssb_mac_to_fapi(fapi::dl_ssb_pdu_builder& bui builder.set_maintenance_v3_basic_parameters(mac_pdu.ssb_case, mac_pdu.scs, mac_pdu.L_max); - builder.set_maintenance_v3_tx_power_info({}, {}); - const ssb_mib_data_pdu& mib_pdu = mac_pdu.mib_data; builder.set_bch_payload_phy_full( mib_pdu.dmrs_typeA_pos, mib_pdu.pdcch_config_sib1, mib_pdu.cell_barred, mib_pdu.intra_freq_reselection); diff --git a/lib/fapi_adaptor/phy/messages/csi_rs.cpp b/lib/fapi_adaptor/phy/messages/csi_rs.cpp index e512b11336..5dee18cfdc 100644 --- a/lib/fapi_adaptor/phy/messages/csi_rs.cpp +++ b/lib/fapi_adaptor/phy/messages/csi_rs.cpp @@ -29,19 +29,18 @@ using namespace srsran; using namespace fapi_adaptor; -/// Translates the \c nzp_csi_rs_epre_to_ssb enum to a linear amplitude value. -static float translate_amplitude(fapi::nzp_csi_rs_epre_to_ssb power) +/// Translates the \c power_controñ_offset_ss enum to a linear amplitude value. +static float translate_amplitude(fapi::power_control_offset_ss power) { switch (power) { - case fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3: + case fapi::power_control_offset_ss::dB_minus_3: return 0.5F; - case fapi::nzp_csi_rs_epre_to_ssb::dB0: + case fapi::power_control_offset_ss::dB0: return 1.F; - case fapi::nzp_csi_rs_epre_to_ssb::dB3: + case fapi::power_control_offset_ss::dB3: return 2.F; - case fapi::nzp_csi_rs_epre_to_ssb::dB6: + case fapi::power_control_offset_ss::dB6: return 4.F; - case fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss: default: return 1.F; } diff --git a/lib/fapi_adaptor/phy/messages/pdcch.cpp b/lib/fapi_adaptor/phy/messages/pdcch.cpp index f6c6092299..12feaee5d7 100644 --- a/lib/fapi_adaptor/phy/messages/pdcch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdcch.cpp @@ -34,7 +34,6 @@ static void fill_dci(pdcch_processor::pdu_t& proc_pdu, const precoding_matrix_repository& pm_repo) { const auto& fapi_dci = fapi_pdu.dl_dci[i_dci]; - const auto& fapi_dci_v3 = fapi_pdu.maintenance_v3.info[i_dci]; const auto& fapi_dci_v4 = fapi_pdu.parameters_v4.params[i_dci]; pdcch_processor::dci_description& dci = proc_pdu.dci; @@ -46,14 +45,8 @@ static void fill_dci(pdcch_processor::pdu_t& proc_pdu, dci.cce_index = fapi_dci.cce_index; dci.aggregation_level = fapi_dci.aggregation_level; - dci.dmrs_power_offset_dB = (fapi_dci.power_control_offset_ss_profile_nr == -127) - ? static_cast(fapi_dci_v3.pdcch_dmrs_power_offset_profile_sss) * 0.001F - : static_cast(fapi_dci.power_control_offset_ss_profile_nr); - - dci.data_power_offset_dB = (fapi_dci_v3.pdcch_data_power_offset_profile_sss == - std::numeric_limits::min()) - ? dci.dmrs_power_offset_dB - : float(fapi_dci_v3.pdcch_data_power_offset_profile_sss) * 0.001F; + dci.dmrs_power_offset_dB = fapi_dci.power_control_offset_ss_profile_nr; + dci.data_power_offset_dB = dci.dmrs_power_offset_dB; // Unpack the payload. dci.payload.resize(fapi_dci.payload.size()); diff --git a/lib/fapi_adaptor/phy/messages/pdsch.cpp b/lib/fapi_adaptor/phy/messages/pdsch.cpp index 7ed064dc03..268d5c544c 100644 --- a/lib/fapi_adaptor/phy/messages/pdsch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdsch.cpp @@ -54,16 +54,16 @@ static void fill_codewords(pdsch_processor::pdu_t& proc_pdu, const fapi::dl_pdsc } } -static float get_power_control_offset_ss_dB(fapi::nzp_csi_rs_epre_to_ssb power_control_offset_ss_profile_nr) +static float get_power_control_offset_ss_dB(fapi::power_control_offset_ss power_control_offset_ss_profile_nr) { switch (power_control_offset_ss_profile_nr) { - case fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3: + case fapi::power_control_offset_ss::dB_minus_3: return -3.0F; - case fapi::nzp_csi_rs_epre_to_ssb::dB0: + case fapi::power_control_offset_ss::dB0: return +0.0F; - case fapi::nzp_csi_rs_epre_to_ssb::dB3: + case fapi::power_control_offset_ss::dB3: return +3.0F; - case fapi::nzp_csi_rs_epre_to_ssb::dB6: + case fapi::power_control_offset_ss::dB6: default: break; } @@ -73,49 +73,12 @@ static float get_power_control_offset_ss_dB(fapi::nzp_csi_rs_epre_to_ssb power_c /// Fills the power related parameters in the PDSCH PDU. static void fill_power_values(pdsch_processor::pdu_t& proc_pdu, const fapi::dl_pdsch_pdu& fapi_pdu) { - // Determine if ProfileNR is enabled. - bool use_profileNR = - (fapi_pdu.power_control_offset_ss_profile_nr != fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss); - - // Depending on the profile to use. - if (use_profileNR) { - // Load Data to SSS ratio from NR profile. - srsran_assert(fapi_pdu.power_control_offset_profile_nr != - std::numeric_limits::max(), - "Expected SSS profile."); - - // Calculate the power offset between NZP-CSI-RS to PDSCH data. - float power_control_offset_dB = static_cast(fapi_pdu.power_control_offset_profile_nr - 8); - - // Calculate the power offset between NZP-CSI-RS to SSS. - float power_control_offset_ss_dB = get_power_control_offset_ss_dB(fapi_pdu.power_control_offset_ss_profile_nr); - - proc_pdu.ratio_pdsch_data_to_sss_dB = power_control_offset_dB + power_control_offset_ss_dB; - } else { - // Load Data to SSS ratio from SSS profile. - srsran_assert(fapi_pdu.power_control_offset_profile_nr == - std::numeric_limits::max(), - "Expected SSS profile."); - srsran_assert(fapi_pdu.power_control_offset_ss_profile_nr == fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss, - "Expected SSS profile."); - srsran_assert( - fapi_pdu.pdsch_maintenance_v3.pdsch_data_power_offset_profile_sss != - std::numeric_limits::min(), - "Expected SSS profile."); - proc_pdu.ratio_pdsch_data_to_sss_dB = - static_cast(fapi_pdu.pdsch_maintenance_v3.pdsch_data_power_offset_profile_sss) * 0.001F; - } + proc_pdu.ratio_pdsch_data_to_sss_dB = get_power_control_offset_ss_dB(fapi_pdu.power_control_offset_ss_profile_nr) + + static_cast(fapi_pdu.power_control_offset_profile_nr); - // Use direct value if SSS profile is used. - if (fapi_pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss != - std::numeric_limits::min()) { - proc_pdu.ratio_pdsch_dmrs_to_sss_dB = - static_cast(fapi_pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss) * 0.001F; - } else { - // Otherwise, determines the PDSCH DMRS power from the PDSCH data power as per TS38.214 Table 4.1-1. - proc_pdu.ratio_pdsch_dmrs_to_sss_dB = - proc_pdu.ratio_pdsch_data_to_sss_dB + get_sch_to_dmrs_ratio_dB(fapi_pdu.num_dmrs_cdm_grps_no_data); - } + // Determine the PDSCH DMRS power from the PDSCH data power as per TS38.214 Table 4.1-1. + proc_pdu.ratio_pdsch_dmrs_to_sss_dB = + proc_pdu.ratio_pdsch_data_to_sss_dB + get_sch_to_dmrs_ratio_dB(fapi_pdu.num_dmrs_cdm_grps_no_data); } static unsigned get_interleaver_size(fapi::vrb_to_prb_mapping_type vrb_to_prb_mapping) diff --git a/lib/fapi_adaptor/phy/messages/ssb.cpp b/lib/fapi_adaptor/phy/messages/ssb.cpp index 789cbe598c..04f8e80400 100644 --- a/lib/fapi_adaptor/phy/messages/ssb.cpp +++ b/lib/fapi_adaptor/phy/messages/ssb.cpp @@ -141,8 +141,6 @@ static float convert_to_beta_pss(const fapi::dl_ssb_pdu& fapi_pdu) return 0.F; case fapi::beta_pss_profile_type::dB_3: return 3.F; - case fapi::beta_pss_profile_type::beta_pss_profile_sss: - return fapi_pdu.ssb_maintenance_v3.beta_pss_profile_sss * 0.001F; default: // NOTE: Unreachable code as the FAPI message should have been validated. srsran_assert(0, "Invalid beta PSS profile"); diff --git a/lib/gateways/sctp_network_gateway_impl.cpp b/lib/gateways/sctp_network_gateway_impl.cpp index b6fe943f4c..cbdd99e8ee 100644 --- a/lib/gateways/sctp_network_gateway_impl.cpp +++ b/lib/gateways/sctp_network_gateway_impl.cpp @@ -573,7 +573,13 @@ void sctp_network_gateway_impl::handle_notification(span pay void sctp_network_gateway_impl::handle_data(const span payload) { logger.debug("Received data of {} bytes", payload.size_bytes()); - data_notifier.on_new_pdu(byte_buffer(payload.begin(), payload.end())); + + auto payload_buffer = byte_buffer::create(payload.begin(), payload.end()); + if (payload_buffer.is_error()) { + logger.warning("Unable to allocate byte_buffer"); + return; + } + data_notifier.on_new_pdu(std::move(payload_buffer.value())); } ///< Process outgoing PDU and send over SCTP socket to peer. diff --git a/lib/gtpu/gtpu_demux_impl.cpp b/lib/gtpu/gtpu_demux_impl.cpp index 27c876c67c..472e952340 100644 --- a/lib/gtpu/gtpu_demux_impl.cpp +++ b/lib/gtpu/gtpu_demux_impl.cpp @@ -74,11 +74,9 @@ void gtpu_demux_impl::handle_pdu(byte_buffer pdu, const sockaddr_storage& src_ad return; } - auto fn = [this, teid, p = std::move(pdu), tunnel = it->second.tunnel, src_addr]() mutable { - handle_pdu_impl(teid, tunnel, std::move(p), src_addr); - }; + auto fn = [this, teid, p = std::move(pdu), src_addr]() mutable { handle_pdu_impl(teid, std::move(p), src_addr); }; - if (not it->second.tunnel_exec->execute(std::move(fn))) { + if (not it->second.tunnel_exec->defer(std::move(fn))) { if (not cfg.warn_on_drop) { logger.info("Dropped GTP-U PDU, queue is full. teid={}", teid); } else { @@ -87,17 +85,34 @@ void gtpu_demux_impl::handle_pdu(byte_buffer pdu, const sockaddr_storage& src_ad } } -void gtpu_demux_impl::handle_pdu_impl(gtpu_teid_t teid, - gtpu_tunnel_rx_upper_layer_interface* tunnel, - byte_buffer pdu, - const sockaddr_storage& src_addr) +void gtpu_demux_impl::handle_pdu_impl(gtpu_teid_t teid, byte_buffer pdu, const sockaddr_storage& src_addr) { if (gtpu_pcap.is_write_enabled()) { - gtpu_pcap.push_pdu(pdu.deep_copy()); + auto pdu_copy = pdu.deep_copy(); + if (pdu_copy.is_error()) { + logger.warning("Unable to deep copy PDU for PCAP writer"); + } else { + gtpu_pcap.push_pdu(std::move(pdu_copy.value())); + } } logger.debug(pdu.begin(), pdu.end(), "Forwarding PDU. pdu_len={} teid={}", pdu.length(), teid); + gtpu_tunnel_rx_upper_layer_interface* tunnel = nullptr; + { + /// Get GTP-U tunnel. We lookup the tunnel again, as the tunnel could have been + /// removed between the time PDU processing was enqueued and the time we actually + /// run the task. + std::lock_guard guard(map_mutex); + const auto& it = teid_to_tunnel.find(teid); + tunnel = it->second.tunnel; + if (it == teid_to_tunnel.end()) { + logger.info("Dropped GTP-U PDU, tunnel not found. teid={}", teid); + return; + } + } // Forward entire PDU to the tunnel + // As removal happens in the same thread as handling the PDU, we no longer + // need the lock. tunnel->handle_pdu(std::move(pdu), src_addr); } diff --git a/lib/gtpu/gtpu_demux_impl.h b/lib/gtpu/gtpu_demux_impl.h index bbe79b7679..c6b54c9a44 100644 --- a/lib/gtpu/gtpu_demux_impl.h +++ b/lib/gtpu/gtpu_demux_impl.h @@ -52,10 +52,7 @@ class gtpu_demux_impl final : public gtpu_demux private: // Actual demuxing, to be run in CU-UP executor. - void handle_pdu_impl(gtpu_teid_t teid, - gtpu_tunnel_rx_upper_layer_interface* tunnel, - byte_buffer pdu, - const sockaddr_storage& src_addr); + void handle_pdu_impl(gtpu_teid_t teid, byte_buffer pdu, const sockaddr_storage& src_addr); const gtpu_demux_cfg_t cfg; dlt_pcap& gtpu_pcap; diff --git a/lib/gtpu/gtpu_echo_rx_impl.h b/lib/gtpu/gtpu_echo_rx_impl.h index ded7a78aa6..f260ef1177 100644 --- a/lib/gtpu/gtpu_echo_rx_impl.h +++ b/lib/gtpu/gtpu_echo_rx_impl.h @@ -73,15 +73,26 @@ class gtpu_echo_rx : public gtpu_tunnel_base_rx // For Supported Extension Headers Notification [...], the Sequence Number shall be ignored by the receiver, // even though the S flag is set to '1'. return; - case GTPU_MSG_ERROR_INDICATION: - // TODO: unpack and print information elements; add handling - logger.log_info(pdu.buf.begin(), pdu.buf.end(), "Received error indication from peer"); - // TS 29.281 Sec. 7.3.1: Error Indication - // When a GTP-U node receives a G-PDU for which no EPS Bearer context, PDP context, PDU Session, MBMS Bearer - // context, or RAB exists, the GTP-U node shall discard the G - PDU.If the TEID of the incoming G-PDU is - // different from the value 'all zeros' the GTP-U node shall also return a GTP error indication to the - // originating node. + case GTPU_MSG_ERROR_INDICATION: { + gtpu_msg_error_indication err_ind = {}; + byte_buffer msg = gtpu_extract_msg(std::move(pdu)); + bool msg_ok = gtpu_read_msg_error_indication(err_ind, msg, logger.get_basic_logger()); + if (!msg_ok) { + logger.log_error(pdu.buf.begin(), pdu.buf.end(), "Received malfomed error indication from peer"); + return; + } + logger.log_info("Received error indication from peer. {}", err_ind); + // TODO: implement handling as specified in TS 23.527 Sec. 5.3.3.1: + // Upon receipt of a GTP-U Error Indication, the 5G-AN shall proceed as follows: + // - if the GTP-U Error Indication was received from an UPF over a NG-U tunnel that is not an indirect + // forwarding tunnel, the 5G-AN shall initiate a PDU Session Resource Notify procedure and release immediately + // the resources of the PDU session for which the Error Indication was received; + // - if the GTP-U Error Indication was received from a peer5G-AN over a Xn-U direct forwarding tunnel or an UPF + // over a NG-U indirect forwarding tunnel, the 5G-AN may ignore the error indication or delete the forwarding + // tunnel context locally without deleting the corresponding PDU session and bearers. + // NOTE: The 5G-AN behaviour for dual connectivity is not described in this specification. return; + } case GTPU_MSG_END_MARKER: // TODO: unpack and print information elements; add handling logger.log_warning("Discarded PDU. Cause: 'End marker' not supported"); diff --git a/lib/gtpu/gtpu_pdu.cpp b/lib/gtpu/gtpu_pdu.cpp index 2a7cb5b90a..6f584b0931 100644 --- a/lib/gtpu/gtpu_pdu.cpp +++ b/lib/gtpu/gtpu_pdu.cpp @@ -152,6 +152,46 @@ bool gtpu_write_ie_private_extension(byte_buffer& pdu, return pack_ok; } +bool gtpu_read_ie_type(gtpu_information_element_type& ie_type, bit_decoder& dec, srslog::basic_logger& logger) +{ + bool read_ok = true; + read_ok &= dec.unpack(reinterpret_cast&>(ie_type), 8); + return read_ok; +} + +bool gtpu_read_ie_teid_i(gtpu_ie_teid_i& ie, bit_decoder& dec, srslog::basic_logger& logger) +{ + bool read_ok = true; + read_ok &= dec.unpack(ie.teid_i, 32); + return read_ok; +} + +bool gtpu_read_ie_gtpu_peer_address(gtpu_ie_gtpu_peer_address& ie, bit_decoder& dec, srslog::basic_logger& logger) +{ + bool read_ok = true; + uint16_t length = 0; + read_ok &= dec.unpack(length, 16); + if (!read_ok) { + logger.warning("Failed to read IE GTP-U peer address: Cannot read length."); + return false; + } + switch (length) { + case 4: + ie.gtpu_peer_address = gtpu_ie_gtpu_peer_address::ipv4_addr_t{}; + read_ok &= dec.unpack_bytes(variant_get(ie.gtpu_peer_address)); + break; + case 16: + ie.gtpu_peer_address = gtpu_ie_gtpu_peer_address::ipv6_addr_t{}; + read_ok &= dec.unpack_bytes(variant_get(ie.gtpu_peer_address)); + break; + default: + logger.warning("Failed to read IE GTP-U peer address: Invalid length={}.", length); + return false; + break; + } + return read_ok; +} + bool gtpu_read_teid(uint32_t& teid, const byte_buffer& pdu, srslog::basic_logger& logger) { if (pdu.length() < GTPU_BASE_HEADER_LEN) { @@ -400,12 +440,41 @@ bool gtpu_extension_header_comprehension_check(const gtpu_extension_header_type& return comp_not_needed; } -byte_buffer gtpu_extract_t_pdu(gtpu_dissected_pdu&& dissected_pdu) +byte_buffer gtpu_extract_msg(gtpu_dissected_pdu&& dissected_pdu) { dissected_pdu.buf.trim_head(dissected_pdu.hdr_len); return std::move(dissected_pdu.buf); } +bool gtpu_read_msg_error_indication(gtpu_msg_error_indication& error_indication, + const byte_buffer& pdu, + srslog::basic_logger& logger) +{ + bool read_ok = true; + bit_decoder decoder = bit_decoder{pdu}; + gtpu_information_element_type ie_type = {}; + + // Read TEID I + read_ok &= gtpu_read_ie_type(ie_type, decoder, logger); + if (ie_type != gtpu_information_element_type::tunnel_endpoint_identifier_data_i) { + logger.error("Unexpected or misplaced IE type in error indication. ie_type={}", ie_type); + return false; + } + read_ok &= gtpu_read_ie_teid_i(error_indication.teid_i, decoder, logger); + + // Read GTP-U peer address + read_ok &= gtpu_read_ie_type(ie_type, decoder, logger); + if (ie_type != gtpu_information_element_type::gsn_address) { + logger.error("Unexpected or misplaced IE type in error indication. ie_type={}", ie_type); + return false; + } + read_ok &= gtpu_read_ie_gtpu_peer_address(error_indication.gtpu_peer_address, decoder, logger); + + // TODO: Read optional private extension + + return read_ok; +} + uint16_t gtpu_get_length(const gtpu_header& header, const byte_buffer& sdu) { uint16_t len = sdu.length(); diff --git a/lib/gtpu/gtpu_pdu.h b/lib/gtpu/gtpu_pdu.h index 8b8a1f53a3..432beab481 100644 --- a/lib/gtpu/gtpu_pdu.h +++ b/lib/gtpu/gtpu_pdu.h @@ -23,7 +23,6 @@ #include "gtpu_tunnel_logger.h" #include "srsran/adt/byte_buffer.h" -#include "srsran/adt/optional.h" #include "srsran/adt/static_vector.h" #include "fmt/format.h" #include @@ -168,13 +167,35 @@ struct gtpu_extension_header { }; /// GTP-U information element for "Recovery". See TS 29.281 Sec. 8.2 +/// +/// The value of the restart counter shall be set to 0 by the sending entity and ignored by the receiving entity. This +/// information element is used in GTP user plane due to backwards compatibility reasons. +/// /// IE format: TV struct gtpu_ie_recovery { - /// The value of the restart counter shall be set to 0 by the sending entity and ignored by the receiving entity. This - /// information element is used in GTP user plane due to backwards compatibility reasons. + /// Restart counter (always 0) uint8_t restart_counter = 0; }; +/// GTPU information element for "Tunnel Endpoint Identifier Data I". See TS 29.281 Sec. 8.3 +/// +/// The Tunnel Endpoint Identifier Data I information element contains the Tunnel Endpoint Identifier used by a GTP +/// entity for the user plane. +/// +/// IE format: TV +struct gtpu_ie_teid_i { + /// Tunnel Endpoint Identifier Data I + uint32_t teid_i = 0; +}; + +struct gtpu_ie_gtpu_peer_address { + using ipv4_addr_t = std::array; + using ipv6_addr_t = std::array; + + /// IPv4 or IPv6 Address + variant gtpu_peer_address; +}; + /// GTP-U information element for "Private Extension". See TS 29.281 Sec. 8.6 /// IE format: TLV struct gtpu_ie_private_extension { @@ -265,11 +286,26 @@ bool gtpu_supported_flags_check(const gtpu_header& header, gtpu_tunnel_logger& l bool gtpu_supported_msg_type_check(const gtpu_header& header, gtpu_tunnel_logger& logger); bool gtpu_extension_header_comprehension_check(const gtpu_extension_header_type& type, gtpu_tunnel_logger& logger); -/// Extracts the T-PDU of a dissected GTP-U PDU by advancing its internal PDU buffer by the header length and returning -/// that object. Any other content of the dissected PDU (e.g. header extensions) will be invalidated. -/// \param dissected_pdu The dissected GTP-U PDU from which the T-PDU shall be extracted. +/// Extracts the GTP-U message (i.e. the information elements or the G-PDU) of a dissected GTP-U PDU by advancing its +/// internal PDU buffer by the header length and returning that object. Any other content of the dissected PDU (e.g. +/// header extensions) will be invalidated. +/// +/// \param dissected_pdu The dissected GTP-U PDU from which the message shall be extracted. /// \return The T-PDU of the dissected GTP-U PDU. -byte_buffer gtpu_extract_t_pdu(gtpu_dissected_pdu&& dissected_pdu); +byte_buffer gtpu_extract_msg(gtpu_dissected_pdu&& dissected_pdu); + +/// GTP-U Tunnel Management Message: Error Indication. See TS 29.281 Sec. 7.3.1 +struct gtpu_msg_error_indication { + /// Tunnel Endpoint Identifier Data I + gtpu_ie_teid_i teid_i; + /// GTP-U Peer Adddress + gtpu_ie_gtpu_peer_address gtpu_peer_address; +}; + +/// Reads and unpacks a GTP-U error indication message. +bool gtpu_read_msg_error_indication(gtpu_msg_error_indication& error_indication, + const byte_buffer& pdu, + srslog::basic_logger& logger); } // namespace srsran @@ -329,4 +365,76 @@ struct formatter { return format_to(ctx.out(), "{}", to_string(ext_type)); } }; + +template <> +struct formatter { + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return ctx.begin(); + } + + template + auto format(const srsran::gtpu_ie_teid_i& ie, FormatContext& ctx) -> decltype(std::declval().out()) + { + return format_to(ctx.out(), "teid_i={:#x}", ie.teid_i); + } +}; + +template <> +struct formatter { + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return ctx.begin(); + } + + template + auto format(const srsran::gtpu_ie_gtpu_peer_address& ie, FormatContext& ctx) + -> decltype(std::declval().out()) + { + if (srsran::variant_holds_alternative(ie.gtpu_peer_address)) { + auto& addr = srsran::variant_get(ie.gtpu_peer_address); + return format_to(ctx.out(), "peer_addr={}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]); + } + if (srsran::variant_holds_alternative(ie.gtpu_peer_address)) { + auto& addr = srsran::variant_get(ie.gtpu_peer_address); + return format_to(ctx.out(), + "peer_addr={:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}", + addr[0], + addr[1], + addr[2], + addr[3], + addr[4], + addr[5], + addr[6], + addr[7], + addr[8], + addr[9], + addr[10], + addr[11], + addr[12], + addr[13], + addr[14], + addr[15]); + } + return format_to(ctx.out(), "peer_addr={{na}}", ie); + } +}; + +template <> +struct formatter { + template + auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + return ctx.begin(); + } + + template + auto format(const srsran::gtpu_msg_error_indication& err_ind, FormatContext& ctx) + -> decltype(std::declval().out()) + { + return format_to(ctx.out(), "{} {}", err_ind.teid_i, err_ind.gtpu_peer_address); + } +}; } // namespace fmt diff --git a/lib/gtpu/gtpu_tunnel_base_tx.h b/lib/gtpu/gtpu_tunnel_base_tx.h index 81c86766be..19ef1cb17f 100644 --- a/lib/gtpu/gtpu_tunnel_base_tx.h +++ b/lib/gtpu/gtpu_tunnel_base_tx.h @@ -64,7 +64,12 @@ class gtpu_tunnel_base_tx void send_pdu(byte_buffer buf, const ::sockaddr_storage& peer_sockaddr) { if (gtpu_pcap.is_write_enabled()) { - gtpu_pcap.push_pdu(buf.deep_copy()); + auto buf_copy = buf.deep_copy(); + if (buf_copy.is_error()) { + logger.log_warning("Unable to deep copy buffer for PCAP writer"); + } else { + gtpu_pcap.push_pdu(std::move(buf_copy.value())); + } } upper_dn.on_new_pdu(std::move(buf), peer_sockaddr); diff --git a/lib/gtpu/gtpu_tunnel_ngu_rx.h b/lib/gtpu/gtpu_tunnel_ngu_rx.h index da7b7df27b..eb34c1782f 100644 --- a/lib/gtpu/gtpu_tunnel_ngu_rx.h +++ b/lib/gtpu/gtpu_tunnel_ngu_rx.h @@ -121,14 +121,14 @@ class gtpu_tunnel_ngu_rx : public gtpu_tunnel_base_rx if (!pdu.hdr.flags.seq_number || config.t_reordering.count() == 0) { // Forward this SDU straight away. - byte_buffer rx_sdu = gtpu_extract_t_pdu(std::move(pdu)); // header is invalidated after extraction + byte_buffer rx_sdu = gtpu_extract_msg(std::move(pdu)); // header is invalidated after extraction gtpu_rx_sdu_info rx_sdu_info = {std::move(rx_sdu), pdu_session_info.qos_flow_id}; deliver_sdu(rx_sdu_info); return; } uint16_t sn = pdu.hdr.seq_number; - byte_buffer rx_sdu = gtpu_extract_t_pdu(std::move(pdu)); // header is invalidated after extraction + byte_buffer rx_sdu = gtpu_extract_msg(std::move(pdu)); // header is invalidated after extraction // Check out-of-window if (!inside_rx_window(sn)) { diff --git a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp index 0474fb8ae3..0528d95817 100644 --- a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp +++ b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp @@ -124,7 +124,9 @@ bool dpdk::set_ldpc_enc_bbdev_data(::rte_bbdev_enc_op& enc_op, // size is below the requested mbuf size (by default set to the maximum supported value RTE_BBDEV_LDPC_E_MAX_MBUF). ::rte_memcpy(input_data, data.begin(), data_len); // If required, copy the TB-CRC. - ::rte_memcpy(input_data + data_len, &tb_crc[0], tb_crc_len); + if (tb_crc_len > 0) { + ::rte_memcpy(input_data + data_len, &tb_crc[0], tb_crc_len); + } enc_op.ldpc_enc.input.length += data_len + tb_crc_len; // Allocate an mbuf for the output data from the received mempool. @@ -216,10 +218,10 @@ void dpdk::read_ldpc_enc_bbdev_data(::rte_bbdev_enc_op& enc_op, } for (uint seg_idx = 0, end_idx = nof_segments; seg_idx < end_idx; ++seg_idx) { - uint32_t seg_byte_length = static_cast(ceil(static_cast(seg_length) / 8.0)); - uint32_t seg_bit_length_with_padding = seg_byte_length * 8; - srsvec::bit_unpack(span(data.subspan(seg_offset, seg_bit_length_with_padding)), - ::bit_buffer::from_bytes(span(&packed_data[seg_byte_offset], seg_byte_length))); + uint32_t seg_byte_length = units::bits(seg_length).round_up_to_bytes().value(); + srsvec::bit_unpack( + span(data.subspan(seg_offset, seg_length)), + ::bit_buffer::from_bytes(span(&packed_data[seg_byte_offset], seg_byte_length)).first(seg_length)); // In TB mode the segment offset needs to be udpated. if (!cb_mode) { diff --git a/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp b/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp index ebda572276..f31dfbf1c5 100644 --- a/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp +++ b/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp @@ -204,7 +204,8 @@ class dl_sch_pdu_assembler::pdu_log_builder } if (lcid != current_sdu_lcid) { if (current_sdu_lcid != lcid_t::INVALID_LCID) { - fmt::format_to(fmtbuf, "SDU: lcid={} nof_sdus={} total_size={}", current_sdu_lcid, nof_sdus, sum_bytes); + fmt::format_to( + fmtbuf, "{}SDU: lcid={} nof_sdus={} total_size={}", separator(), current_sdu_lcid, nof_sdus, sum_bytes); } current_sdu_lcid = lcid; nof_sdus = 1; @@ -239,10 +240,11 @@ class dl_sch_pdu_assembler::pdu_log_builder // Log pending LCID SDUs. if (current_sdu_lcid != lcid_t::INVALID_LCID) { - fmt::format_to(fmtbuf, "SDU: lcid={} nof_sdus={} total_size={}", current_sdu_lcid, nof_sdus, sum_bytes); + fmt::format_to( + fmtbuf, "{}SDU: lcid={} nof_sdus={} total_size={}", separator(), current_sdu_lcid, nof_sdus, sum_bytes); } - logger.info("DL PDU: ue={} rnti={} size={}: {}", ue_index, rnti, tbs, to_c_str(fmtbuf)); + logger.info("DL PDU: ue={} rnti={} size={}:{}", ue_index, rnti, tbs, to_c_str(fmtbuf)); } private: diff --git a/lib/mac/mac_sched/uci_cell_decoder.cpp b/lib/mac/mac_sched/uci_cell_decoder.cpp index ef3fb6dcb0..3d92be3f65 100644 --- a/lib/mac/mac_sched/uci_cell_decoder.cpp +++ b/lib/mac/mac_sched/uci_cell_decoder.cpp @@ -84,18 +84,18 @@ uci_indication uci_cell_decoder::decode_uci(const mac_uci_indication_message& ms uci_indication ind{}; ind.slot_rx = msg.sl_rx; ind.cell_index = cell_index; - for (unsigned i = 0; i != msg.ucis.size(); ++i) { + for (const auto& mac_uci : msg.ucis) { uci_indication::uci_pdu& uci_pdu = ind.ucis.emplace_back(); - uci_pdu.crnti = msg.ucis[i].rnti; - uci_pdu.ue_index = rnti_table[msg.ucis[i].rnti]; - if (ind.ucis[i].ue_index == INVALID_DU_UE_INDEX) { + uci_pdu.crnti = mac_uci.rnti; + uci_pdu.ue_index = rnti_table[mac_uci.rnti]; + if (uci_pdu.ue_index == INVALID_DU_UE_INDEX) { ind.ucis.pop_back(); logger.info("rnti={}: Discarding UCI PDU. Cause: No UE with provided RNTI exists.", uci_pdu.crnti); continue; } - if (variant_holds_alternative(msg.ucis[i].pdu)) { - const auto& pucch = variant_get(msg.ucis[i].pdu); + if (variant_holds_alternative(mac_uci.pdu)) { + const auto& pucch = variant_get(mac_uci.pdu); uci_indication::uci_pdu::uci_pucch_f0_or_f1_pdu pdu{}; if (pucch.ul_sinr.has_value()) { @@ -140,20 +140,20 @@ uci_indication uci_cell_decoder::decode_uci(const mac_uci_indication_message& ms } // Report ACK for RLF detection purposes. - rlf_handler.handle_ack(ind.ucis[i].ue_index, cell_index, pdu.harqs[j] == mac_harq_ack_report_status::ack); + rlf_handler.handle_ack(uci_pdu.ue_index, cell_index, pdu.harqs[j] == mac_harq_ack_report_status::ack); } } - ind.ucis[i].pdu.emplace(pdu); - } else if (variant_holds_alternative(msg.ucis[i].pdu)) { - const auto& pusch = variant_get(msg.ucis[i].pdu); - auto& pdu = ind.ucis[i].pdu.emplace(); + uci_pdu.pdu.emplace(pdu); + } else if (variant_holds_alternative(mac_uci.pdu)) { + const auto& pusch = variant_get(mac_uci.pdu); + auto& pdu = uci_pdu.pdu.emplace(); if (pusch.harq_info.has_value()) { pdu.harqs = convert_mac_harq_bits_to_sched_harq_values(pusch.harq_info.value().is_valid, pusch.harq_info->payload); // Report ACK for RLF detection purposes. for (unsigned j = 0; j != pdu.harqs.size(); ++j) { - rlf_handler.handle_ack(ind.ucis[i].ue_index, cell_index, pdu.harqs[j] == mac_harq_ack_report_status::ack); + rlf_handler.handle_ack(uci_pdu.ue_index, cell_index, pdu.harqs[j] == mac_harq_ack_report_status::ack); } } @@ -180,13 +180,13 @@ uci_indication uci_cell_decoder::decode_uci(const mac_uci_indication_message& ms // the RLF detection will be based on the PUSCH CRC. However, if the PUSCH UCI has a correctly decoded CSI, we // need to reset the CSI KOs counter. if (pusch.csi_part1_info->is_valid) { - rlf_handler.handle_csi(ind.ucis[i].ue_index, cell_index, true); + rlf_handler.handle_csi(uci_pdu.ue_index, cell_index, true); } } - } else if (variant_holds_alternative(msg.ucis[i].pdu)) { - const auto& pucch = variant_get(msg.ucis[i].pdu); - auto& pdu = ind.ucis[i].pdu.emplace(); + } else if (variant_holds_alternative(mac_uci.pdu)) { + const auto& pucch = variant_get(mac_uci.pdu); + auto& pdu = uci_pdu.pdu.emplace(); if (pucch.ul_sinr.has_value()) { pdu.ul_sinr.emplace(pucch.ul_sinr.value()); @@ -203,7 +203,7 @@ uci_indication uci_cell_decoder::decode_uci(const mac_uci_indication_message& ms // Report ACK for RLF detection purposes. for (const mac_harq_ack_report_status& harq_st : pdu.harqs) { - rlf_handler.handle_ack(ind.ucis[i].ue_index, cell_index, harq_st == mac_harq_ack_report_status::ack); + rlf_handler.handle_ack(uci_pdu.ue_index, cell_index, harq_st == mac_harq_ack_report_status::ack); } } @@ -228,7 +228,7 @@ uci_indication uci_cell_decoder::decode_uci(const mac_uci_indication_message& ms } } // We consider any status other than "crc_pass" as non-decoded CSI. - rlf_handler.handle_csi(ind.ucis[i].ue_index, cell_index, pucch.csi_part1_info->is_valid); + rlf_handler.handle_csi(uci_pdu.ue_index, cell_index, pucch.csi_part1_info->is_valid); } } } diff --git a/lib/ngap/ngap_impl.cpp b/lib/ngap/ngap_impl.cpp index e9067ae691..322953c642 100644 --- a/lib/ngap/ngap_impl.cpp +++ b/lib/ngap/ngap_impl.cpp @@ -191,8 +191,12 @@ void ngap_impl::handle_ul_nas_transport_message(const cu_cp_ul_nas_transport& ms ue_ctxt.logger.log_info("Sending UlNasTransportMessage"); - // Forward message to AMF - ngap_notifier.on_new_message(ngap_msg); + // Schedule transmission of UL NAS transport message to AMF + task_sched.schedule_async_task(msg.ue_index, launch_async([this, ngap_msg](coro_context>& ctx) { + CORO_BEGIN(ctx); + ngap_notifier.on_new_message(ngap_msg); + CORO_RETURN(); + })); } void ngap_impl::handle_message(const ngap_message& msg) @@ -726,11 +730,12 @@ void ngap_impl::handle_error_indication(const asn1::ngap::error_ind_s& msg) } ue_index = ue_ctxt_list[ran_ue_id].ue_ids.ue_index; } else { - logger.info("Received ErrorIndication{}", msg_cause.empty() ? "" : ". Cause{}", msg_cause); + logger.info("Received ErrorIndication{}", msg_cause.empty() ? "" : ". Cause: " + msg_cause); return; } - ue_ctxt_list[ue_index].logger.log_info("Received ErrorIndication{}", msg_cause.empty() ? "" : ". Cause{}", msg_cause); + ue_ctxt_list[ue_index].logger.log_info("Received ErrorIndication{}", + msg_cause.empty() ? "" : ". Cause: " + msg_cause); // Request UE release task_sched.schedule_async_task(ue_index, launch_async([this, ue_index](coro_context>& ctx) { diff --git a/lib/pcap/backend_pcap_writer.h b/lib/pcap/backend_pcap_writer.h index b7e8eba6ea..63e96a0494 100644 --- a/lib/pcap/backend_pcap_writer.h +++ b/lib/pcap/backend_pcap_writer.h @@ -34,10 +34,15 @@ class task_executor; class pcap_pdu_data { public: - pcap_pdu_data(byte_buffer payload_) : payload_buf(std::move(payload_)) {} + explicit pcap_pdu_data(byte_buffer payload_) : payload_buf(std::move(payload_)) {} + pcap_pdu_data(span context_header, byte_buffer payload) { - if (not header_buf.append(byte_buffer{context_header})) { + auto header = byte_buffer::create(context_header); + if (header.is_error()) { + return; + } + if (not header_buf.append(std::move(header.value()))) { return; } if (not payload_buf.append(std::move(payload))) { @@ -93,4 +98,4 @@ class backend_pcap_writer std::atomic is_open{true}; }; -} // namespace srsran \ No newline at end of file +} // namespace srsran diff --git a/lib/pcap/dlt_pcap_impl.cpp b/lib/pcap/dlt_pcap_impl.cpp index a9424b627a..9469b5ef1e 100644 --- a/lib/pcap/dlt_pcap_impl.cpp +++ b/lib/pcap/dlt_pcap_impl.cpp @@ -26,12 +26,12 @@ using namespace srsran; -// DLT PCAP values for different layers -constexpr uint16_t PCAP_NGAP_DLT = 152; -constexpr uint16_t PCAP_E1AP_DLT = 153; -constexpr uint16_t PCAP_F1AP_DLT = 154; -constexpr uint16_t PCAP_E2AP_DLT = 155; -constexpr uint16_t PCAP_GTPU_DLT = 156; +// DLT PCAP values for different layers. +static constexpr uint16_t PCAP_NGAP_DLT = 152; +static constexpr uint16_t PCAP_E1AP_DLT = 153; +static constexpr uint16_t PCAP_F1AP_DLT = 154; +static constexpr uint16_t PCAP_E2AP_DLT = 155; +static constexpr uint16_t PCAP_GTPU_DLT = 156; dlt_pcap_impl::dlt_pcap_impl(uint32_t dlt, const std::string& layer_name_, @@ -57,7 +57,11 @@ void dlt_pcap_impl::push_pdu(const_span pdu) // skip. return; } - writer.write_pdu(byte_buffer(pdu)); + auto pdu_buffer = byte_buffer::create(pdu); + if (pdu_buffer.is_error()) { + return; + } + writer.write_pdu(std::move(pdu_buffer.value())); } void dlt_pcap_impl::push_pdu(byte_buffer pdu) diff --git a/lib/pcap/mac_pcap_impl.cpp b/lib/pcap/mac_pcap_impl.cpp index 7c7df22dec..be4db0f713 100644 --- a/lib/pcap/mac_pcap_impl.cpp +++ b/lib/pcap/mac_pcap_impl.cpp @@ -25,10 +25,10 @@ using namespace srsran; -constexpr uint16_t UDP_DLT = 149; -constexpr uint16_t MAC_DLT = 157; +static constexpr uint16_t UDP_DLT = 149; +static constexpr uint16_t MAC_DLT = 157; -int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, uint8_t* buffer, unsigned int length); +static int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, span buffer); mac_pcap_impl::mac_pcap_impl(const std::string& filename, mac_pcap_type type_, task_executor& backend_exec_) : type(type_), @@ -49,7 +49,11 @@ void mac_pcap_impl::close() void mac_pcap_impl::push_pdu(const mac_nr_context_info& context, const_span pdu) { - push_pdu(context, byte_buffer{pdu}); + auto pdu_buffer = byte_buffer::create(pdu); + if (pdu_buffer.is_error()) { + return; + } + push_pdu(context, std::move(pdu_buffer.value())); } void mac_pcap_impl::push_pdu(const mac_nr_context_info& context, byte_buffer pdu) @@ -59,33 +63,34 @@ void mac_pcap_impl::push_pdu(const mac_nr_context_info& context, byte_buffer pdu return; } - uint8_t context_header[PCAP_CONTEXT_HEADER_MAX] = {}; - int offset = nr_pcap_pack_mac_context_to_buffer(context, &context_header[0], PCAP_CONTEXT_HEADER_MAX); + std::array context_header = {}; + int offset = nr_pcap_pack_mac_context_to_buffer(context, span(context_header)); if (offset < 0) { logger.warning("Discarding MAC PCAP PDU. Cause: Failed to generate header."); return; } if (type == mac_pcap_type::udp) { - pcap_pdu_data buf{0xbeef, 0xdead, MAC_NR_START_STRING, span(context_header, offset), std::move(pdu)}; + pcap_pdu_data buf{ + 0xbeef, 0xdead, MAC_NR_START_STRING, span(context_header).first(offset), std::move(pdu)}; writer.write_pdu(std::move(buf)); } else { - pcap_pdu_data buf{span(context_header, offset), std::move(pdu)}; + pcap_pdu_data buf{span(context_header).first(offset), std::move(pdu)}; writer.write_pdu(std::move(buf)); } } -/// Helper function to serialize MAC NR context -int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, uint8_t* buffer, unsigned int length) +/// Helper function to serialize MAC NR context. +int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, span buffer) { - int offset = 0; - uint16_t tmp16 = {}; - - if (buffer == nullptr || length < PCAP_CONTEXT_HEADER_MAX) { - printf("Error: Writing buffer null or length to small \n"); + if (buffer.size() < PCAP_CONTEXT_HEADER_MAX) { + srslog::fetch_basic_logger("ALL").error("Writing buffer length is too small"); return -1; } + int offset = 0; + uint16_t tmp16 = 0; + /*****************************************************************/ /* Context information (same as written by UDP heuristic clients */ buffer[offset++] = context.radioType; @@ -95,13 +100,13 @@ int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, uint8 /* RNTI */ buffer[offset++] = MAC_NR_RNTI_TAG; tmp16 = htons(context.rnti); - memcpy(buffer + offset, &tmp16, 2); + std::memcpy(buffer.begin() + offset, &tmp16, 2); offset += 2; /* UEId */ buffer[offset++] = MAC_NR_UEID_TAG; tmp16 = htons(context.ueid); - memcpy(buffer + offset, &tmp16, 2); + std::memcpy(buffer.begin() + offset, &tmp16, 2); offset += 2; /* HARQID */ @@ -117,7 +122,7 @@ int nr_pcap_pack_mac_context_to_buffer(const mac_nr_context_info& context, uint8 buffer[offset++] = MAC_NR_FRAME_SUBFRAME_TAG; tmp16 = (context.system_frame_number << 4) | context.sub_frame_number; tmp16 = htons(tmp16); - memcpy(buffer + offset, &tmp16, 2); + std::memcpy(buffer.begin() + offset, &tmp16, 2); offset += 2; /* Data tag immediately preceding PDU */ diff --git a/lib/pdcp/pdcp_entity_rx.cpp b/lib/pdcp/pdcp_entity_rx.cpp index e50dc0530c..6f03245ce9 100644 --- a/lib/pdcp/pdcp_entity_rx.cpp +++ b/lib/pdcp/pdcp_entity_rx.cpp @@ -73,12 +73,14 @@ void pdcp_entity_rx::handle_pdu(byte_buffer_chain buf) return; } - byte_buffer pdu = buf.deep_copy(); - if (pdu.empty()) { + auto pdu_copy = buf.deep_copy(); + if (pdu_copy.is_error()) { metrics_add_dropped_pdus(1); logger.log_error("Dropping PDU: Copy failed. pdu_len={}", buf.length()); return; } + byte_buffer pdu = std::move(pdu_copy.value()); + pdcp_dc_field dc = pdcp_pdu_get_dc(*(pdu.begin())); if (is_srb() || dc == pdcp_dc_field::data) { handle_data_pdu(std::move(pdu)); diff --git a/lib/pdcp/pdcp_entity_tx.cpp b/lib/pdcp/pdcp_entity_tx.cpp index d832c92b3a..80dc98bbce 100644 --- a/lib/pdcp/pdcp_entity_tx.cpp +++ b/lib/pdcp/pdcp_entity_tx.cpp @@ -84,7 +84,13 @@ void pdcp_entity_tx::handle_sdu(byte_buffer buf) // We will need a copy of the SDU for the discard timer when using AM byte_buffer sdu; if (cfg.discard_timer.has_value() && is_am()) { - sdu = buf.deep_copy(); + auto sdu_copy = buf.deep_copy(); + if (sdu_copy.is_error()) { + logger.log_error("Unable to deep copy SDU"); + upper_cn.on_protocol_failure(); + return; + } + sdu = std::move(sdu_copy.value()); } // Perform header compression @@ -223,7 +229,13 @@ void pdcp_entity_tx::write_control_pdu_to_lower_layers(byte_buffer buf) void pdcp_entity_tx::handle_status_report(byte_buffer_chain status) { - byte_buffer buf = {status.begin(), status.end()}; + auto status_buffer = byte_buffer::create(status.begin(), status.end()); + if (status_buffer.is_error()) { + logger.log_warning("Unable to allocate byte_buffer"); + return; + } + + byte_buffer buf = std::move(status_buffer.value()); bit_decoder dec(buf); // Unpack and check PDU header @@ -420,7 +432,14 @@ void pdcp_entity_tx::retransmit_all_pdus() hdr.sn = SN(sdu_info.count); // Pack header - byte_buffer buf = sdu_info.sdu.deep_copy(); + auto buf_copy = sdu_info.sdu.deep_copy(); + if (buf_copy.is_error()) { + logger.log_error("Could not deep copy SDU, dropping SDU and notifying RRC. count={} {}", sdu_info.count, st); + upper_cn.on_protocol_failure(); + return; + } + + byte_buffer buf = std::move(buf_copy.value()); if (not write_data_pdu_header(buf, hdr)) { logger.log_error( "Could not append PDU header, dropping SDU and notifying RRC. count={} {}", sdu_info.count, st); diff --git a/lib/phy/support/CMakeLists.txt b/lib/phy/support/CMakeLists.txt index 0dfe946e87..226478b5f7 100644 --- a/lib/phy/support/CMakeLists.txt +++ b/lib/phy/support/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(srsran_phy_support STATIC interpolator/interpolator_linear_impl.cpp + time_alignment_estimator/time_alignment_estimator_dft_impl.cpp + time_alignment_estimator/time_alignment_estimator_factories.cpp prach_buffer_pool_impl.cpp re_pattern.cpp resource_grid_impl.cpp diff --git a/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.cpp b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.cpp new file mode 100644 index 0000000000..72d8d7e090 --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.cpp @@ -0,0 +1,73 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "time_alignment_estimator_dft_impl.h" +#include "srsran/adt/bounded_bitset.h" +#include "srsran/adt/complex.h" +#include "srsran/adt/span.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h" +#include "srsran/ran/subcarrier_spacing.h" +#include "srsran/srsvec/compare.h" +#include "srsran/srsvec/zero.h" +#include + +using namespace srsran; + +static double to_seconds(unsigned index, unsigned dft_size, subcarrier_spacing scs) +{ + // Calculate DFT sampling rate. + unsigned sampling_rate = dft_size * scs_to_khz(scs) * 1000; + + // Calculate time. + return static_cast(index) / static_cast(sampling_rate); +} + +time_alignment_measurement time_alignment_estimator_dft_impl::estimate(span pilots_lse, + bounded_bitset re_mask, + subcarrier_spacing scs) +{ + span channel_observed_freq = idft->get_input(); + srsvec::zero(channel_observed_freq); + re_mask.for_each(0, re_mask.size(), [&channel_observed_freq, &pilots_lse, i_lse = 0U](unsigned i_re) mutable { + channel_observed_freq[i_re] = pilots_lse[i_lse++]; + }); + + span channel_observed_time = idft->run(); + + static constexpr unsigned HALF_CP_LENGTH = ((144 / 2) * dft_size) / 2048; + std::pair observed_max_delay = srsvec::max_abs_element(channel_observed_time.first(HALF_CP_LENGTH)); + std::pair observed_max_advance = srsvec::max_abs_element(channel_observed_time.last(HALF_CP_LENGTH)); + + double t_align_seconds; + if (observed_max_delay.second >= observed_max_advance.second) { + t_align_seconds = to_seconds(observed_max_delay.first, dft_size, scs); + } else { + t_align_seconds = -to_seconds(HALF_CP_LENGTH - observed_max_advance.first, dft_size, scs); + } + + time_alignment_measurement result; + result.time_alignment = t_align_seconds; + result.min = -to_seconds(HALF_CP_LENGTH, dft_size, scs); + result.max = to_seconds(HALF_CP_LENGTH, dft_size, scs); + result.resolution = to_seconds(1, dft_size, scs); + return result; +} diff --git a/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.h b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.h new file mode 100644 index 0000000000..9d0f75776d --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/bounded_bitset.h" +#include "srsran/phy/generic_functions/dft_processor.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h" + +namespace srsran { + +class time_alignment_estimator_dft_impl : public time_alignment_estimator +{ +public: + /// Required DFT size. + static constexpr unsigned dft_size = 4096; + /// Required DFT direction. + static constexpr dft_processor::direction dft_direction = dft_processor::direction::INVERSE; + + /// \brief Creates the time alignment estimator instance. + /// + /// \remark An assertion is triggered if the DFT processor direction or the DFT size are not as expected. + time_alignment_estimator_dft_impl(std::unique_ptr idft_) : idft(std::move(idft_)) + { + srsran_assert(idft, "Invalid DFT processor."); + srsran_assert(idft->get_direction() == dft_processor::direction::INVERSE, "Invalid DFT processor direction."); + srsran_assert(idft->get_size() == dft_size, "Invalid DFT processor size (i.e., {}).", idft->get_size()); + } + + // See interface for documentation. + time_alignment_measurement + estimate(span symbols, bounded_bitset mask, subcarrier_spacing scs) override; + +private: + /// DFT processor for converting frequency domain to time domain. + std::unique_ptr idft; +}; + +} // namespace srsran diff --git a/lib/phy/support/time_alignment_estimator/time_alignment_estimator_factories.cpp b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_factories.cpp new file mode 100644 index 0000000000..16ab9c26a8 --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_factories.cpp @@ -0,0 +1,62 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h" +#include "time_alignment_estimator_dft_impl.h" +#include "srsran/phy/generic_functions/dft_processor.h" +#include "srsran/phy/generic_functions/generic_functions_factories.h" +#include "srsran/support/srsran_assert.h" +#include + +using namespace srsran; + +namespace { + +class time_alignment_estimator_dft_factory : public time_alignment_estimator_factory +{ +public: + time_alignment_estimator_dft_factory(std::shared_ptr dft_proc_factory_) : + dft_proc_factory(std::move(dft_proc_factory_)) + { + srsran_assert(dft_proc_factory, "Invalid DFT processor factory."); + } + + std::unique_ptr create() override + { + dft_processor::configuration dft_proc_config; + dft_proc_config.size = time_alignment_estimator_dft_impl::dft_size; + dft_proc_config.dir = time_alignment_estimator_dft_impl::dft_direction; + + return std::make_unique(dft_proc_factory->create(dft_proc_config)); + } + +private: + std::shared_ptr dft_proc_factory; +}; + +} // namespace + +std::shared_ptr +srsran::create_time_alignment_estimator_dft_factory(std::shared_ptr dft_proc_factory) +{ + return std::make_shared(std::move(dft_proc_factory)); +} diff --git a/lib/phy/upper/channel_processors/channel_processor_factories.cpp b/lib/phy/upper/channel_processors/channel_processor_factories.cpp index a1bbedd879..be1408c0b0 100644 --- a/lib/phy/upper/channel_processors/channel_processor_factories.cpp +++ b/lib/phy/upper/channel_processors/channel_processor_factories.cpp @@ -466,8 +466,10 @@ class pdsch_processor_lite_factory_sw : public pdsch_processor_factory class pdsch_processor_pool_factory : public pdsch_processor_factory { public: - pdsch_processor_pool_factory(std::shared_ptr factory_, unsigned max_nof_processors_) : - factory(std::move(factory_)), max_nof_processors(max_nof_processors_) + pdsch_processor_pool_factory(std::shared_ptr factory_, + unsigned max_nof_processors_, + bool blocking_) : + factory(std::move(factory_)), max_nof_processors(max_nof_processors_), blocking(blocking_) { srsran_assert(factory, "Invalid PDSCH processor factory."); srsran_assert(max_nof_processors >= 1, @@ -483,7 +485,7 @@ class pdsch_processor_pool_factory : public pdsch_processor_factory processor = factory->create(); } - return std::make_unique(processors); + return std::make_unique(processors, blocking); } std::unique_ptr create(srslog::basic_logger& logger, bool enable_logging_broadcast) override @@ -494,7 +496,7 @@ class pdsch_processor_pool_factory : public pdsch_processor_factory processor = factory->create(logger, enable_logging_broadcast); } - return std::make_unique(processors); + return std::make_unique(processors, blocking); } std::unique_ptr create_validator() override { return factory->create_validator(); } @@ -502,6 +504,7 @@ class pdsch_processor_pool_factory : public pdsch_processor_factory private: std::shared_ptr factory; unsigned max_nof_processors; + bool blocking; }; class prach_detector_factory_sw : public prach_detector_factory @@ -955,9 +958,10 @@ srsran::create_pdsch_lite_processor_factory_sw(std::shared_ptr srsran::create_pdsch_processor_pool(std::shared_ptr pdsch_proc_factory, - unsigned max_nof_processors) + unsigned max_nof_processors, + bool blocking) { - return std::make_shared(std::move(pdsch_proc_factory), max_nof_processors); + return std::make_shared(std::move(pdsch_proc_factory), max_nof_processors, blocking); } std::shared_ptr diff --git a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h index c04d36053b..703b2a909e 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h @@ -37,6 +37,8 @@ namespace srsran { /// Generic hardware-accelerated implementation of the PDSCH encoder. class pdsch_encoder_hw_impl : public pdsch_encoder { + static constexpr units::bytes CODEWORD_MAX_SIZE = pdsch_constants::CODEWORD_MAX_SIZE.round_up_to_bytes(); + public: /// CRC calculators used in shared channels. struct sch_crc { @@ -107,7 +109,7 @@ class pdsch_encoder_hw_impl : public pdsch_encoder static_vector d_segments = {}; /// Buffer for storing temporary encoded and packed codeblock. - static_vector codeblock_packed; + static_vector codeblock_packed; /// \brief Computes the segmentation parameters required by the hardware-accelerated PDSCH encoder function. /// \param[out] hw_cfg Hardware-accelerated PDSCH encoder configuration parameters. diff --git a/lib/phy/upper/channel_processors/pdsch_processor_pool.h b/lib/phy/upper/channel_processors/pdsch_processor_pool.h index 4bc4cd2c5f..a8e5a8247b 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_pool.h @@ -100,7 +100,8 @@ class pdsch_processor_wrapper : private pdsch_processor, private pdsch_processor class pdsch_processor_pool : public pdsch_processor { public: - explicit pdsch_processor_pool(span> processors_) : free_list(processors_.size()) + explicit pdsch_processor_pool(span> processors_, bool blocking_) : + free_list(processors_.size()), blocking(blocking_) { unsigned index = 0; for (std::unique_ptr& processor : processors_) { @@ -115,7 +116,11 @@ class pdsch_processor_pool : public pdsch_processor const pdu_t& pdu) override { // Try to get a worker. - optional index = free_list.try_pop(); + optional index; + + do { + index = free_list.try_pop(); + } while (blocking && !index.has_value()); // If no worker is available. if (!index.has_value()) { @@ -131,6 +136,7 @@ class pdsch_processor_pool : public pdsch_processor private: std::vector processors; detail::pdsch_processor_free_list free_list; + bool blocking; }; } // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/channel_processors/pusch/factories.cpp b/lib/phy/upper/channel_processors/pusch/factories.cpp index c3e7a94ed3..8277a178a7 100644 --- a/lib/phy/upper/channel_processors/pusch/factories.cpp +++ b/lib/phy/upper/channel_processors/pusch/factories.cpp @@ -227,8 +227,10 @@ class pusch_processor_factory_generic : public pusch_processor_factory class pusch_processor_pool_factory : public pusch_processor_factory { public: - pusch_processor_pool_factory(std::shared_ptr factory_, unsigned max_nof_processors_) : - factory(std::move(factory_)), max_nof_processors(max_nof_processors_) + pusch_processor_pool_factory(std::shared_ptr factory_, + unsigned max_nof_processors_, + bool blocking_) : + factory(std::move(factory_)), max_nof_processors(max_nof_processors_), blocking(blocking_) { srsran_assert(factory, "Invalid PUSCH factory."); } @@ -244,7 +246,7 @@ class pusch_processor_pool_factory : public pusch_processor_factory processor = factory->create(); } - return std::make_unique(processors); + return std::make_unique(processors, blocking); } std::unique_ptr create(srslog::basic_logger& logger) override @@ -258,7 +260,7 @@ class pusch_processor_pool_factory : public pusch_processor_factory processor = factory->create(logger); } - return std::make_unique(processors); + return std::make_unique(processors, blocking); } std::unique_ptr create_validator() override { return factory->create_validator(); } @@ -266,6 +268,7 @@ class pusch_processor_pool_factory : public pusch_processor_factory private: std::shared_ptr factory; unsigned max_nof_processors; + bool blocking; }; class ulsch_demultiplex_factory_sw : public ulsch_demultiplex_factory @@ -309,9 +312,11 @@ srsran::create_pusch_processor_factory_sw(pusch_processor_factory_sw_configurati } std::shared_ptr -srsran::create_pusch_processor_pool(std::shared_ptr factory, unsigned max_nof_processors) +srsran::create_pusch_processor_pool(std::shared_ptr factory, + unsigned max_nof_processors, + bool blocking) { - return std::make_shared(std::move(factory), max_nof_processors); + return std::make_shared(std::move(factory), max_nof_processors, blocking); } std::unique_ptr pusch_processor_factory::create(srslog::basic_logger& logger) diff --git a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp index 84bde612cb..f9b504f125 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp @@ -91,6 +91,12 @@ pusch_decoder_buffer& pusch_decoder_impl::new_data(span pusch_decoder_notifier& notifier, const pusch_decoder::configuration& cfg) { + internal_states previous_state = current_state.exchange(internal_states::collecting); + srsran_assert(previous_state == internal_states::idle, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::idle), + to_string(previous_state)); + transport_block = transport_block_; unique_rm_buffer = std::move(unique_rm_buffer_); result_notifier = ¬ifier; @@ -133,6 +139,12 @@ pusch_decoder_buffer& pusch_decoder_impl::new_data(span span pusch_decoder_impl::get_next_block_view(unsigned block_size) { + internal_states state = current_state.load(); + srsran_assert(state == internal_states::collecting, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::collecting), + state); + // Makes sure the block size does not overflow the buffer. srsran_assert(softbits_count + block_size <= softbits_buffer.size(), "The sum of current buffer number of elements (i.e., {}) and the block size (i.e., {}), exceeds the " @@ -146,6 +158,12 @@ span pusch_decoder_impl::get_next_block_view(unsigned bloc void pusch_decoder_impl::set_nof_softbits(units::bits nof_softbits) { + internal_states state = current_state.load(); + srsran_assert(state == internal_states::collecting, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::collecting), + to_string(state)); + nof_ulsch_softbits.emplace(nof_softbits); unsigned modulation_order = get_bits_per_symbol(current_config.mod); @@ -188,6 +206,12 @@ void pusch_decoder_impl::set_nof_softbits(units::bits nof_softbits) void pusch_decoder_impl::on_new_softbits(span softbits) { + internal_states state = current_state.load(); + srsran_assert(state == internal_states::collecting, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::collecting), + state); + span block = get_next_block_view(softbits.size()); // Copy only if the soft bits do not match. @@ -213,6 +237,7 @@ void pusch_decoder_impl::on_new_softbits(span softbi void pusch_decoder_impl::on_end_softbits() { + // Verify the number of bits match with the configured one. srsran_assert(!nof_ulsch_softbits.has_value() || (nof_ulsch_softbits.value() == units::bits(softbits_count)), "The number of UL-SCH softbits, i.e., {}, does not match the expected value, i.e., {}.", softbits_count, @@ -231,9 +256,32 @@ void pusch_decoder_impl::on_end_softbits() "The number of provided softbits (i.e. {}), does not match the expected number (i.e. {}).", softbits_count, nof_ulsch_softbits->value()); + + // Try to transition from collecting to decoding. + internal_states expected_state = internal_states::collecting; + if (!current_state.compare_exchange_strong(expected_state, internal_states::decoding)) { + // If the previous state was not collecting, the only valid state is decoded. + internal_states state = current_state.load(); + srsran_assert(state == internal_states::decoded, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::decoded), + to_string(state)); + + // In this case, all the codeblocks have already been decoded. Notify the completion. + join_and_notify(); + } + + // All codeblocks have already been forked. There is nothing else to do. return; } + // Transition to decoding. + internal_states previous_state = current_state.exchange(internal_states::decoding); + srsran_assert(previous_state == internal_states::collecting, + "Invalid state. It was expected to be {} but it was {}.", + to_string(internal_states::collecting), + to_string(previous_state)); + srsran_assert(!nof_ulsch_softbits.has_value(), "The number of CW softbits has been provided and not all CB decoding tasks have been dispatched."); @@ -335,6 +383,12 @@ void pusch_decoder_impl::fork_codeblock_task(unsigned cb_id) void pusch_decoder_impl::join_and_notify() { + // Transition to decoded if the current state is collecting. In this case, skip notifying. + internal_states expected_state_collecting = internal_states::collecting; + if (current_state.compare_exchange_strong(expected_state_collecting, internal_states::decoded)) { + return; + } + unsigned nof_cbs = codeblock_llrs.size(); span cb_crcs = unique_rm_buffer->get_codeblocks_crc(); @@ -385,6 +439,14 @@ void pusch_decoder_impl::join_and_notify() // Finally report decoding result. result_notifier->on_sch_data(stats); + + // Transition back to idle. + internal_states previous_state = current_state.exchange(internal_states::idle); + srsran_assert((previous_state == internal_states::decoding) || (previous_state == internal_states::decoded), + "Invalid state. It expected to be {} or {} but it was {}.", + to_string(internal_states::decoding), + to_string(internal_states::decoded), + to_string(previous_state)); } unsigned pusch_decoder_impl::concatenate_codeblocks() diff --git a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h index 75c76bb4b4..7d3fb20ffb 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h @@ -30,6 +30,7 @@ #include "srsran/ran/pusch/pusch_constants.h" #include "srsran/support/executors/task_executor.h" #include "srsran/support/memory_pool/concurrent_thread_local_object_pool.h" +#include namespace srsran { @@ -108,6 +109,51 @@ class pusch_decoder_impl : public pusch_decoder, private pusch_decoder_buffer void set_nof_softbits(units::bits nof_softbits) override; private: + /// Internal states for verifying the component coherence. + enum class internal_states : uint8_t { + /// \brief The decoder is not configured for decoding. + /// + /// The decoder only accepts new transmissions. It transitions to \c collecting when a new transmission is + /// configured. + /// + idle = 0, + /// \brief The decoder is collecting soft bits. + /// + /// It can simultaneously decode. It transitions to \c decoded if it finishes decoding prior \c on_end_softbits is + /// called. In this case, the decoder shall not notify the ending of processing. + /// + /// It transitions to \c decoding if \c on_end_softbits is called before the asynchronous decoding finishes. + collecting, + /// \brief The decoder does not accept soft bits and it is decoding. + /// + /// It transitions to \c idle when it finishes decoding. In this case, the decoder shall notify the end of the + /// processing. + decoding, + /// \brief The decoder finished decoding all codeblocks asynchronously before \c on_end_softbits is called. + /// + /// It transitions to \c idle when \c on_end_softbits is called. In this case, the decoder notifies the end of the + /// processing. + decoded + }; + + /// Convert an internal state to a string. + static const char* to_string(internal_states state) + { + switch (state) { + default: + case internal_states::idle: + return "idle"; + case internal_states::collecting: + return "collecting"; + case internal_states::decoding: + return "decoding"; + case internal_states::decoded: + return "decoded"; + } + } + + /// Current internal state. + std::atomic current_state = {internal_states::idle}; /// Pointer to an LDPC segmenter. std::unique_ptr segmenter; /// Pointer to a codeblock decoder. diff --git a/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h index f5aed6b8ae..afdb684fc8 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h @@ -109,7 +109,8 @@ class pusch_processor_pool : public pusch_processor { public: /// Creates a PUSCH processor pool from a list of processors. Ownership is transferred to the pool. - explicit pusch_processor_pool(span> processors_) : free_list(processors_.size()) + explicit pusch_processor_pool(span> processors_, bool blocking_) : + free_list(processors_.size()), blocking(blocking_) { unsigned index = 0; for (std::unique_ptr& processor : processors_) { @@ -125,11 +126,24 @@ class pusch_processor_pool : public pusch_processor const resource_grid_reader& grid, const pdu_t& pdu) override { - // Try to get a worker. - optional index = free_list.try_pop(); + // Try to get an available worker. + optional index; + do { + index = free_list.try_pop(); + } while (blocking && !index.has_value()); // If no worker is available. if (!index.has_value()) { + // Prepare dummy results. + pusch_processor_result_data results; + results.data.tb_crc_ok = false; + results.data.nof_codeblocks_total = 0; + results.data.ldpc_decoder_stats.reset(); + results.csi = channel_state_information(); + + // Report SCH results. + notifier.on_sch(results); + srslog::fetch_basic_logger("PHY").warning("Insufficient number of PUSCH processors. Dropping PUSCH {:s}.", pdu); return; } @@ -141,6 +155,7 @@ class pusch_processor_pool : public pusch_processor private: std::vector processors; detail::pusch_processor_free_list free_list; + bool blocking; }; } // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/signal_processors/CMakeLists.txt b/lib/phy/upper/signal_processors/CMakeLists.txt index 0fcfa068ed..6cae1b1c1e 100644 --- a/lib/phy/upper/signal_processors/CMakeLists.txt +++ b/lib/phy/upper/signal_processors/CMakeLists.txt @@ -19,14 +19,16 @@ # set(SOURCES + pucch/dmrs_pucch_processor_format1_impl.cpp + pucch/dmrs_pucch_processor_format2_impl.cpp + srs/srs_estimator_factory.cpp + srs/srs_estimator_generic_impl.cpp dmrs_pbch_processor_impl.cpp dmrs_pdcch_processor_impl.cpp dmrs_pdsch_processor_impl.cpp dmrs_pusch_estimator_impl.cpp nzp_csi_rs_generator_impl.cpp port_channel_estimator_average_impl.cpp - pucch/dmrs_pucch_processor_format1_impl.cpp - pucch/dmrs_pucch_processor_format2_impl.cpp signal_processor_factories.cpp pss_processor_impl.cpp sss_processor_impl.cpp diff --git a/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp b/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp index 0c6577a2c3..76dd02791c 100644 --- a/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp +++ b/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp @@ -30,6 +30,7 @@ #include "srsran/srsvec/mean.h" #include "srsran/srsvec/prod.h" #include "srsran/srsvec/sc_prod.h" +#include "srsran/srsvec/unwrap.h" #include "srsran/srsvec/zero.h" using namespace srsran; @@ -44,6 +45,22 @@ static constexpr std::array RC_FILTER = { 0.3235207, 0.3073415, 0.2814857, 0.2475302, 0.2075139, 0.1637874, 0.1188406, 0.0751249, 0.0348830, 0.0000000, -0.0281126, -0.0485918, -0.0611526, -0.0660711, -0.0641253}; +/// Maximum number of virtual pilots used for estimation at the edges. +constexpr unsigned MAX_V_PILOTS = 12; + +/// Create an array indexing the virtual pilots. +template +static constexpr std::array create_index_array() +{ + std::array out; + int count = 0; + for (int& v : out) { + v = count++; + } + return out; +} +static const std::array indices = create_index_array(); + namespace { /// \brief Provides access to customized raised-cosine filters. /// @@ -96,44 +113,29 @@ class filter_type }; } // namespace +/// \brief Computes some virtual pilots to improve estimation at the edges. +/// +/// \param[out] out Computed virtual pilots. +/// \param[in] in_abs Modulus of the true pilots used for extrapolation. +/// \param[in] in_arg Phase angle of the true pilots used for extrapolation - it is assumed unwrapped. +/// \param[in] is_start Direction flag: If true, virtual pilots are computed to precede the true ones. If false, +/// virtual pilots will follow the true ones. +static void compute_v_pilots(span out, span in_abs, span in_arg, bool is_start); + +/// Adds virtual pilots at both ends of \c old_pilots (\c old_pilots is assumed a centered subspan of new_pilots). +static void add_v_pilots(span new_pilots, span old_pilots); + /// \brief Applies frequency domain smoothing strategy. -/// \param[out] filtered_pilots_lse Smoothed pilots estimates. -/// \param[in] pilots_lse Pilots estimates. -/// \param[in] nof_rb Number of resource elements. -/// \param[in] stride Reference signals stride in frequency domain. -/// \param[in] fd_smoothing_strategy Frequency domain smoothing strategy. -static void apply_fd_smoothing(span filtered_pilots_lse, - span pilots_lse, +/// \param[out] enlarged_filtered_pilots_out Smoothed pilots estimates. +/// \param[in] enlarged_pilots_in Pilots estimates. +/// \param[in] nof_rb Number of resource blocks. +/// \param[in] stride Reference signals stride in frequency domain. +/// \param[in] fd_smoothing_strategy Frequency domain smoothing strategy. +static void apply_fd_smoothing(span enlarged_filtered_pilots_out, + span enlarged_pilots_in, unsigned nof_rb, unsigned stride, - port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy) -{ - switch (fd_smoothing_strategy) { - case port_channel_estimator_fd_smoothing_strategy::mean: - std::fill(filtered_pilots_lse.begin(), filtered_pilots_lse.end(), srsvec::mean(pilots_lse)); - break; - case port_channel_estimator_fd_smoothing_strategy::filter: { - // Generate a low pass filter. - filter_type rc(nof_rb, stride); - - // Apply filter. - srsvec::convolution_same(filtered_pilots_lse, pilots_lse, rc.rc_filter); - - // Compensate tails (note that we take the reverse iterator for the back tail). - auto tail_front = filtered_pilots_lse.begin(); - auto tail_back = filtered_pilots_lse.rbegin(); - for (const auto cc : rc.tail_correction) { - *tail_front++ *= cc; - *tail_back++ *= cc; - } - } break; - case port_channel_estimator_fd_smoothing_strategy::none: - default: - // No strategy. - srsvec::copy(filtered_pilots_lse, pilots_lse); - break; - } -} + port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy); /// \brief Extracts channel observations corresponding to DM-RS pilots from the resource grid for one layer, one hop /// and for the selected port. @@ -172,16 +174,18 @@ static float estimate_noise(const dmrs_symbol_list& pilots, /// \brief Estimates the time alignment based on one hop. /// -/// \param[in] pilots_lse The estimated channel (only for REs carrying DM-RS). -/// \param[in] pattern DM-RS pattern for the current layer. -/// \param[in] hop Intra-slot frequency hopping index: 0 for first position (before hopping), 1 for second -/// position (after hopping). -/// \param[in] idft Inverse DFT processor. +/// \param[in] pilots_lse The estimated channel (only for REs carrying DM-RS). +/// \param[in] pattern DM-RS pattern for the current layer. +/// \param[in] hop Intra-slot frequency hopping index: 0 for first position (before hopping), 1 for second +/// position (after hopping). +/// \param[in] scs Subcarrier spacing. +/// \param[in] ta_estimator Time alignment estimator. /// \return The estimated time alignment as a number of samples (the sampling frequency is given by the DFT processor). static float estimate_time_alignment(span pilots_lse, const port_channel_estimator::layer_dmrs_pattern& pattern, unsigned hop, - dft_processor* idft); + subcarrier_spacing scs, + time_alignment_estimator& ta_estimator); // Returns the interpolator configuration for the given RE pattern. static interpolator::configuration configure_interpolator(const bounded_bitset& re_mask) @@ -223,7 +227,6 @@ void port_channel_estimator_average_impl::compute(channel_estimate& es rsrp /= static_cast(nof_dmrs_pilots); epre /= static_cast(nof_dmrs_pilots); - time_alignment_s /= (DFT_SIZE * scs_to_khz(cfg.scs) * 1000.0F); estimate.set_rsrp(rsrp, port, i_layer); estimate.set_epre(epre, port, i_layer); @@ -257,9 +260,9 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti "Frequency hopping requested but not configured."); // Auxiliary buffers for pilot computations. - std::array aux_pilot_products; - std::array aux_pilots_lse; - std::array aux_pilots_lse_rc; + std::array aux_pilot_products; + std::array aux_pilots_lse; + std::array aux_pilots_lse_rc; const layer_dmrs_pattern& pattern = cfg.dmrs_pattern[i_layer]; @@ -279,7 +282,7 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti } span pilot_products = span(aux_pilot_products).first(pilots.size().nof_subc); - span pilots_lse = span(aux_pilots_lse).first(pilots.size().nof_subc); + span pilots_lse = span(aux_pilots_lse).subspan(MAX_V_PILOTS, pilots.size().nof_subc); srsvec::prod_conj(rx_pilots.get_symbol(0, i_layer), pilots.get_symbol(hop_offset, i_layer), pilots_lse); epre += std::real(srsvec::dot_prod(rx_pilots.get_symbol(0, i_layer), rx_pilots.get_symbol(0, i_layer))); @@ -303,10 +306,21 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti const bounded_bitset& hop_rb_mask = (hop == 0) ? pattern.rb_mask : pattern.rb_mask2; interpolator::configuration interpolator_cfg = configure_interpolator(pattern.re_pattern); - // Apply a smoothing strategy to remove some noise ("high-time" components). - span filtered_pilots_lse = span(aux_pilots_lse_rc).first(pilots_lse.size()); - apply_fd_smoothing( - filtered_pilots_lse, pilots_lse, hop_rb_mask.count(), interpolator_cfg.stride, fd_smoothing_strategy); + // Apply a smoothing strategy to remove some noise ("high-time" components). Note that pilots_lse and + // filtered_pilots_lse have some empty space at both sides, which we include with the enlarged version. + span filtered_pilots_lse = span(aux_pilots_lse_rc).subspan(MAX_V_PILOTS, pilots_lse.size()); + span enlarged_pilots_lse = span(aux_pilots_lse).first(pilots_lse.size() + 2 * MAX_V_PILOTS); + span enlarged_filtered_pilots_lse = span(aux_pilots_lse_rc).first(pilots_lse.size() + 2 * MAX_V_PILOTS); + if (fd_smoothing_strategy != port_channel_estimator_fd_smoothing_strategy::filter) { + // Enlarging is only necessary with the filter smoothing strategy. + enlarged_pilots_lse = pilots_lse; + enlarged_filtered_pilots_lse = filtered_pilots_lse; + } + apply_fd_smoothing(enlarged_filtered_pilots_lse, + enlarged_pilots_lse, + hop_rb_mask.count(), + interpolator_cfg.stride, + fd_smoothing_strategy); rsrp += std::real(srsvec::dot_prod(filtered_pilots_lse, filtered_pilots_lse)) * beta_scaling * beta_scaling * static_cast(nof_dmrs_symbols); @@ -314,7 +328,7 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti noise_var += estimate_noise(pilots, rx_pilots, filtered_pilots_lse, beta_scaling, nof_dmrs_symbols, hop_offset, i_layer); - time_alignment_s += estimate_time_alignment(filtered_pilots_lse, pattern, hop, idft.get()); + time_alignment_s += estimate_time_alignment(filtered_pilots_lse, pattern, hop, cfg.scs, *ta_estimator); // Interpolate frequency domain. span ce_freq = span(freq_response).first(hop_rb_mask.count() * NRE); @@ -408,7 +422,8 @@ static float estimate_noise(const dmrs_symbol_list& pilots, static float estimate_time_alignment(span pilots_lse, const port_channel_estimator::layer_dmrs_pattern& pattern, unsigned hop, - dft_processor* idft) + subcarrier_spacing scs, + time_alignment_estimator& ta_estimator) { const bounded_bitset& hop_rb_mask = (hop == 0) ? pattern.rb_mask : pattern.rb_mask2; @@ -425,19 +440,117 @@ static float estimate_time_alignment(span re_mask.size(), pilots_lse.size()); - span channel_observed_freq = idft->get_input(); - srsvec::zero(channel_observed_freq); - re_mask.for_each(0, re_mask.size(), [&channel_observed_freq, &pilots_lse, i_lse = 0U](unsigned i_re) mutable { - channel_observed_freq[i_re] = pilots_lse[i_lse++]; - }); + return ta_estimator.estimate(pilots_lse, re_mask, scs).time_alignment; +} - span channel_observed_time = idft->run(); +static void apply_fd_smoothing(span enlarged_filtered_pilots_out, + span enlarged_pilots_in, + unsigned nof_rb, + unsigned stride, + port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy) +{ + switch (fd_smoothing_strategy) { + case port_channel_estimator_fd_smoothing_strategy::mean: + std::fill( + enlarged_filtered_pilots_out.begin(), enlarged_filtered_pilots_out.end(), srsvec::mean(enlarged_pilots_in)); + break; + case port_channel_estimator_fd_smoothing_strategy::filter: { + // Generate a low pass filter. + filter_type rc(nof_rb, stride); + + // Recover data part of extended_pilots_lse + span pilots_lse = + enlarged_pilots_in.subspan(MAX_V_PILOTS, enlarged_pilots_in.size() - 2 * MAX_V_PILOTS); + // Create virtual pilots. + unsigned nof_v_pilots = std::min(MAX_V_PILOTS, rc.rc_filter.size() / 2); + if (nof_rb == 1) { + nof_v_pilots = pilots_lse.size() / nof_rb; + } + span enlarged_pilots = + enlarged_pilots_in.subspan(MAX_V_PILOTS - nof_v_pilots, pilots_lse.size() + 2 * nof_v_pilots); + add_v_pilots(enlarged_pilots, pilots_lse); + + span enlarged_filtered_pilots = + enlarged_filtered_pilots_out.subspan(MAX_V_PILOTS - nof_v_pilots, pilots_lse.size() + 2 * nof_v_pilots); + // Apply filter. + srsvec::convolution_same(enlarged_filtered_pilots, enlarged_pilots, rc.rc_filter); + } break; + + case port_channel_estimator_fd_smoothing_strategy::none: + default: + // No strategy. + srsvec::copy(enlarged_filtered_pilots_out, enlarged_pilots_in); + break; + } +} + +static void add_v_pilots(span new_pilots, span old_pilots) +{ + std::array aux_base_abs; + std::array aux_base_arg; + + unsigned nof_pilots = old_pilots.size(); + unsigned nof_v_pilots = new_pilots.size() - nof_pilots; + srsran_assert((nof_v_pilots >= 2) && ((nof_v_pilots & 1U) == 0U), + "The total number of virtual pilots should be an even number not lower than 2, provided {}.", + nof_v_pilots); + nof_v_pilots /= 2; + + // Compute virtual pilots at the beginning of the band. + span base_pilots = old_pilots.first(nof_v_pilots); + span base_abs = span(aux_base_abs).first(nof_v_pilots); + std::transform(base_pilots.begin(), base_pilots.end(), base_abs.begin(), [](cf_t a) { return std::abs(a); }); + + span base_arg = span(aux_base_arg).first(nof_v_pilots); + srsvec::unwrap_arguments(base_arg, base_pilots); + compute_v_pilots(new_pilots.first(nof_v_pilots), base_abs, base_arg, /* is_start = */ true); + + // Compute virtual pilots at the end of the band. + base_pilots = old_pilots.last(nof_v_pilots); + std::transform(base_pilots.begin(), base_pilots.end(), base_abs.begin(), [](cf_t a) { return std::abs(a); }); + + srsvec::unwrap_arguments(base_arg, base_pilots); + compute_v_pilots(new_pilots.last(nof_v_pilots), base_abs, base_arg, /* is start = */ false); +} + +static void compute_v_pilots(span out, span in_abs, span in_arg, bool is_start) +{ + unsigned nof_v_pilots = out.size(); + srsran_assert(nof_v_pilots < 13, "The maximum number of virtual pilots is 12, requested {}.", nof_v_pilots); + srsran_assert(in_abs.size() == nof_v_pilots, + "Input and output should have the same size, provided {} and {}.", + in_abs.size(), + nof_v_pilots); + srsran_assert(in_arg.size() == nof_v_pilots, + "Input and output should have the same size, provided {} and {}.", + in_arg.size(), + nof_v_pilots); + span used_indices = span(indices).first(nof_v_pilots); + + float mean_x = static_cast(nof_v_pilots * (nof_v_pilots - 1)) / 2.0F / nof_v_pilots; + float norm_x_sq = static_cast((nof_v_pilots - 1) * nof_v_pilots * (2 * nof_v_pilots - 1)) / 6.0F; + + float mean_abs = srsvec::mean(in_abs); + float slope_abs = srsvec::dot_prod(in_abs, used_indices, 0.0F); + slope_abs -= mean_x * mean_abs * nof_v_pilots; + slope_abs /= (norm_x_sq - nof_v_pilots * mean_x * mean_x); + + float intercept_abs = mean_abs - slope_abs * mean_x; + + float mean_arg = srsvec::mean(in_arg); + float slope_arg = srsvec::dot_prod(in_arg, used_indices, 0.0F); + slope_arg -= mean_x * mean_arg * nof_v_pilots; + slope_arg /= (norm_x_sq - nof_v_pilots * mean_x * mean_x); + + float intercept_arg = mean_arg - slope_arg * mean_x; + + int v_offset = -nof_v_pilots; + if (!is_start) { + v_offset = nof_v_pilots; + } - static constexpr unsigned HALF_CP_LENGTH = ((144 / 2) * DFT_SIZE) / 2048; - std::pair observed_max_delay = srsvec::max_abs_element(channel_observed_time.first(HALF_CP_LENGTH)); - std::pair observed_max_advance = srsvec::max_abs_element(channel_observed_time.last(HALF_CP_LENGTH)); - if (observed_max_delay.second >= observed_max_advance.second) { - return static_cast(observed_max_delay.first); + for (unsigned i_pilot = 0; i_pilot != nof_v_pilots; ++i_pilot) { + int i_virtual = static_cast(i_pilot) + v_offset; + out[i_pilot] = std::polar(slope_abs * i_virtual + intercept_abs, slope_arg * i_virtual + intercept_arg); } - return -static_cast(HALF_CP_LENGTH - observed_max_advance.first); } diff --git a/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.h b/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.h index 388829b862..3c242dda5d 100644 --- a/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.h +++ b/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.h @@ -24,6 +24,7 @@ #include "srsran/phy/generic_functions/dft_processor.h" #include "srsran/phy/support/interpolator.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h" #include "srsran/phy/upper/signal_processors/port_channel_estimator.h" #include "srsran/phy/upper/signal_processors/port_channel_estimator_parameters.h" @@ -49,17 +50,14 @@ class port_channel_estimator_average_impl : public port_channel_estimator /// Constructor - Sets the internal interpolator and inverse DFT processor of size \c DFT_SIZE. port_channel_estimator_average_impl(std::unique_ptr interp, - std::unique_ptr idft_proc, + std::unique_ptr ta_estimator_, port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy_) : - fd_smoothing_strategy(fd_smoothing_strategy_), freq_interpolator(std::move(interp)), idft(std::move(idft_proc)) + fd_smoothing_strategy(fd_smoothing_strategy_), + freq_interpolator(std::move(interp)), + ta_estimator(std::move(ta_estimator_)) { srsran_assert(freq_interpolator, "Invalid interpolator."); - srsran_assert(idft->get_direction() == dft_processor::direction::INVERSE, - "The port channel estimator requires an inverse (not direct) DFT processor."); - srsran_assert(idft->get_size() == DFT_SIZE, - "The port channel estimator requires an iDFT of size {}, provided {}.", - static_cast(DFT_SIZE), - idft->get_size()); + srsran_assert(ta_estimator, "Invalid TA estimator."); } // See interface for documentation. @@ -88,8 +86,8 @@ class port_channel_estimator_average_impl : public port_channel_estimator /// REs without pilots. std::unique_ptr freq_interpolator; - /// Inverse DFT processor of size \c DFT_SIZE. - std::unique_ptr idft; + /// Time alignment estimator. + std::unique_ptr ta_estimator; /// Buffer of received signal samples corresponding to pilots. dmrs_symbol_list rx_pilots; diff --git a/lib/phy/upper/signal_processors/signal_processor_factories.cpp b/lib/phy/upper/signal_processors/signal_processor_factories.cpp index ef70fd4708..187994d605 100644 --- a/lib/phy/upper/signal_processors/signal_processor_factories.cpp +++ b/lib/phy/upper/signal_processors/signal_processor_factories.cpp @@ -34,6 +34,7 @@ #include "sss_processor_impl.h" #include "srsran/phy/support/support_factories.h" #include "srsran/phy/support/support_formatters.h" +#include "srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h" #include "srsran/phy/upper/signal_processors/signal_processor_formatters.h" using namespace srsran; @@ -235,10 +236,10 @@ class nzp_csi_rs_generator_pool_factory : public nzp_csi_rs_generator_factory class port_channel_estimator_factory_sw : public port_channel_estimator_factory { public: - explicit port_channel_estimator_factory_sw(std::shared_ptr dft_f) : - dft_factory(std::move(dft_f)) + explicit port_channel_estimator_factory_sw(std::shared_ptr ta_estimator_factory_) : + ta_estimator_factory(std::move(ta_estimator_factory_)) { - srsran_assert(dft_factory, "Invalid DFT factory."); + srsran_assert(ta_estimator_factory, "Invalid TA estimator factory."); } std::unique_ptr @@ -246,17 +247,12 @@ class port_channel_estimator_factory_sw : public port_channel_estimator_factory { std::unique_ptr interp = create_interpolator(); - dft_processor::configuration idft_config; - idft_config.size = port_channel_estimator_average_impl::DFT_SIZE; - idft_config.dir = dft_processor::direction::INVERSE; - std::unique_ptr idft_proc = dft_factory->create(idft_config); - return std::make_unique( - std::move(interp), std::move(idft_proc), fd_smoothing_strategy); + std::move(interp), ta_estimator_factory->create(), fd_smoothing_strategy); } private: - std::shared_ptr dft_factory; + std::shared_ptr ta_estimator_factory; }; class pss_processor_factory_sw : public pss_processor_factory @@ -320,9 +316,9 @@ srsran::create_nzp_csi_rs_generator_pool_factory(std::shared_ptr -srsran::create_port_channel_estimator_factory_sw(std::shared_ptr dft_f) +srsran::create_port_channel_estimator_factory_sw(std::shared_ptr ta_estimator_factory) { - return std::make_shared(std::move(dft_f)); + return std::make_shared(std::move(ta_estimator_factory)); } std::shared_ptr srsran::create_pss_processor_factory_sw() diff --git a/lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp b/lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp new file mode 100644 index 0000000000..570a61737e --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp @@ -0,0 +1,57 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h" +#include "srs_estimator_generic_impl.h" + +using namespace srsran; + +namespace { + +class srs_estimator_factory_generic : public srs_estimator_factory +{ +public: + srs_estimator_factory_generic(std::shared_ptr sequence_generator_factory_) : + sequence_generator_factory(std::move(sequence_generator_factory_)) + { + srsran_assert(sequence_generator_factory, "Invalid sequence generator factory."); + } + + std::unique_ptr create() override + { + srs_estimator_generic_impl::dependencies deps; + deps.sequence_generator = sequence_generator_factory->create(); + + return std::make_unique(std::move(deps)); + } + +private: + std::shared_ptr sequence_generator_factory; +}; + +} // namespace + +std::shared_ptr srsran::create_srs_estimator_generic_factory( + std::shared_ptr sequence_generator_factory) +{ + return std::make_shared(std::move(sequence_generator_factory)); +} diff --git a/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp new file mode 100644 index 0000000000..7dbce96915 --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp @@ -0,0 +1,96 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srs_estimator_generic_impl.h" +#include "srsran/phy/constants.h" +#include "srsran/phy/support/resource_grid_reader.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_result.h" +#include "srsran/ran/cyclic_prefix.h" +#include "srsran/ran/srs/srs_bandwidth_configuration.h" +#include "srsran/ran/srs/srs_information.h" +#include "srsran/srsvec/dot_prod.h" + +using namespace srsran; + +void srs_estimator_generic_impl::extract_sequence(span sequence, + const resource_grid_reader& grid, + unsigned i_rx_port, + unsigned i_symbol, + unsigned initial_subcarrier, + unsigned comb_size) +{ + bounded_bitset mask(sequence.size() * comb_size); + + for (unsigned i = 0, i_end = sequence.size(); i != i_end; ++i) { + mask.set(comb_size * i); + } + + grid.get(sequence, i_rx_port, i_symbol, initial_subcarrier, mask); +} + +srs_estimator_result srs_estimator_generic_impl::estimate(const resource_grid_reader& grid, + const srs_estimator_configuration& config) +{ + unsigned nof_symbols = static_cast(config.resource.nof_symbols); + unsigned nof_symbols_per_slot = get_nsymb_per_slot(cyclic_prefix::NORMAL); + srsran_assert(config.resource.start_symbol.value() + nof_symbols <= nof_symbols_per_slot, + "The start symbol index (i.e., {}) plus the number of symbols (i.e., {}) exceeds the number of symbols " + "per slot (i.e., {})", + config.resource.start_symbol, + nof_symbols, + nof_symbols_per_slot); + + srs_estimator_result result; + result.channel_matrix = + srs_channel_matrix(config.ports.size(), static_cast(config.resource.nof_antenna_ports)); + + for (uint8_t i_rx_port : config.ports) { + for (unsigned i_antenna_port = 0, i_antenna_port_end = static_cast(config.resource.nof_antenna_ports); + i_antenna_port != i_antenna_port_end; + ++i_antenna_port) { + cf_t coefficient = 0; + for (unsigned i_symbol = config.resource.start_symbol.value(), + i_symbol_end = config.resource.start_symbol.value() + nof_symbols; + i_symbol != i_symbol_end; + ++i_symbol) { + // Generate SRS information for a given SRS antenna port and symbol. + srs_information info = get_srs_information(config.resource, i_antenna_port, i_symbol); + + // Generate sequence. + static_vector sequence(info.sequence_length); + deps.sequence_generator->generate(sequence, info.sequence_group, info.sequence_number, info.alpha); + + static_vector rx_sequence(info.sequence_length); + extract_sequence(rx_sequence, grid, i_rx_port, i_symbol, info.mapping_initial_subcarrier, info.comb_size); + + coefficient += srsvec::dot_prod(rx_sequence, sequence) / static_cast(sequence.size()); + } + + coefficient /= static_cast(nof_symbols); + + result.channel_matrix.set_coefficient(coefficient, i_rx_port, i_antenna_port); + } + } + + return result; +} diff --git a/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h new file mode 100644 index 0000000000..24739d628e --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h @@ -0,0 +1,77 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/phy/constants.h" +#include "srsran/phy/upper/sequence_generators/low_papr_sequence_generator.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator.h" +#include + +namespace srsran { + +/// Implements a generic Sounding Reference Signal estimator. +class srs_estimator_generic_impl : public srs_estimator +{ +public: + /// Collects the component dependencies. + struct dependencies { + /// Sequence generator. + std::unique_ptr sequence_generator; + }; + + srs_estimator_generic_impl(dependencies deps_) : deps(std::move(deps_)) + { + srsran_assert(deps.sequence_generator, "Invalid sequence generator."); + } + + srs_estimator_result estimate(const resource_grid_reader& grid, const srs_estimator_configuration& config) override; + +private: + /// \brief Maximum sequence length in subcarriers. + /// + /// It is given by the maximum value of \f$m_{SRS,0}\f$ in TS38.211 Table 6.4.1.4.3-1 and a comb size of 2. + static constexpr unsigned max_seq_length = 272 * NRE / 2; + + /// \brief Extract the received Sounding Reference Signals sequence from a resource grid. + /// + /// The sequence mapping is given in TS38.211 Section 6.4.1.4.3. + /// + /// \param[out] sequence Extracted sequence. + /// \param[in] grid Received resource grid. + /// \param[in] i_rx_port Receive port index. + /// \param[in] i_symbol OFDM symbol index within the slot to extract. + /// \param[in] initial_subcarrier Initial subcarrier index relative to Point A. Parameter \f$k_0^{(p_i)}\f$. + /// \param[in] comb_size Subcarrier stride. Parameter \f$K_{TC}\f$. + /// \return A vector containing the sequence. + void extract_sequence(span sequence, + const resource_grid_reader& grid, + unsigned i_rx_port, + unsigned i_symbol, + unsigned initial_subcarrier, + unsigned comb_size); + + /// Dependencies collection. + dependencies deps; +}; + +} // namespace srsran \ No newline at end of file diff --git a/lib/phy/upper/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index bac866c1a9..17ae16ae3a 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -347,9 +347,13 @@ static std::shared_ptr create_ul_processor_factory(con report_fatal_error_if_not(prach_factory, "Invalid PRACH detector pool factory."); } + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + report_fatal_error_if_not(ta_estimator_factory, "Invalid TA estimator factory."); + std::shared_ptr prg_factory = create_pseudo_random_generator_sw_factory(); std::shared_ptr ch_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); std::shared_ptr equalizer_factory = create_channel_equalizer_factory_zf(); std::shared_ptr demodulation_factory = create_channel_modulation_sw_factory(); @@ -423,7 +427,7 @@ static std::shared_ptr create_ul_processor_factory(con // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); report_fatal_error_if_not(port_chan_estimator_factory, "Invalid port channel estimator factory."); std::shared_ptr pucch_dmrs_factory = diff --git a/lib/ran/CMakeLists.txt b/lib/ran/CMakeLists.txt index 27dfb63e3b..b47da4078a 100644 --- a/lib/ran/CMakeLists.txt +++ b/lib/ran/CMakeLists.txt @@ -48,12 +48,14 @@ add_library(srsran_ran pusch/pusch_tpmi_select.cpp pusch/pusch_uci_beta_offset.cpp pusch/ulsch_info.cpp + qos/five_qi_qos_mapping.cpp uci/uci_part2_size_calculator.cpp band_helper.cpp sch/tbs_calculator.cpp resource_allocation/resource_allocation_frequency.cpp sch/sch_segmentation.cpp srs/srs_bandwidth_configuration.cpp + srs/srs_information.cpp ssb_freq_position_generator.cpp ssb_gscn.cpp ssb_mapping.cpp diff --git a/lib/ran/qos/five_qi_qos_mapping.cpp b/lib/ran/qos/five_qi_qos_mapping.cpp new file mode 100644 index 0000000000..a01f922c58 --- /dev/null +++ b/lib/ran/qos/five_qi_qos_mapping.cpp @@ -0,0 +1,85 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsran/ran/qos/five_qi_qos_mapping.h" +#include + +using namespace srsran; + +/// \brief Standardized 5QI to QoS characteristics mapping as per TS 23.501, table 5.7.4-1. +static const std::unordered_map five_qi_to_qos_mapping = { + // clang-format off + + // GBR. + {uint_to_five_qi(1), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 20, 100, 10e-2, 2000, nullopt}}, + {uint_to_five_qi(2), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 40, 150, 10e-3, 2000, nullopt}}, + {uint_to_five_qi(3), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 30, 50, 10e-3, 2000, nullopt}}, + {uint_to_five_qi(4), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 50, 300, 10e-6, 2000, nullopt}}, + {uint_to_five_qi(65), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 7, 75, 10e-2, 2000, nullopt}}, + {uint_to_five_qi(66), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 20, 100, 10e-2, 2000, nullopt}}, + {uint_to_five_qi(67), + qos_characteristics{srsran::qos_flow_resource_type::gbr, 15, 100, 10e-3, 2000, nullopt}}, + + // Non-GBR. + {uint_to_five_qi(5), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 10, 100, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(6), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 60, 300, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(7), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 70, 100, 10e-3, nullopt, nullopt}}, + {uint_to_five_qi(8), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 80, 300, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(9), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 90, 300, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(69), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 5, 60, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(70), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 55, 200, 10e-6, nullopt, nullopt}}, + {uint_to_five_qi(79), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 65, 50, 10e-2, nullopt, nullopt}}, + {uint_to_five_qi(80), + qos_characteristics{srsran::qos_flow_resource_type::non_gbr, 68, 10, 10e-6, nullopt, nullopt}}, + + // Delay Critical GBR. + {uint_to_five_qi(82), + qos_characteristics{srsran::qos_flow_resource_type::delay_critical_gbr, 19, 10, 10e-4, 2000, 255}}, + {uint_to_five_qi(83), + qos_characteristics{srsran::qos_flow_resource_type::delay_critical_gbr, 22, 10, 10e-4, 2000, 1354}}, + {uint_to_five_qi(84), + qos_characteristics{srsran::qos_flow_resource_type::delay_critical_gbr, 24, 30, 10e-5, 2000, 1354}}, + {uint_to_five_qi(85), + qos_characteristics{srsran::qos_flow_resource_type::delay_critical_gbr, 21, 5, 10e-5, 2000, 255}}, + // clang-format on +}; + +qos_characteristics srsran::get_5qi_to_qos_characteristics_mapping(five_qi_t five_qi) +{ + const auto qos_char = five_qi_to_qos_mapping.find(five_qi); + srsran_assert(qos_char != five_qi_to_qos_mapping.end(), "Undefined QoS characteristics for 5QI={}", five_qi); + return qos_char->second; +} diff --git a/lib/ran/srs/srs_information.cpp b/lib/ran/srs/srs_information.cpp new file mode 100644 index 0000000000..0b5680a48e --- /dev/null +++ b/lib/ran/srs/srs_information.cpp @@ -0,0 +1,107 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srsran/ran/srs/srs_information.h" +#include "srsran/adt/optional.h" +#include "srsran/ran/srs/srs_bandwidth_configuration.h" +#include "srsran/ran/srs/srs_resource_configuration.h" +#include "srsran/support/srsran_assert.h" +#include + +using namespace srsran; + +static constexpr unsigned N_RB_SC = 12; + +static constexpr unsigned get_sequence_length(unsigned m_srs_b, srs_resource_configuration::comb_size_enum comb_size) +{ + return (m_srs_b * N_RB_SC) / static_cast(comb_size); +} + +srs_information +srsran::get_srs_information(const srs_resource_configuration& resource, unsigned i_antenna_port, unsigned i_symbol) +{ + // Select BW configuration. + optional srs_bw_config = + srs_configuration_get(resource.configuration_index.value(), resource.bandwidth_index.value()); + srsran_assert(srs_bw_config.has_value(), + "Invalid combination of c-SRS (i.e., {}) and b-SRS (i.e., {})", + resource.configuration_index, + resource.bandwidth_index); + + // Assert configuration parameters. + srsran_assert(resource.hopping == srs_resource_configuration::group_or_sequence_hopping_enum::neither, + "No sequence nor group hopping supported"); + srsran_assert(resource.freq_hopping >= resource.bandwidth_index, "Frequency hopping is not supported."); + + // Calculate sequence length. + unsigned sequence_length = get_sequence_length(srs_bw_config->m_srs, resource.comb_size); + + // Extract comb size. + unsigned comb_size = static_cast(resource.comb_size); + + // Calculate sequence group. + unsigned f_gh = 0; + unsigned u = (f_gh + resource.sequence_id.value()) % 30; + + // Calculate sequence number. + unsigned v = 0; + + // Maximum number of cyclic shifts depending on the comb size. + unsigned n_cs_max = (resource.comb_size == srs_resource_configuration::comb_size_enum::four) ? 12 : 8; + + // Calculate cyclic shift. Note that n_cs_max is always multiple of the number of antenna ports (one, two or four). + unsigned cyclic_shift_port = (resource.cyclic_shift.value() + + (n_cs_max * i_antenna_port) / static_cast(resource.nof_antenna_ports)) % + n_cs_max; + + // Calculate alpha. + float alpha = 2 * M_PI * static_cast(cyclic_shift_port) / static_cast(n_cs_max); + + // Calculate initial subcarrier index. + unsigned k_tc = resource.comb_offset.value(); + if ((resource.cyclic_shift >= n_cs_max / 2) && (resource.cyclic_shift < n_cs_max) && + (resource.nof_antenna_ports == srs_resource_configuration::one_two_four_enum::four) && + ((i_antenna_port == 1) || (i_antenna_port == 3))) { + k_tc = (k_tc + comb_size / 2) % comb_size; + } + unsigned k0_bar = resource.freq_shift.value() * N_RB_SC + k_tc; + unsigned sum = 0; + for (unsigned b = 0; b <= resource.bandwidth_index; ++b) { + optional bw_config = srs_configuration_get(resource.configuration_index.value(), b); + srsran_assert(bw_config, "Invalid configuration."); + + unsigned M_srs = get_sequence_length(bw_config->m_srs, resource.comb_size); + unsigned n_b = ((4 * resource.freq_position.value()) / bw_config->m_srs) % bw_config->N; + sum += comb_size * M_srs * n_b; + } + unsigned initial_subcarrier = k0_bar + sum; + + // Fill derived parameters. + srs_information info; + info.sequence_length = sequence_length; + info.sequence_group = u; + info.sequence_number = v; + info.alpha = alpha; + info.mapping_initial_subcarrier = initial_subcarrier; + info.comb_size = comb_size; + return info; +} \ No newline at end of file diff --git a/lib/ran/tdd_ul_dl_config.cpp b/lib/ran/tdd_ul_dl_config.cpp index 3c633b407e..506d72b5c8 100644 --- a/lib/ran/tdd_ul_dl_config.cpp +++ b/lib/ran/tdd_ul_dl_config.cpp @@ -95,6 +95,34 @@ srsran::get_active_tdd_ul_symbols(const tdd_ul_dl_config_common& cfg, unsigned s return nof_symbols > 0 ? ofdm_symbol_range{symbols_per_slot - nof_symbols, symbols_per_slot} : ofdm_symbol_range{}; } +optional srsran::find_next_tdd_dl_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index) +{ + const unsigned period = nof_slots_per_tdd_period(cfg); + + optional ret; + for (unsigned i = start_slot_index; i < period; ++i) { + if (has_active_tdd_dl_symbols(cfg, i)) { + ret = i; + break; + } + } + return ret; +} + +optional srsran::find_next_tdd_full_dl_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index) +{ + const unsigned period = nof_slots_per_tdd_period(cfg); + + optional ret; + for (unsigned i = start_slot_index; i < period; ++i) { + if (get_active_tdd_dl_symbols(cfg, i, cyclic_prefix::NORMAL).length() == NOF_OFDM_SYM_PER_SLOT_NORMAL_CP) { + ret = i; + break; + } + } + return ret; +} + optional srsran::find_next_tdd_ul_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index) { const unsigned period = nof_slots_per_tdd_period(cfg); diff --git a/lib/rrc/ue/rrc_ue_srb_context.h b/lib/rrc/ue/rrc_ue_srb_context.h index 711276bdc8..dd10da7dbb 100644 --- a/lib/rrc/ue/rrc_ue_srb_context.h +++ b/lib/rrc/ue/rrc_ue_srb_context.h @@ -134,7 +134,12 @@ class ue_srb_context // Decipher and verify integrity of an PDCP PDU. pdcp_result unpack_pdcp_pdu(byte_buffer pdcp_pdu) { - pdcp_context.entity->get_rx_lower_interface().handle_pdu(byte_buffer_chain{std::move(pdcp_pdu)}); + auto buffer_chain = byte_buffer_chain::create(std::move(pdcp_pdu)); + if (buffer_chain.is_error()) { + return pdcp_result{pdcp_context.rrc_rx_control_notifier.get_failure_cause()}; + } + + pdcp_context.entity->get_rx_lower_interface().handle_pdu(std::move(buffer_chain.value())); byte_buffer unpacked_pdu = pdcp_context.rrc_rx_data_notifier.get_rrc_pdu(); diff --git a/lib/scheduler/CMakeLists.txt b/lib/scheduler/CMakeLists.txt index 92433261d8..144d23f33a 100644 --- a/lib/scheduler/CMakeLists.txt +++ b/lib/scheduler/CMakeLists.txt @@ -51,7 +51,8 @@ set(SOURCES support/csi_report_helpers.cpp cell_scheduler.cpp scheduler_factory.cpp - scheduler_impl.cpp) + scheduler_impl.cpp + support/csi_rs_helper.cpp) add_library(srsran_sched STATIC ${SOURCES} $ diff --git a/lib/scheduler/cell/resource_grid.cpp b/lib/scheduler/cell/resource_grid.cpp index f1e8b36987..fe01bc7e3f 100644 --- a/lib/scheduler/cell/resource_grid.cpp +++ b/lib/scheduler/cell/resource_grid.cpp @@ -301,8 +301,7 @@ void cell_slot_resource_allocator::slot_indication(slot_point new_slot) cell_resource_allocator::cell_resource_allocator(const cell_configuration& cfg_) : cfg(cfg_), max_dl_slot_alloc_delay(SCHEDULER_MAX_K0), - max_ul_slot_alloc_delay(SCHEDULER_MAX_K0 + std::max(SCHEDULER_MAX_K1, SCHEDULER_MAX_K2 + MAX_MSG3_DELTA) + - cfg.ntn_cs_koffset) + max_ul_slot_alloc_delay(get_max_slot_ul_alloc_delay(cfg.ntn_cs_koffset)) { // Create cell_slot_resource_allocator objects. std::vector dl_scs_carriers, ul_scs_carriers; diff --git a/lib/scheduler/cell/resource_grid.h b/lib/scheduler/cell/resource_grid.h index 9cc0c3e635..8414f52cf6 100644 --- a/lib/scheduler/cell/resource_grid.h +++ b/lib/scheduler/cell/resource_grid.h @@ -260,9 +260,8 @@ struct cell_resource_allocator { /// Having access to past decisions is useful during the handling of error indications. static const size_t RING_MAX_HISTORY_SIZE = 8; /// Number of slots managed by this container. - static const size_t RING_ALLOCATOR_SIZE = - get_allocator_ring_size_gt_min(RING_MAX_HISTORY_SIZE + SCHEDULER_MAX_K0 + NTN_CELL_SPECIFIC_KOFFSET_MAX + - std::max(SCHEDULER_MAX_K1, SCHEDULER_MAX_K2 + MAX_MSG3_DELTA)); + static const size_t RING_ALLOCATOR_SIZE = get_allocator_ring_size_gt_min( + RING_MAX_HISTORY_SIZE + get_max_slot_ul_alloc_delay(NTN_CELL_SPECIFIC_KOFFSET_MAX)); /// Cell configuration const cell_configuration& cfg; diff --git a/lib/scheduler/cell/resource_grid_util.h b/lib/scheduler/cell/resource_grid_util.h index 701cfc8915..1f202d35ef 100644 --- a/lib/scheduler/cell/resource_grid_util.h +++ b/lib/scheduler/cell/resource_grid_util.h @@ -22,6 +22,8 @@ #pragma once +#include "srsran/scheduler/sched_consts.h" + namespace srsran { /// \brief Retrieves the resource grid allocator ring size greater than given minimum value. @@ -48,4 +50,10 @@ constexpr inline unsigned get_allocator_ring_size_gt_min(unsigned minimum_value) return 640; } +/// \brief Retrieves how far in advance the scheduler can allocate resources in the UL resource grid. +constexpr inline unsigned get_max_slot_ul_alloc_delay(unsigned ntn_cs_koffset) +{ + return SCHEDULER_MAX_K0 + std::max(SCHEDULER_MAX_K1, SCHEDULER_MAX_K2 + MAX_MSG3_DELTA) + ntn_cs_koffset; +} + } // namespace srsran diff --git a/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp b/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp index 4554de6e9a..ccbc4d334d 100644 --- a/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp +++ b/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp @@ -47,6 +47,10 @@ static csi_rs_info build_csi_rs_info(const bwp_configuration& bwp_cfg, const zp_ csi_rs.type = csi_rs_type::CSI_RS_ZP; fill_csi_rs_info_res_map(csi_rs, zp_csi_rs_res.res_mapping); + csi_rs.scrambling_id = 0; + csi_rs.power_ctrl_offset = 0; + csi_rs.power_ctrl_offset_ss = 0; + return csi_rs; } diff --git a/lib/scheduler/config/serving_cell_config_factory.cpp b/lib/scheduler/config/serving_cell_config_factory.cpp index 495e1e2274..21460fe616 100644 --- a/lib/scheduler/config/serving_cell_config_factory.cpp +++ b/lib/scheduler/config/serving_cell_config_factory.cpp @@ -325,13 +325,6 @@ srsran::config_helpers::generate_k2_candidates(cyclic_prefix cp, const tdd_ul_dl if (nof_dl_slots > nof_ul_slots) { break; } - // [Implementation-defined] For UL heavy TDD configuration, we avoid allocating PUSCH too far in the future. - // Reason: Scheduling PUSCH at slot k2 > nof_ul_slots results in CRC=KO when tested with COTS UE. - if (k2 > nof_ul_slots) { - // Remove last added PUSCH Time Domain resource since k2 > nof_ul_slots. - result.pop_back(); - break; - } } } } diff --git a/lib/scheduler/config/ue_configuration.cpp b/lib/scheduler/config/ue_configuration.cpp index 09190e20ed..b595eee319 100644 --- a/lib/scheduler/config/ue_configuration.cpp +++ b/lib/scheduler/config/ue_configuration.cpp @@ -778,6 +778,10 @@ void ue_configuration::update(const cell_common_configuration_list& common_cells if (cfg_req.lc_config_list.has_value()) { lc_list = cfg_req.lc_config_list.value(); } + // Update QoS information of DRBs. + if (not cfg_req.drb_qos_list.empty()) { + drb_qos_list = cfg_req.drb_qos_list; + } // Update UE dedicated cell configs. if (cfg_req.cells.has_value()) { diff --git a/lib/scheduler/config/ue_configuration.h b/lib/scheduler/config/ue_configuration.h index 1823cc0290..f488fb5a56 100644 --- a/lib/scheduler/config/ue_configuration.h +++ b/lib/scheduler/config/ue_configuration.h @@ -245,6 +245,9 @@ class ue_configuration // List of configured logical channels std::vector lc_list; + // List of QoS information for DRBs. + std::vector drb_qos_list; + // List of cells configured for a UE. slotted_id_vector> du_cells; diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index 73655e0006..400f385d36 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -64,19 +64,25 @@ void scheduler_metrics_handler::handle_crc_indication(const ul_crc_pdu_indicatio if (crc_pdu.tb_crc_success) { u.data.sum_ul_tb_bytes += tbs.value(); } + if (crc_pdu.time_advance_offset.has_value()) { + u.last_ta = crc_pdu.time_advance_offset->to_seconds(); + } } } -void scheduler_metrics_handler::handle_csi_report(du_ue_index_t ue_index, const csi_report_data& csi) +void scheduler_metrics_handler::handle_pucch_sinr(ue_metric_context& u, float sinr) { - if (ues.contains(ue_index)) { - auto& u = ues[ue_index]; - if (csi.first_tb_wideband_cqi.has_value()) { - u.last_cqi = csi.first_tb_wideband_cqi->to_uint(); - } - if (csi.ri.has_value()) { - u.last_ri = csi.ri->to_uint(); - } + u.data.nof_pucch_snr_reports++; + u.data.sum_pucch_snrs += sinr; +} + +void scheduler_metrics_handler::handle_csi_report(ue_metric_context& u, const csi_report_data& csi) +{ + if (csi.first_tb_wideband_cqi.has_value()) { + u.last_cqi = csi.first_tb_wideband_cqi->to_uint(); + } + if (csi.ri.has_value()) { + u.last_ri = csi.ri->to_uint(); } } @@ -104,13 +110,42 @@ void scheduler_metrics_handler::handle_harq_timeout(du_ue_index_t ue_index, bool } } -void scheduler_metrics_handler::handle_pucch_sinr(du_ue_index_t ue_index, optional pucch_sinr) +void scheduler_metrics_handler::handle_uci_pdu_indication(const uci_indication::uci_pdu& pdu) { - if (ues.contains(ue_index)) { - auto& u = ues[ue_index]; - if (pucch_sinr.has_value()) { - u.data.nof_pucch_snr_reports++; - u.data.sum_pucch_snrs += pucch_sinr.value(); + if (ues.contains(pdu.ue_index)) { + auto& u = ues[pdu.ue_index]; + + if (variant_holds_alternative(pdu.pdu)) { + auto& f1 = variant_get(pdu.pdu); + + if (f1.ul_sinr.has_value()) { + handle_pucch_sinr(u, f1.ul_sinr.value()); + } + + if (f1.time_advance_offset.has_value()) { + u.last_ta = f1.time_advance_offset.value().to_seconds(); + } + } else if (variant_holds_alternative(pdu.pdu)) { + auto& f2 = variant_get(pdu.pdu); + + if (f2.ul_sinr.has_value()) { + handle_pucch_sinr(u, f2.ul_sinr.value()); + } + + if (f2.csi.has_value()) { + handle_csi_report(u, f2.csi.value()); + } + + if (f2.time_advance_offset.has_value()) { + u.last_ta = f2.time_advance_offset.value().to_seconds(); + } + } else { + // PUSCH case. + auto& pusch = variant_get(pdu.pdu); + + if (pusch.csi.has_value()) { + handle_csi_report(u, pusch.csi.value()); + } } } } @@ -135,7 +170,11 @@ void scheduler_metrics_handler::handle_ul_phr_indication(const ul_phr_indication auto& u = ues[phr_ind.ue_index]; // Store last PHR. - u.last_phr = phr_ind.phr; + if (not phr_ind.phr.get_phr().empty()) { + // Log the floor of the average of the PH interval. + interval rg = phr_ind.phr.get_phr().front().ph; + u.last_phr = (rg.start() + rg.stop()) / 2; + } } } @@ -248,7 +287,10 @@ scheduler_metrics_handler::ue_metric_context::compute_report(std::chrono::millis for (const unsigned value : last_dl_bs) { ret.dl_bs += value; } - // TODO: update PUSCH and PUCCH SNR metrics based on indications. + if (last_ta >= 0) { + ret.last_ta = std::chrono::microseconds{static_cast(last_ta * 1e6)}; + } + ret.last_phr = last_phr; // Reset UE stats metrics on every report. reset(); diff --git a/lib/scheduler/logging/scheduler_metrics_handler.h b/lib/scheduler/logging/scheduler_metrics_handler.h index a90e23c9a8..fcb5db0e43 100644 --- a/lib/scheduler/logging/scheduler_metrics_handler.h +++ b/lib/scheduler/logging/scheduler_metrics_handler.h @@ -51,17 +51,14 @@ class scheduler_metrics_handler final : public harq_timeout_handler, public sche /// \brief Register CRC indication. void handle_crc_indication(const ul_crc_pdu_indication& crc_pdu, units::bytes tbs); - /// \brief Register CSI report metric. - void handle_csi_report(du_ue_index_t ue_index, const csi_report_data& csi); - /// \brief Register HARQ-ACK UCI indication. void handle_dl_harq_ack(du_ue_index_t ue_index, bool ack, units::bytes tbs); /// \brief Register HARQ timeout. void handle_harq_timeout(du_ue_index_t ue_index, bool is_dl) override; - /// \brief Register PUCCH SINR. - void handle_pucch_sinr(du_ue_index_t ue_index, optional pucch_sinr); + /// \brief Handle UCI PDU indication. + void handle_uci_pdu_indication(const uci_indication::uci_pdu& pdu); /// \brief Handle UL BSR indication. void handle_ul_bsr_indication(const ul_bsr_indication_message& bsr); @@ -106,7 +103,8 @@ class scheduler_metrics_handler final : public harq_timeout_handler, public sche uint8_t last_cqi = 0; uint8_t last_ri = 1; unsigned last_bsr = 0; - phr_report last_phr; + optional last_phr; + double last_ta = -1; std::array last_dl_bs{0}; non_persistent_data data; @@ -115,6 +113,9 @@ class scheduler_metrics_handler final : public harq_timeout_handler, public sche void reset(); }; + void handle_pucch_sinr(ue_metric_context& u, float sinr); + void handle_csi_report(ue_metric_context& u, const csi_report_data& csi); + void report_metrics(); void handle_slot_result(const sched_result& slot_result); diff --git a/lib/scheduler/policy/scheduler_time_rr.cpp b/lib/scheduler/policy/scheduler_time_rr.cpp index e20082271f..5f8b80d220 100644 --- a/lib/scheduler/policy/scheduler_time_rr.cpp +++ b/lib/scheduler/policy/scheduler_time_rr.cpp @@ -241,6 +241,11 @@ static alloc_outcome alloc_dl_ue(const ue& u, const ue_cell& ue_cc = u.get_cell(to_ue_cell_index(i)); const slot_point pdcch_slot = res_grid.get_pdcch_slot(ue_cc.cell_index); + if (ue_cc.is_in_fallback_mode()) { + // Skip allocation for UEs in fallback mode, as it is handled by the SRB fallback scheduler. + return alloc_outcome::skip_ue; + } + // UE is already allocated in the PDCCH for this slot (e.g. we should skip a newTx if a reTx has already been // allocated for this UE). if (res_grid.has_ue_dl_pdcch(ue_cc.cell_index, u.crnti)) { diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index d8094df2c5..f9a0a167b4 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -123,6 +123,14 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res return nullopt; } + if (has_common_pucch_f1_grant(tcrnti, pucch_slot_alloc.slot)) { + logger.debug("tc-rnti={}: PUCCH common not allocated for slot={}. Cause: a grant for this UE already exists in the " + "same slot", + tcrnti, + pucch_slot_alloc.slot); + return nullopt; + } + // Get the PUCCH resources, either from default tables. optional pucch_res = alloc_pucch_common_res_harq(pucch_slot_alloc, dci_info.ctx); diff --git a/lib/scheduler/support/csi_rs_helper.cpp b/lib/scheduler/support/csi_rs_helper.cpp new file mode 100644 index 0000000000..4e3a3ce318 --- /dev/null +++ b/lib/scheduler/support/csi_rs_helper.cpp @@ -0,0 +1,51 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "csi_rs_helpers.h" + +bool srsran::csi_helper::is_csi_rs_slot(const cell_configuration& cell_cfg, slot_point sl_tx) +{ + if (not cell_cfg.is_dl_enabled(sl_tx)) { + return false; + } + + if (not cell_cfg.zp_csi_rs_list.empty() and cell_cfg.nzp_csi_rs_list.empty()) { + return false; + } + + // for (unsigned i = 0; i != cell_cfg.zp_csi_rs_list.size(); ++i) + for (const auto& zp_csi : cell_cfg.zp_csi_rs_list) { + if (zp_csi.offset.has_value() and zp_csi.period.has_value() and + (sl_tx - *zp_csi.offset).to_uint() % (unsigned)*zp_csi.period == 0) { + return true; + } + } + + for (const auto& nzp_csi : cell_cfg.nzp_csi_rs_list) { + if (nzp_csi.csi_res_offset.has_value() and nzp_csi.csi_res_period.has_value() and + (sl_tx - *nzp_csi.csi_res_offset).to_uint() % (unsigned)*nzp_csi.csi_res_period == 0) { + return true; + } + } + + return false; +} diff --git a/lib/scheduler/support/csi_rs_helpers.h b/lib/scheduler/support/csi_rs_helpers.h new file mode 100644 index 0000000000..a04f5fdfcc --- /dev/null +++ b/lib/scheduler/support/csi_rs_helpers.h @@ -0,0 +1,34 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "../config/cell_configuration.h" + +namespace srsran { +namespace csi_helper { + +/// \brief Helpers that checks if the slot is a candidate for CSI RS signalling. +bool is_csi_rs_slot(const cell_configuration& cell_cfg, slot_point sl_tx); + +} // namespace csi_helper +} // namespace srsran diff --git a/lib/scheduler/support/dci_builder.cpp b/lib/scheduler/support/dci_builder.cpp index 4bd2fa472a..47bd8db0f6 100644 --- a/lib/scheduler/support/dci_builder.cpp +++ b/lib/scheduler/support/dci_builder.cpp @@ -163,22 +163,20 @@ void srsran::build_dci_f1_0_tc_rnti(dci_dl_info& dci, f1_0.redundancy_version = rv; } -void srsran::build_dci_f1_0_c_rnti(dci_dl_info& dci, - const ue_cell_configuration& ue_cell_cfg, - search_space_id ss_id, - crb_interval crbs, - unsigned time_resource, - unsigned k1, - unsigned pucch_res_indicator, - unsigned dai, - sch_mcs_index mcs_index, - uint8_t rv, - const dl_harq_process& h_dl) +void srsran::build_dci_f1_0_c_rnti(dci_dl_info& dci, + const search_space_info& ss_info, + const bwp_downlink_common& init_dl_bwp, + crb_interval crbs, + unsigned time_resource, + unsigned k1, + unsigned pucch_res_indicator, + unsigned dai, + sch_mcs_index mcs_index, + uint8_t rv, + const dl_harq_process& h_dl) { - const search_space_info& ss_info = ue_cell_cfg.search_space(ss_id); const coreset_configuration& cs_cfg = *ss_info.coreset; const bwp_downlink_common& active_dl_bwp_cmn = *ss_info.bwp->dl_common; - const bwp_downlink_common& init_dl_bwp = *ue_cell_cfg.bwp(to_bwp_id(0)).dl_common; const bwp_configuration& active_dl_bwp = active_dl_bwp_cmn.generic_params; dci.type = dci_dl_rnti_config_type::c_rnti_f1_0; diff --git a/lib/scheduler/support/dci_builder.h b/lib/scheduler/support/dci_builder.h index 4b4a10b3d2..cc82e40db0 100644 --- a/lib/scheduler/support/dci_builder.h +++ b/lib/scheduler/support/dci_builder.h @@ -65,17 +65,17 @@ void build_dci_f1_0_tc_rnti(dci_dl_info& dci, const dl_harq_process& h_dl); /// Builds DCI f1_0 for C-RNTI. -void build_dci_f1_0_c_rnti(dci_dl_info& dci, - const ue_cell_configuration& ue_cell_cfg, - search_space_id ss_id, - crb_interval crbs, - unsigned time_resource, - unsigned k1, - unsigned pucch_res_indicator, - unsigned dai, - sch_mcs_index mcs_index, - uint8_t rv, - const dl_harq_process& h_dl); +void build_dci_f1_0_c_rnti(dci_dl_info& dci, + const search_space_info& ss_info, + const bwp_downlink_common& init_dl_bwp, + crb_interval crbs, + unsigned time_resource, + unsigned k1, + unsigned pucch_res_indicator, + unsigned dai, + sch_mcs_index mcs_index, + uint8_t rv, + const dl_harq_process& h_dl); /// Builds DCI f1_1 for C-RNTI. void build_dci_f1_1_c_rnti(dci_dl_info& dci, diff --git a/lib/scheduler/support/mcs_tbs_calculator.cpp b/lib/scheduler/support/mcs_tbs_calculator.cpp index 155c262b7f..3ac98f7ce9 100644 --- a/lib/scheduler/support/mcs_tbs_calculator.cpp +++ b/lib/scheduler/support/mcs_tbs_calculator.cpp @@ -161,11 +161,10 @@ static void update_ulsch_info(ulsch_configuration& ulsch_cfg, unsigned tbs_bytes ulsch_cfg.mcs_descr = mcs_info; } -optional srsran::compute_dl_mcs_tbs(const pdsch_config_params& pdsch_params, - const ue_cell_configuration& ue_cell_cfg, - sch_mcs_index max_mcs, - unsigned nof_prbs, - bool contains_dc) +optional srsran::compute_dl_mcs_tbs(const pdsch_config_params& pdsch_params, + sch_mcs_index max_mcs, + unsigned nof_prbs, + bool contains_dc) { // The maximum supported code rate is 0.95, as per TS38.214, Section 5.1.3. The maximum code rate is defined for DL, // but we consider the same value for UL. diff --git a/lib/scheduler/support/mcs_tbs_calculator.h b/lib/scheduler/support/mcs_tbs_calculator.h index fea75143f6..f636065318 100644 --- a/lib/scheduler/support/mcs_tbs_calculator.h +++ b/lib/scheduler/support/mcs_tbs_calculator.h @@ -43,17 +43,14 @@ struct sch_mcs_tbs { /// \brief Computes the PDSCH MCS and TBS such that the effective code rate does not exceed 0.95. /// /// \param[in] pdsch_params PDSCH parameters needed to compute the MCS and TBS. -/// \param[in] ue_cell_cfg UE cell configuration. /// \param[in] max_mcs Initial value to be applied for the MCS; the final MCS might be lowered if the effective /// code rate is above 0.95. /// \param[in] nof_prbs Maximum number of PRBs available for the PUSCH transmission. +/// \param[in] contains_dc Set to true if the transmission overlaps with the position of the DC. /// \return The MCS and TBS, if for these values the effective code rate does not exceed 0.95; else, it returns an empty /// optional object. -optional compute_dl_mcs_tbs(const pdsch_config_params& pdsch_params, - const ue_cell_configuration& ue_cell_cfg, - sch_mcs_index max_mcs, - unsigned nof_prbs, - bool contains_dc); +optional +compute_dl_mcs_tbs(const pdsch_config_params& pdsch_params, sch_mcs_index max_mcs, unsigned nof_prbs, bool contains_dc); /// \brief Computes the PUSCH MCS and TBS such that the effective code rate does not exceed 0.95. /// diff --git a/lib/scheduler/support/pdsch/pdsch_resource_allocation.h b/lib/scheduler/support/pdsch/pdsch_resource_allocation.h index 263fcfd6cf..d5d31e5ebb 100644 --- a/lib/scheduler/support/pdsch/pdsch_resource_allocation.h +++ b/lib/scheduler/support/pdsch/pdsch_resource_allocation.h @@ -64,11 +64,8 @@ inline crb_interval get_ra_crb_limits(dci_dl_format dci_fmt, /// \brief Determine CRB limits for PDSCH grant, for the special case of non UE-dedicated allocations (e.g. SIB, RAR, /// SRB0). /// -/// \param dci_fmt DL DCI format. -/// \param init_dl_bwp Initial DL BWP configuration. -/// \param active_dl_bwp Active DL BWP configuration. -/// \param ss_cfg SearchSpace configuration. -/// \param cs_cfg CORESET configuration corresponding to SerachSpace. +/// \param[in] init_dl_bwp Initial DL BWP configuration. +/// \param[in] ss_id SearchSpace ID. /// \return Calculated CRB limits. inline crb_interval get_ra_crb_limits_common(const bwp_downlink_common& init_dl_bwp, search_space_id ss_id) { diff --git a/lib/scheduler/support/rb_helper.cpp b/lib/scheduler/support/rb_helper.cpp index 79e015c7e4..d4b74c7759 100644 --- a/lib/scheduler/support/rb_helper.cpp +++ b/lib/scheduler/support/rb_helper.cpp @@ -31,7 +31,7 @@ rb_helper::find_next_empty_interval(const prb_bitmap& used_rb_bitmap, size_t sta int rb_start = used_rb_bitmap.find_lowest(start_crb_idx, std::min(used_rb_bitmap.size(), last_crb_idx), false); if (rb_start != -1) { int rb_end = used_rb_bitmap.find_lowest(rb_start + 1, std::min(used_rb_bitmap.size(), last_crb_idx), true); - return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? used_rb_bitmap.size() : rb_end)}; + return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? std::min(used_rb_bitmap.size(), last_crb_idx) : rb_end)}; } return {}; } diff --git a/lib/scheduler/support/sch_pdu_builder.cpp b/lib/scheduler/support/sch_pdu_builder.cpp index 95a4f516f1..541b101365 100644 --- a/lib/scheduler/support/sch_pdu_builder.cpp +++ b/lib/scheduler/support/sch_pdu_builder.cpp @@ -73,7 +73,8 @@ pdsch_config_params srsran::get_pdsch_config_f1_0_tc_rnti(const cell_configurati return pdsch; } -pdsch_config_params srsran::get_pdsch_config_f1_0_c_rnti(const ue_cell_configuration& ue_cell_cfg, +pdsch_config_params srsran::get_pdsch_config_f1_0_c_rnti(const cell_configuration& cell_cfg, + const ue_cell_configuration* ue_cell_cfg, const pdsch_time_domain_resource_allocation& pdsch_td_cfg) { // As per TS 38.214, Section 5.1.3.2, TB scaling filed can be different to 0 only for DCI 1_0 with P-RNTI, or RA-RNTI. @@ -83,12 +84,11 @@ pdsch_config_params srsran::get_pdsch_config_f1_0_c_rnti(const ue_cell_configura pdsch_config_params pdsch; - pdsch.dmrs = - make_dmrs_info_common(pdsch_td_cfg, ue_cell_cfg.cell_cfg_common.pci, ue_cell_cfg.cell_cfg_common.dmrs_typeA_pos); + pdsch.dmrs = make_dmrs_info_common(pdsch_td_cfg, cell_cfg.pci, cell_cfg.dmrs_typeA_pos); // According to TS 38.214, Section 5.1.3.2, nof_oh_prb is set equal to xOverhead, when set; else nof_oh_prb = 0. // NOTE: x_overhead::not_set is mapped to 0. - pdsch.nof_oh_prb = ue_cell_cfg.cfg_dedicated().pdsch_serv_cell_cfg.has_value() - ? static_cast(ue_cell_cfg.cfg_dedicated().pdsch_serv_cell_cfg.value().x_ov_head) + pdsch.nof_oh_prb = ue_cell_cfg != nullptr and ue_cell_cfg->cfg_dedicated().pdsch_serv_cell_cfg.has_value() + ? static_cast(ue_cell_cfg->cfg_dedicated().pdsch_serv_cell_cfg.value().x_ov_head) : static_cast(x_overhead::not_set); pdsch.symbols = pdsch_td_cfg.symbols; @@ -495,14 +495,12 @@ void srsran::build_pdsch_f1_0_c_rnti(pdsch_information& pdsch, const pdsch_config_params& pdsch_cfg, unsigned tbs_bytes, rnti_t rnti, - const ue_cell_configuration& ue_cell_cfg, - search_space_id ss_id, + const cell_configuration& cell_cfg, + const search_space_info& ss_info, const dci_1_0_c_rnti_configuration& dci_cfg, const crb_interval& crbs, bool is_new_data) { - const cell_configuration& cell_cfg = ue_cell_cfg.cell_cfg_common; - const search_space_info& ss_info = ue_cell_cfg.search_space(ss_id); const coreset_configuration& cs_cfg = *ss_info.coreset; const bwp_info& active_bwp = *ss_info.bwp; const bwp_downlink_common& bwp_dl = *active_bwp.dl_common; diff --git a/lib/scheduler/support/sch_pdu_builder.h b/lib/scheduler/support/sch_pdu_builder.h index c9f94f22b2..6095d5b2d6 100644 --- a/lib/scheduler/support/sch_pdu_builder.h +++ b/lib/scheduler/support/sch_pdu_builder.h @@ -66,7 +66,8 @@ pdsch_config_params get_pdsch_config_f1_0_tc_rnti(const cell_configuration& /// \brief Fetches the PDSCH parameters needed for PUSCH PDU for DCI format 1_0, scrambled by C-RNTI. /// /// Returns parameters needed to compute the number of PRBs, MCS and TBS. -pdsch_config_params get_pdsch_config_f1_0_c_rnti(const ue_cell_configuration& ue_cell_cfg, +pdsch_config_params get_pdsch_config_f1_0_c_rnti(const cell_configuration& cell_cfg, + const ue_cell_configuration* ue_cell_cfg, const pdsch_time_domain_resource_allocation& pdsch_td_cfg); /// \brief Fetches the PDSCH parameters needed for PUSCH PDU for DCI format 1_1, scrambled by C-RNTI. @@ -142,8 +143,8 @@ void build_pdsch_f1_0_c_rnti(pdsch_information& pdsch, const pdsch_config_params& pdsch_cfg, unsigned tbs_bytes, rnti_t rnti, - const ue_cell_configuration& ue_cell_cfg, - search_space_id ss_id, + const cell_configuration& cell_cfg, + const search_space_info& ss_info, const dci_1_0_c_rnti_configuration& dci_cfg, const crb_interval& crbs, bool is_new_data); diff --git a/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp index 435adac02f..0d68645b98 100644 --- a/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp @@ -249,7 +249,6 @@ void uci_scheduler_impl::schedule_updated_ues_ucis(cell_resource_allocator& cell { // For all UEs whose config has been recently updated, schedule their UCIs up until one slot before the farthest // slot in the resource grid. - // TODO: Remove UCIs from the list of updated UEs when the UE is removed, if they have no HARQ-ACK. for (rnti_t rnti : updated_ues) { const ue_cell_configuration* ue_cfg = get_ue_cfg(rnti); if (ue_cfg == nullptr) { diff --git a/lib/scheduler/ue_scheduling/CMakeLists.txt b/lib/scheduler/ue_scheduling/CMakeLists.txt index 2489f1a67f..d038b5313d 100644 --- a/lib/scheduler/ue_scheduling/CMakeLists.txt +++ b/lib/scheduler/ue_scheduling/CMakeLists.txt @@ -29,7 +29,7 @@ set(SOURCES ue_cell.cpp ue_cell_grid_allocator.cpp ue_event_manager.cpp - ue_srb0_scheduler.cpp + ue_fallback_scheduler.cpp ue_scheduler_impl.cpp ue_repository.cpp) diff --git a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp index 782aab286c..9337da5713 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp @@ -49,18 +49,18 @@ void dl_logical_channel_manager::configure(span lo } } -unsigned dl_logical_channel_manager::allocate_mac_sdu(dl_msg_lc_info& subpdu, unsigned rem_bytes) +unsigned dl_logical_channel_manager::allocate_mac_sdu(dl_msg_lc_info& subpdu, unsigned rem_bytes, lcid_t lcid) { subpdu.lcid = lcid_dl_sch_t::MIN_RESERVED; subpdu.sched_bytes = 0; - lcid_t lcid = get_max_prio_lcid(); - if (lcid == lcid_t::INVALID_LCID) { + lcid_t lcid_with_prio = lcid == lcid_t::INVALID_LCID ? get_max_prio_lcid() : lcid; + if (lcid_with_prio == lcid_t::INVALID_LCID) { return 0; } // Update Buffer Status of allocated LCID. - return allocate_mac_sdu(subpdu, lcid, rem_bytes); + return allocate_mac_sdu(subpdu, lcid_with_prio, rem_bytes); } lcid_t dl_logical_channel_manager::get_max_prio_lcid() const @@ -76,6 +76,8 @@ lcid_t dl_logical_channel_manager::get_max_prio_lcid() const unsigned dl_logical_channel_manager::allocate_mac_sdu(dl_msg_lc_info& subpdu, lcid_t lcid, unsigned rem_bytes) { + srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); + unsigned lch_bytes = pending_bytes(lcid); if (lch_bytes == 0 or rem_bytes <= MIN_MAC_SDU_SUBHEADER_SIZE) { return 0; @@ -90,7 +92,7 @@ unsigned dl_logical_channel_manager::allocate_mac_sdu(dl_msg_lc_info& subpdu, lc alloc_bytes += leftover_bytes; } if (alloc_bytes == MAC_SDU_SUBHEADER_LENGTH_THRES + MIN_MAC_SDU_SUBHEADER_SIZE) { - // avoid invalid combination of MAC subPDU and subheader size. + // Avoid invalid combination of MAC subPDU and subheader size. alloc_bytes--; } unsigned sdu_size = get_mac_sdu_size(alloc_bytes); @@ -142,23 +144,24 @@ unsigned dl_logical_channel_manager::allocate_mac_ce(dl_msg_lc_info& subpdu, uns return alloc_bytes; } -unsigned srsran::allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_manager& lch_mng, unsigned total_tbs) +unsigned +srsran::allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_manager& lch_mng, unsigned total_tbs, lcid_t lcid) { unsigned rem_tbs = total_tbs; - // if we do not have enough bytes to fit MAC subheader, skip MAC SDU allocation. + // If we do not have enough bytes to fit MAC subheader, skip MAC SDU allocation. // Note: We assume upper layer accounts for its own subheaders when updating the buffer state. while (rem_tbs > MAX_MAC_SDU_SUBHEADER_SIZE and not tb_info.lc_chs_to_sched.full()) { dl_msg_lc_info subpdu; - unsigned alloc_bytes = lch_mng.allocate_mac_sdu(subpdu, rem_tbs); + unsigned alloc_bytes = lch_mng.allocate_mac_sdu(subpdu, rem_tbs, lcid); if (alloc_bytes == 0) { break; } - // add new subPDU. + // Add new subPDU. tb_info.lc_chs_to_sched.push_back(subpdu); - // update remaining space taking into account the MAC SDU subheader. + // Update remaining space taking into account the MAC SDU subheader. rem_tbs -= alloc_bytes; } @@ -176,10 +179,10 @@ unsigned srsran::allocate_mac_ces(dl_msg_tb_info& tb_info, dl_logical_channel_ma break; } - // add new subPDU. + // Add new subPDU. tb_info.lc_chs_to_sched.push_back(subpdu); - // update remaining space taking into account the MAC CE subheader. + // Update remaining space taking into account the MAC CE subheader. rem_tbs -= alloc_bytes; } return total_tbs - rem_tbs; @@ -221,10 +224,10 @@ srsran::allocate_ue_con_res_id_mac_ce(dl_msg_tb_info& tb_info, dl_logical_channe dl_msg_lc_info subpdu; unsigned alloc_bytes = lch_mng.allocate_ue_con_res_id_mac_ce(subpdu, rem_tbs); if (alloc_bytes != 0) { - // add new subPDU. + // Add new subPDU. tb_info.lc_chs_to_sched.push_back(subpdu); - // update remaining space taking into account the MAC CE subheader. + // Update remaining space taking into account the MAC CE subheader. rem_tbs -= alloc_bytes; } } diff --git a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h index a8cc845739..607f1b0fac 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h @@ -44,13 +44,23 @@ class dl_logical_channel_manager dl_logical_channel_manager(); /// \brief Activate/Deactivate Bearer. - void set_status(lcid_t lcid, bool active) { channels[lcid].active = active; } + void set_status(lcid_t lcid, bool active) + { + srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); + channels[lcid].active = active; + } /// \brief Update the configurations of the provided lists of bearers. void configure(span log_channels_configs); /// \brief Verifies if logical channel is activated for DL. - bool is_active(lcid_t lcid) const { return channels[lcid].active; } + bool is_active(lcid_t lcid) const + { + if (lcid > LCID_MAX_DRB) { + return false; + } + return channels[lcid].active; + } /// \brief Checks whether the UE has pending data. /// \remark Excludes data for SRB0. @@ -113,6 +123,7 @@ class dl_logical_channel_manager /// \brief Update DL buffer status for a given LCID. void handle_dl_buffer_status_indication(lcid_t lcid, unsigned buffer_status) { + srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); channels[lcid].buf_st = buffer_status; } @@ -129,7 +140,7 @@ class dl_logical_channel_manager /// \brief Allocates highest priority MAC SDU within space of \c rem_bytes bytes. Updates \c lch_info with allocated /// bytes for the MAC SDU (no MAC subheader). /// \return Allocated bytes for MAC SDU (with subheader). - unsigned allocate_mac_sdu(dl_msg_lc_info& lch_info, unsigned rem_bytes); + unsigned allocate_mac_sdu(dl_msg_lc_info& lch_info, unsigned rem_bytes, lcid_t lcid = INVALID_LCID); /// \brief Allocates next MAC CE within space of \c rem_bytes bytes. Updates \c lch_info with allocated bytes for the /// MAC CE. @@ -167,8 +178,13 @@ class dl_logical_channel_manager /// \param[in] tb_info TB on which MAC subPDUs will be stored. /// \param[in] lch_mng UE DL logical channel manager. /// \param[in] total_tbs available space in bytes for subPDUs. +/// \param[in] lcid if provided, LCID of the logical channel to be allocated. Otherwise, the LCID with higher priority +/// is chosen. /// \return Total number of bytes allocated (including MAC subheaders). -unsigned allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_manager& lch_mng, unsigned total_tbs); +unsigned allocate_mac_sdus(dl_msg_tb_info& tb_info, + dl_logical_channel_manager& lch_mng, + unsigned total_tbs, + lcid_t lcid = INVALID_LCID); /// \brief Allocate MAC subPDUs for pending MAC CEs. /// \param[in] tb_info TB on which MAC subPDUs will be stored. diff --git a/lib/scheduler/ue_scheduling/harq_process.cpp b/lib/scheduler/ue_scheduling/harq_process.cpp index 435afa76f2..b34b39137e 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -196,13 +196,15 @@ void dl_harq_process::new_tx(slot_point pdsch_slot, unsigned max_harq_nof_retxs, uint8_t harq_bit_idx, cqi_value cqi, - unsigned nof_layers) + unsigned nof_layers, + bool is_fallback_) { base_type::tx_common(pdsch_slot, pdsch_slot + k1); base_type::new_tx_tb_common(0, max_harq_nof_retxs, harq_bit_idx); - prev_tx_params = {}; - prev_tx_params.cqi = cqi; - prev_tx_params.nof_layers = nof_layers; + prev_tx_params = {}; + prev_tx_params.cqi = cqi; + prev_tx_params.nof_layers = nof_layers; + prev_tx_params.is_fallback = is_fallback_; prev_tx_params.tb[0].emplace(); prev_tx_params.tb[1].reset(); pucch_ack_to_receive = 0; diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index 50c3b31042..2219ed6c0b 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -282,6 +282,7 @@ class dl_harq_process : public detail::harq_process std::array, base_type::MAX_NOF_TBS> tb; cqi_value cqi; unsigned nof_layers; + bool is_fallback{false}; }; struct dl_ack_info_result { @@ -323,7 +324,8 @@ class dl_harq_process : public detail::harq_process unsigned max_harq_nof_retxs, uint8_t harq_bit_idx, cqi_value cqi, - unsigned nof_layers); + unsigned nof_layers, + bool is_fallback = false); /// \brief Called on every TB retransmission, when only one TB is active. This function assumes that the HARQ TB is /// in pending new_retx state. diff --git a/lib/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index 9463589078..5c9604f6e3 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -120,16 +120,16 @@ void ue::handle_reconfiguration_request(const ue_reconf_command& cmd) } } -unsigned ue::pending_dl_newtx_bytes() const +unsigned ue::pending_dl_newtx_bytes(lcid_t lcid) const { - return dl_lc_ch_mgr.pending_bytes(); + return lcid != INVALID_LCID ? dl_lc_ch_mgr.pending_bytes(lcid) : dl_lc_ch_mgr.pending_bytes(); } -unsigned ue::pending_dl_srb0_newtx_bytes() const +unsigned ue::pending_dl_srb0_or_srb1_newtx_bytes(bool is_srb0) const { - unsigned pending_bytes = dl_lc_ch_mgr.pending_bytes(LCID_SRB0); + unsigned pending_bytes = dl_lc_ch_mgr.pending_bytes(is_srb0 ? LCID_SRB0 : LCID_SRB1); - if (pending_bytes > 0) { + if (pending_bytes != 0) { // In case SRB0 has data, only allocate SRB0 and CEs. return pending_bytes + dl_lc_ch_mgr.pending_ue_con_res_id_ce_bytes(); } @@ -168,18 +168,19 @@ bool ue::has_pending_sr() const return ul_lc_ch_mgr.has_pending_sr(); } -unsigned ue::build_dl_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes) +unsigned ue::build_dl_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, lcid_t lcid) { unsigned total_subpdu_bytes = 0; total_subpdu_bytes += allocate_mac_ces(tb_info, dl_lc_ch_mgr, tb_size_bytes); - total_subpdu_bytes += allocate_mac_sdus(tb_info, dl_lc_ch_mgr, tb_size_bytes - total_subpdu_bytes); + total_subpdu_bytes += allocate_mac_sdus(tb_info, dl_lc_ch_mgr, tb_size_bytes - total_subpdu_bytes, lcid); return total_subpdu_bytes; } -unsigned ue::build_dl_srb0_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes) +unsigned ue::build_dl_fallback_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, bool is_srb0) { unsigned total_subpdu_bytes = 0; total_subpdu_bytes += allocate_ue_con_res_id_mac_ce(tb_info, dl_lc_ch_mgr, tb_size_bytes); - total_subpdu_bytes += allocate_mac_sdus(tb_info, dl_lc_ch_mgr, tb_size_bytes - total_subpdu_bytes); + total_subpdu_bytes += + allocate_mac_sdus(tb_info, dl_lc_ch_mgr, tb_size_bytes - total_subpdu_bytes, is_srb0 ? LCID_SRB0 : LCID_SRB1); return total_subpdu_bytes; } diff --git a/lib/scheduler/ue_scheduling/ue.h b/lib/scheduler/ue_scheduling/ue.h index 9d54d90f3f..ffdf7653f3 100644 --- a/lib/scheduler/ue_scheduling/ue.h +++ b/lib/scheduler/ue_scheduling/ue.h @@ -141,12 +141,16 @@ class ue /// \brief Computes the number of DL pending bytes that are not already allocated in a DL HARQ. The value is used /// to derive the required transport block size for an DL grant. - /// \remark Excludes SRB0. - unsigned pending_dl_newtx_bytes() const; + /// param[in] lcid If the LCID is provided, the method will return the number of pending bytes for that LCID. + /// Otherwise it will return the sum of all LCIDs pending bytes, excluding SRB0. + /// \return The number of DL pending bytes that are not already allocated in a DL HARQ. + unsigned pending_dl_newtx_bytes(lcid_t lcid = lcid_t::INVALID_LCID) const; - /// \brief Computes the number of DL pending bytes that are not already allocated in a DL HARQ for SRB0. The value - /// is used to derive the required transport block size for an DL grant. - unsigned pending_dl_srb0_newtx_bytes() const; + /// \brief Computes the number of DL pending bytes that are not already allocated in a DL HARQ for SRB0 or SRB1. The + /// value is used to derive the required transport block size for an DL grant. + /// param[in] is_srb0 tells whether to computes the number of DL pending bytes for SRB0, if true; for SRB1 otherwise. + /// \return The number of DL pending bytes. + unsigned pending_dl_srb0_or_srb1_newtx_bytes(bool is_srb0) const; /// \brief Computes the number of UL pending bytes that are not already allocated in a UL HARQ. The value is used /// to derive the required transport block size for an UL grant. @@ -158,12 +162,13 @@ class ue /// \brief Defines the list of subPDUs, including LCID and payload size, that will compose the transport block. /// \return Returns the number of bytes reserved in the TB for subPDUs (other than padding). /// \remark Excludes SRB0. - unsigned build_dl_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes); + unsigned build_dl_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, lcid_t lcid = INVALID_LCID); /// \brief Defines the list of subPDUs, including LCID and payload size, that will compose the transport block for - /// SRB0. + /// SRB0 or for SRB1 in fallback mode. + /// It includes the UE Contention Resolution Identity CE if it is pending. /// \return Returns the number of bytes reserved in the TB for subPDUs (other than padding). - unsigned build_dl_srb0_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes); + unsigned build_dl_fallback_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, bool is_srb0); private: /// Expert config parameters used for UE scheduler. diff --git a/lib/scheduler/ue_scheduling/ue_cell.cpp b/lib/scheduler/ue_scheduling/ue_cell.cpp index 6519dc28da..325deb11e2 100644 --- a/lib/scheduler/ue_scheduling/ue_cell.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell.cpp @@ -96,7 +96,7 @@ grant_prbs_mcs ue_cell::required_dl_prbs(const pdsch_time_domain_resource_alloca pdsch_cfg = get_pdsch_config_f1_0_tc_rnti(cell_cfg, pdsch_td_cfg); break; case dci_dl_rnti_config_type::c_rnti_f1_0: - pdsch_cfg = get_pdsch_config_f1_0_c_rnti(cfg(), pdsch_td_cfg); + pdsch_cfg = get_pdsch_config_f1_0_c_rnti(cell_cfg, &cfg(), pdsch_td_cfg); break; case dci_dl_rnti_config_type::c_rnti_f1_1: pdsch_cfg = get_pdsch_config_f1_1_c_rnti(cfg(), pdsch_td_cfg, channel_state_manager().get_nof_dl_layers()); diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index 81989a255f..809a80beb7 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -93,11 +93,12 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr // Find a SearchSpace candidate. const search_space_info* ss_info = ue_cell_cfg.find_search_space(grant.ss_id); if (ss_info == nullptr) { - logger.warning("Failed to allocate PDSCH. Cause: No valid SearchSpace found."); + logger.warning("ue={} rnti={}: Failed to allocate PDSCH. Cause: No valid SearchSpace found.", u.ue_index, u.crnti); return alloc_outcome::invalid_params; } if (ss_info->bwp->bwp_id != ue_cc->active_bwp_id()) { - logger.warning("Failed to allocate PDSCH. Cause: SearchSpace not valid for active BWP."); + logger.warning( + "ue={} rnti={}: Failed to allocate PDSCH. Cause: SearchSpace not valid for active BWP.", u.ue_index, u.crnti); return alloc_outcome::invalid_params; } const search_space_configuration& ss_cfg = *ss_info->cfg; @@ -119,14 +120,19 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr // CRC scrambled by a RA-RNTI, a MsgB-RNTI, or a TC-RNTI on the primary cell. if (dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 and grant.ss_id != cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common.ra_search_space_id) { - logger.info("Failed to allocate PDSCH. Cause: SearchSpace not valid for re-transmission of Msg4."); + logger.info("ue={} rnti={}: Failed to allocate PDSCH. Cause: SearchSpace not valid for re-transmission of Msg4.", + u.ue_index, + u.crnti); return alloc_outcome::invalid_params; } // Note: Unable to multiplex CSI and SRB0 retransmission. if (dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 and not get_res_alloc(grant.cell_index)[0].result.dl.csi_rs.empty()) { - logger.info("Failed to allocate PDSCH. Cause: Multiplexing of CSI-RS and TC-RNTI retransmission is not allowed."); + logger.info("ue={} rnti={}: Failed to allocate PDSCH. Cause: Multiplexing of CSI-RS and TC-RNTI retransmission is " + "not allowed.", + u.ue_index, + u.crnti); return alloc_outcome::skip_ue; } @@ -140,30 +146,44 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr if (pdsch_alloc.result.dl.bc.sibs.size() + pdsch_alloc.result.dl.paging_grants.size() + pdsch_alloc.result.dl.rar_grants.size() + pdsch_alloc.result.dl.ue_grants.size() >= expert_cfg.max_pdschs_per_slot) { - logger.info("Failed to allocate PDSCH. Cause: Max number of PDSCHs per slot {} was reached.", + logger.info("ue={} rnti={}: Failed to allocate PDSCH. Cause: Max number of PDSCHs per slot {} was reached.", + u.ue_index, + u.crnti, expert_cfg.max_pdschs_per_slot); return alloc_outcome::skip_slot; } if (not cell_cfg.is_dl_enabled(pdcch_alloc.slot)) { - logger.warning("Failed to allocate PDSCH in slot={}. Cause: DL is not active in the PDCCH slot", pdsch_alloc.slot); + logger.warning("ue={} rnti={}: Failed to allocate PDSCH in slot={}. Cause: DL is not active in the PDCCH slot", + u.ue_index, + u.crnti, + pdsch_alloc.slot); return alloc_outcome::skip_slot; } if (not cell_cfg.is_dl_enabled(pdsch_alloc.slot)) { - logger.warning("Failed to allocate PDSCH in slot={}. Cause: DL is not active in the PDSCH slot", pdsch_alloc.slot); + logger.warning("ue={} rnti={}: Failed to allocate PDSCH in slot={}. Cause: DL is not active in the PDSCH slot", + u.ue_index, + u.crnti, + pdsch_alloc.slot); return alloc_outcome::invalid_params; } // Check whether PDSCH time domain resource does not overlap with CORESET. if (pdsch_td_cfg.symbols.start() < ss_cfg.get_first_symbol_index() + cs_cfg.duration) { - logger.warning("Failed to allocate PDSCH in slot={}. Cause: PDSCH time domain resource ={} is starting before the " + logger.warning("ue={} rnti={}: Failed to allocate PDSCH in slot={}. Cause: PDSCH time domain resource={} is " + "starting before the " "CORESET symbols", + u.ue_index, + u.crnti, pdsch_alloc.slot, grant.time_res_index); return alloc_outcome::invalid_params; } // Check whether PDSCH time domain resource fits in DL symbols of the slot. if (pdsch_td_cfg.symbols.stop() > cell_cfg.get_nof_dl_symbol_per_slot(pdsch_alloc.slot)) { - logger.warning("Failed to allocate PDSCH in slot={}. Cause: Nof. DL symbols in PDSCH slot shorter than PDSCH time " - "domain resource ={}", + logger.warning("ue={} rnti={}: Failed to allocate PDSCH in slot={}. Cause: Nof. DL symbols in PDSCH slot shorter " + "than PDSCH time " + "domain resource={}", + u.ue_index, + u.crnti, pdsch_alloc.slot, grant.time_res_index); return alloc_outcome::invalid_params; @@ -258,7 +278,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr pdsch_cfg = get_pdsch_config_f1_0_tc_rnti(cell_cfg, pdsch_list[grant.time_res_index]); break; case dci_dl_rnti_config_type::c_rnti_f1_0: - pdsch_cfg = get_pdsch_config_f1_0_c_rnti(ue_cell_cfg, pdsch_list[grant.time_res_index]); + pdsch_cfg = get_pdsch_config_f1_0_c_rnti(cell_cfg, &ue_cell_cfg, pdsch_list[grant.time_res_index]); break; case dci_dl_rnti_config_type::c_rnti_f1_1: pdsch_cfg = get_pdsch_config_f1_1_c_rnti(ue_cell_cfg, pdsch_list[grant.time_res_index], grant.nof_layers); @@ -294,7 +314,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr cell_cfg.dl_cfg_common.freq_info_dl.scs_carrier_list.back().tx_direct_current_location.value(), grant.crbs); } - mcs_tbs_info = compute_dl_mcs_tbs(pdsch_cfg, ue_cell_cfg, adjusted_mcs, grant.crbs.length(), contains_dc); + mcs_tbs_info = compute_dl_mcs_tbs(pdsch_cfg, adjusted_mcs, grant.crbs.length(), contains_dc); } else { // It is a retx. mcs_tbs_info.emplace( @@ -359,8 +379,8 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr break; case dci_dl_rnti_config_type::c_rnti_f1_0: build_dci_f1_0_c_rnti(pdcch->dci, - ue_cell_cfg, - grant.ss_id, + ue_cell_cfg.search_space(grant.ss_id), + cell_cfg.dl_cfg_common.init_dl_bwp, grant.crbs, grant.time_res_index, k1, @@ -413,8 +433,8 @@ alloc_outcome ue_cell_grid_allocator::allocate_dl_grant(const ue_pdsch_grant& gr pdsch_cfg, mcs_tbs_info.value().tbs, u.crnti, - ue_cell_cfg, - grant.ss_id, + cell_cfg, + ue_cell_cfg.search_space(grant.ss_id), pdcch->dci.c_rnti_f1_0, grant.crbs, h_dl.tb(0).nof_retxs == 0); @@ -484,13 +504,16 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // Find a SearchSpace candidate. const search_space_info* ss_info = ue_cell_cfg.find_search_space(grant.ss_id); if (ss_info == nullptr) { - logger.warning("Failed to allocate PUSCH. Cause: No valid SearchSpace found."); + logger.warning("ue={} rnti={}: Failed to allocate PUSCH. Cause: No valid SearchSpace found.", u.ue_index, u.crnti); return alloc_outcome::invalid_params; } if (ss_info->bwp->bwp_id != ue_cc->active_bwp_id()) { - logger.warning("Failed to allocate PUSCH. Cause: Chosen SearchSpace {} does not belong to the active BWP {}", - grant.ss_id, - ue_cc->active_bwp_id()); + logger.warning( + "ue={} rnti={}: Failed to allocate PUSCH. Cause: Chosen SearchSpace {} does not belong to the active BWP {}", + u.ue_index, + u.crnti, + grant.ss_id, + ue_cc->active_bwp_id()); return alloc_outcome::invalid_params; } const search_space_configuration& ss_cfg = *ss_info->cfg; @@ -509,18 +532,21 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // CRC scrambled by a RA-RNTI, a MsgB-RNTI, or a TC-RNTI on the primary cell. if (dci_type == dci_ul_rnti_config_type::tc_rnti_f0_0 and grant.ss_id != cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common.ra_search_space_id) { - logger.info("Failed to allocate PUSCH. Cause: SearchSpace not valid for re-transmission."); + logger.info("ue={} rnti={}: Failed to allocate PUSCH. Cause: SearchSpace not valid for re-transmission.", + u.ue_index, + u.crnti); return alloc_outcome::invalid_params; } // In case of re-transmission DCI format must remain same and therefore its necessary to find the SS which support // that DCI format. if (dci_type != dci_ul_rnti_config_type::tc_rnti_f0_0 and dci_type != ss_supported_crnti_dci_type) { - logger.info( - "rnti={} Failed to allocate PUSCH. Cause: DCI format {} in HARQ retx is not supported in SearchSpace {}.", - u.crnti, - dci_ul_rnti_config_format(h_ul.last_tx_params().dci_cfg_type), - grant.ss_id); + logger.info("ue={} rnti={}: Failed to allocate PUSCH. Cause: DCI format {} in HARQ retx is not supported in " + "SearchSpace {}.", + u.ue_index, + u.crnti, + dci_ul_rnti_config_format(h_ul.last_tx_params().dci_cfg_type), + grant.ss_id); return alloc_outcome::invalid_params; } @@ -530,29 +556,36 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr get_res_alloc(grant.cell_index)[pdcch_delay_in_slots + pusch_td_cfg.k2 + cell_cfg.ntn_cs_koffset]; if (not cell_cfg.is_dl_enabled(pdcch_alloc.slot)) { - logger.warning("rnti={} Failed to allocate PUSCH in slot={}. Cause: DL is not active in the PDCCH slot", + logger.warning("ue={} rnti={}: Failed to allocate PUSCH in slot={}. Cause: DL is not active in the PDCCH slot", + u.ue_index, u.crnti, pusch_alloc.slot); return alloc_outcome::skip_slot; } if (not cell_cfg.is_ul_enabled(pusch_alloc.slot)) { - logger.warning("rnti={} Failed to allocate PUSCH in slot={}. Cause: UL is not active in the PUSCH slot (k2={})", - u.crnti, - pusch_alloc.slot, - pusch_td_cfg.k2); + logger.warning( + "ue={} rnti={}: Failed to allocate PUSCH in slot={}. Cause: UL is not active in the PUSCH slot (k2={})", + u.ue_index, + u.crnti, + pusch_alloc.slot, + pusch_td_cfg.k2); return alloc_outcome::invalid_params; } if (pusch_alloc.result.ul.puschs.size() >= expert_cfg.max_puschs_per_slot) { - logger.info("Failed to allocate PUSCH. Cause: Max number of PUSCHs per slot {} was reached.", + logger.info("ue={} rnti={}: Failed to allocate PUSCH. Cause: Max number of PUSCHs per slot {} was reached.", + u.ue_index, + u.crnti, expert_cfg.max_puschs_per_slot); return alloc_outcome::skip_slot; } // Verify there is space in PUSCH and PDCCH result lists for new allocations. if (pusch_alloc.result.ul.puschs.full() or pdcch_alloc.result.dl.ul_pdcchs.full()) { - logger.warning("rnti={} Failed to allocate PUSCH in slot={}. Cause: No space available in scheduler output list", - u.crnti, - pusch_alloc.slot); + logger.warning( + "ue={} rnti={}: Failed to allocate PUSCH in slot={}. Cause: No space available in scheduler output list", + u.ue_index, + u.crnti, + pusch_alloc.slot); return alloc_outcome::skip_slot; } @@ -574,8 +607,9 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // when the UE does not have a dedicated configuration. if (ue_cc->is_in_fallback_mode()) { if (nof_pucch_grants != 0) { - logger.debug("rnti={} Allocation of PUSCH in slot={} skipped. Cause: this UE is in fallback mode and has " + logger.debug("ue={} rnti={}: Allocation of PUSCH in slot={} skipped. Cause: this UE is in fallback mode and has " "PUCCH grants scheduled", + u.ue_index, u.crnti, pusch_alloc.slot); return alloc_outcome::skip_ue; @@ -598,7 +632,9 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr if (pusch_alloc.result.ul.puschs.size() >= expert_cfg.max_ul_grants_per_slot - (static_cast(pusch_alloc.result.ul.pucchs.size()) - nof_pucch_grants)) { - logger.info("Failed to allocate PUSCH. Cause: Max number of UL grants per slot {} was reached.", + logger.info("ue={} rnti={}: Failed to allocate PUSCH. Cause: Max number of UL grants per slot {} was reached.", + u.ue_index, + u.crnti, expert_cfg.max_puschs_per_slot); return alloc_outcome::skip_slot; } @@ -606,6 +642,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // Verify CRBs allocation. if (not ss_info->ul_crb_lims.contains(grant.crbs)) { logger.warning("rnti={} Failed to allocate PUSCH. Cause: CRBs {} allocated outside the BWP {}", + u.ue_index, u.crnti, grant.crbs, ss_info->ul_crb_lims); @@ -614,19 +651,21 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // In case of retx, ensure the number of PRBs for the grant did not change. if (not h_ul.empty() and grant.crbs.length() != h_ul.last_tx_params().rbs.type1().length()) { - logger.warning( - "rnti={} Failed to allocate PUSCH. Cause: Number of CRBs has to remain constant during retxs (harq-id={}, " - "nof_prbs={}!={})", - u.crnti, - h_ul.id, - h_ul.last_tx_params().rbs.type1().length(), - grant.crbs.length()); + logger.warning("ue={} rnti={}: Failed to allocate PUSCH. Cause: Number of CRBs has to remain constant during retxs " + "(harq-id={}, " + "nof_prbs={}!={})", + u.ue_index, + u.crnti, + h_ul.id, + h_ul.last_tx_params().rbs.type1().length(), + grant.crbs.length()); return alloc_outcome::invalid_params; } // Verify there is no RB collision. if (pusch_alloc.ul_res_grid.collides(scs, pusch_td_cfg.symbols, grant.crbs)) { - logger.warning("rnti={} Failed to allocate PUSCH. Cause: No space available in scheduler RB resource grid.", + logger.warning("ue={} rnti={}: Failed to allocate PUSCH. Cause: No space available in scheduler RB resource grid.", + u.ue_index, u.crnti); return alloc_outcome::invalid_params; } @@ -636,7 +675,7 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr get_pdcch_sched(grant.cell_index) .alloc_ul_pdcch_ue(pdcch_alloc, u.crnti, ue_cell_cfg, ss_cfg.get_id(), grant.aggr_lvl); if (pdcch == nullptr) { - logger.info("rnti={}: Failed to allocate PUSCH. Cause: No space in PDCCH.", u.crnti); + logger.info("ue={} rnti={}: Failed to allocate PUSCH. Cause: No space in PDCCH.", u.ue_index, u.crnti); return alloc_outcome::skip_ue; } @@ -684,9 +723,10 @@ alloc_outcome ue_cell_grid_allocator::allocate_ul_grant(const ue_pusch_grant& gr // If there is not MCS-TBS info, it means no MCS exists such that the effective code rate is <= 0.95. if (not mcs_tbs_info.has_value()) { logger.warning( - "rnti={} Failed to allocate PUSCH. Cause: no MCS such that code rate <= 0.95 with this " + "ue={} rnti={}: Failed to allocate PUSCH. Cause: no MCS such that code rate <= 0.95 with this " "configuration: mcs={} crbs={} symbols={} nof_oh={} tb-sc-field={} layers={} pi2bpsk={} " "harq_bits={} csi1_bits={} csi2_bits={} mcs_table_idx={} dmrs_A_pos={} is_dmrs_type2={} dmrs_add_pos_idx={}", + u.ue_index, u.crnti, grant.mcs.to_uint(), grant.crbs, diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 96f211aaf0..9ee26a1c57 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -90,9 +90,10 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ // Forward DL BO update to UE. u.handle_dl_buffer_state_indication(dl_bo); - if (dl_bo.lcid == LCID_SRB0) { - // Signal SRB0 scheduler with the new SRB0 buffer state. - parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication(dl_bo.ue_index); + if (dl_bo.lcid == LCID_SRB0 or (u.get_pcell().is_in_fallback_mode() and dl_bo.lcid == LCID_SRB1)) { + // Signal SRB fallback scheduler with the new SRB0/SRB1 buffer state. + parent.du_cells[u.get_pcell().cell_index].fallback_sched->handle_dl_buffer_state_indication_srb( + dl_bo.ue_index, dl_bo.lcid == LCID_SRB0); } // Log event. @@ -301,18 +302,18 @@ void ue_event_manager::handle_crc_indication(const ul_crc_indication& crc_ind) return; } + // Process Timing Advance Offset. + if (crc.tb_crc_success and crc.time_advance_offset.has_value() and crc.ul_sinr_metric.has_value()) { + ue_db[ue_cc.ue_index].handle_ul_n_ta_update_indication( + ue_cc.cell_index, crc.ul_sinr_metric.value(), crc.time_advance_offset.value()); + } + // Log event. ev_logger.enqueue(scheduler_event_logger::crc_event{ crc.ue_index, crc.rnti, ue_cc.cell_index, sl_rx, crc.harq_id, crc.tb_crc_success, crc.ul_sinr_metric}); // Notify metrics handler. metrics_handler.handle_crc_indication(crc, units::bytes{(unsigned)tbs}); - - // Process Timing Advance Offset. - if (crc.tb_crc_success and crc.time_advance_offset.has_value() and crc.ul_sinr_metric.has_value()) { - ue_db[ue_cc.ue_index].handle_ul_n_ta_update_indication( - ue_cc.cell_index, crc.ul_sinr_metric.value(), crc.time_advance_offset.value()); - } }, "CRC", true); @@ -351,9 +352,6 @@ void ue_event_manager::handle_csi(ue_cell& ue_cc, const csi_report_data& csi_rep // Log event. ev_logger.enqueue(scheduler_event_logger::csi_report_event{ue_cc.ue_index, ue_cc.rnti(), csi_rep}); - - // Report the CSI metric. - metrics_handler.handle_csi_report(ue_cc.ue_index, csi_rep); } void ue_event_manager::handle_uci_indication(const uci_indication& ind) @@ -365,9 +363,9 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) cell_specific_events[ind.cell_index].emplace( uci.ue_index, - [this, uci_sl = ind.slot_rx, uci_pdu = uci.pdu](ue_cell& ue_cc) { - if (variant_holds_alternative(uci_pdu)) { - const auto& pdu = variant_get(uci_pdu); + [this, uci_sl = ind.slot_rx, uci_pdu = uci](ue_cell& ue_cc) { + if (variant_holds_alternative(uci_pdu.pdu)) { + const auto& pdu = variant_get(uci_pdu.pdu); // Process DL HARQ ACKs. if (not pdu.harqs.empty()) { @@ -383,9 +381,6 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) ev_logger.enqueue(scheduler_event_logger::sr_event{ue_cc.ue_index, ue_cc.rnti()}); } - // Report the PUCCH SINR metric. - metrics_handler.handle_pucch_sinr(ue_cc.ue_index, pdu.ul_sinr); - const bool is_uci_valid = not pdu.harqs.empty() or pdu.sr_detected; // Process Timing Advance Offset. if (is_uci_valid and pdu.time_advance_offset.has_value() and pdu.ul_sinr.has_value()) { @@ -393,8 +388,8 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) ue_cc.cell_index, pdu.ul_sinr.value(), pdu.time_advance_offset.value()); } - } else if (variant_holds_alternative(uci_pdu)) { - const auto& pdu = variant_get(uci_pdu); + } else if (variant_holds_alternative(uci_pdu.pdu)) { + const auto& pdu = variant_get(uci_pdu.pdu); // Process DL HARQ ACKs. if (not pdu.harqs.empty()) { @@ -406,8 +401,8 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) handle_csi(ue_cc, *pdu.csi); } - } else if (variant_holds_alternative(uci_pdu)) { - const auto& pdu = variant_get(uci_pdu); + } else if (variant_holds_alternative(uci_pdu.pdu)) { + const auto& pdu = variant_get(uci_pdu.pdu); // Process DL HARQ ACKs. if (not pdu.harqs.empty()) { @@ -429,9 +424,6 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) handle_csi(ue_cc, *pdu.csi); } - // Report the PUCCH metric to the scheduler. - metrics_handler.handle_pucch_sinr(ue_cc.ue_index, pdu.ul_sinr); - const bool is_uci_valid = not pdu.harqs.empty() or (not pdu.sr_info.empty() and pdu.sr_info.test(sr_bit_position_with_1_sr_bit)) or pdu.csi.has_value(); @@ -441,6 +433,9 @@ void ue_event_manager::handle_uci_indication(const uci_indication& ind) ue_cc.cell_index, pdu.ul_sinr.value(), pdu.time_advance_offset.value()); } } + + // Report the UCI PDU to the metrics handler. + metrics_handler.handle_uci_pdu_indication(uci_pdu); }, "UCI", // Note: We do not warn if the UE is not found, because there is this transient period when the UE @@ -649,16 +644,16 @@ void ue_event_manager::run(slot_point sl, du_cell_index_t cell_index) } void ue_event_manager::add_cell(cell_resource_allocator& cell_res_grid, - ue_srb0_scheduler& srb0_sched, + ue_fallback_scheduler& fallback_sched, uci_scheduler_impl& uci_sched) { const du_cell_index_t cell_index = cell_res_grid.cell_index(); srsran_assert(not cell_exists(cell_index), "Overwriting cell configurations not supported"); - du_cells[cell_index].cfg = &cell_res_grid.cfg; - du_cells[cell_index].res_grid = &cell_res_grid; - du_cells[cell_index].srb0_sched = &srb0_sched; - du_cells[cell_index].uci_sched = &uci_sched; + du_cells[cell_index].cfg = &cell_res_grid.cfg; + du_cells[cell_index].res_grid = &cell_res_grid; + du_cells[cell_index].fallback_sched = &fallback_sched; + du_cells[cell_index].uci_sched = &uci_sched; } bool ue_event_manager::cell_exists(du_cell_index_t cell_index) const diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.h b/lib/scheduler/ue_scheduling/ue_event_manager.h index 5be34e8bbf..6edeb3a8ce 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.h +++ b/lib/scheduler/ue_scheduling/ue_event_manager.h @@ -26,7 +26,7 @@ #include "../policy/scheduler_policy.h" #include "../support/slot_event_list.h" #include "ue.h" -#include "ue_srb0_scheduler.h" +#include "ue_fallback_scheduler.h" #include "srsran/adt/unique_function.h" #include "srsran/ran/du_types.h" #include "srsran/ran/uci/uci_constants.h" @@ -48,7 +48,9 @@ class ue_event_manager final : public sched_ue_configuration_handler, ue_event_manager(ue_repository& ue_db, scheduler_metrics_handler& metrics_handler, scheduler_event_logger& ev_logger); ~ue_event_manager(); - void add_cell(cell_resource_allocator& cell_res_grid, ue_srb0_scheduler& srb0_sched, uci_scheduler_impl& uci_sched); + void add_cell(cell_resource_allocator& cell_res_grid, + ue_fallback_scheduler& fallback_sched, + uci_scheduler_impl& uci_sched); /// UE Add/Mod/Remove interface. void handle_ue_creation(ue_config_update_event ev) override; @@ -124,8 +126,8 @@ class ue_event_manager final : public sched_ue_configuration_handler, cell_resource_allocator* res_grid = nullptr; - // Reference to SRB0 and other bearers scheduler - ue_srb0_scheduler* srb0_sched = nullptr; + // Reference to fallback scheduler. + ue_fallback_scheduler* fallback_sched = nullptr; // Reference to the CSI and SR UCI scheduler. uci_scheduler_impl* uci_sched = nullptr; diff --git a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp new file mode 100644 index 0000000000..c2f08a28f8 --- /dev/null +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp @@ -0,0 +1,763 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "ue_fallback_scheduler.h" +#include "../support/csi_rs_helpers.h" +#include "../support/dci_builder.h" +#include "../support/dmrs_helpers.h" +#include "../support/pdsch/pdsch_resource_allocation.h" +#include "../support/prbs_calculator.h" +#include "srsran/ran/sch/tbs_calculator.h" + +using namespace srsran; + +ue_fallback_scheduler::ue_fallback_scheduler(const scheduler_ue_expert_config& expert_cfg_, + const cell_configuration& cell_cfg_, + pdcch_resource_allocator& pdcch_sch_, + pucch_allocator& pucch_alloc_, + ue_repository& ues_) : + expert_cfg(expert_cfg_), + cell_cfg(cell_cfg_), + pdcch_sch(pdcch_sch_), + pucch_alloc(pucch_alloc_), + ues(ues_), + initial_active_dl_bwp(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params), + ss_cfg(cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common + .search_spaces[cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common.ra_search_space_id]), + cs_cfg(cell_cfg.get_common_coreset(ss_cfg.get_coreset_id())), + logger(srslog::fetch_basic_logger("SCHED")) +{ + ongoing_ues_ack_retxs.reserve(MAX_NOF_DU_UES); + // NOTE: We use a std::vector instead of a std::array because we can later on initialize the vector with the minimum + // value of k1, passed through the expert config. + dci_1_0_k1_values = {4, 5, 6, 7, 8}; +} + +void ue_fallback_scheduler::run_slot(cell_resource_allocator& res_alloc) +{ + // Update the HARQ processes of UE with ongoing transmissions to check which ones still need to be acked or + // retransmitted. + update_ongoing_ue_retxs(); + + // Reset the scheduling attempt counter; this takes into account retxs and new txs. + sched_attempts_cnt = 0; + + if (ues.empty()) { + return; + } + + // Although the scheduler can schedule on future slots, we run the scheduler only in DL enabled slots. + if (not cell_cfg.is_dl_enabled(res_alloc[0].slot)) { + return; + } + + for (auto& next_ue_harq_retx : ongoing_ues_ack_retxs) { + auto& u = *ues.find(next_ue_harq_retx.ue_index); + auto* h_dl = next_ue_harq_retx.h_dl; + + if (h_dl->has_pending_retx()) { + optional most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + schedule_srb(res_alloc, u, next_ue_harq_retx.is_srb0, h_dl, most_recent_tx_ack); + } + } + + // Schedule SRB0 messages before SRB1, as we prioritize SRB0 over SRB1. + for (auto next_ue = pending_ues.begin(); next_ue != pending_ues.end();) { + if (not next_ue->is_srb0) { + ++next_ue; + continue; + } + + // The UE might have been deleted in the meantime, check if still exists. + if (not ues.contains(next_ue->ue_index)) { + next_ue = pending_ues.erase(next_ue); + continue; + } + + auto& u = ues[next_ue->ue_index]; + optional most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb(res_alloc, u, true, nullptr, most_recent_tx_ack)) { + next_ue = pending_ues.erase(next_ue); + } else { + ++next_ue; + } + } + + // Keep SRB1 with lower priority than SRB0. + for (auto next_ue = pending_ues.begin(); next_ue != pending_ues.end();) { + if (next_ue->is_srb0) { + ++next_ue; + continue; + } + + // The UE might have been deleted in the meantime, check if still exists. + if (not ues.contains(next_ue->ue_index)) { + next_ue = pending_ues.erase(next_ue); + continue; + } + + auto& u = ues[next_ue->ue_index]; + optional most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + // NOTE: Since SRB1 data can be segmented, it could happen that not all the SRB1 bytes are scheduled at once. The + // scheduler will attempt to allocate those remaining bytes in the following slots. The policy we adopt in this + // scheduler is to schedule first all possible grants to a given UE (to speed up the re-establishment and + // re-configuration). Only after the SRB1 buffer of that UE is emptied, we move on to the next UE. + if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx_ack)) { + // If all bytes of SRB1 are scheduled, remove UE. + if (not u.has_pending_dl_newtx_bytes(LCID_SRB1)) { + next_ue = pending_ues.erase(next_ue); + } + // Don't increase the iterator here, as we give priority to the same UE, if there are still some SRB1 bytes left + // in the buffer. + } else { + ++next_ue; + } + } +} + +void ue_fallback_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) +{ + pending_ues.push_back({ue_index, is_srb0}); +} + +static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_point sl_tx) +{ + slot_point next_candidate_slot = sl_tx + 1U; + + // In FDD, we advance by 1 slot. + if (not cell_cfg.is_tdd()) { + return next_candidate_slot; + } + + // In TDD, advance the slot until it's a DL slot. + while (not cell_cfg.is_dl_enabled(next_candidate_slot)) { + next_candidate_slot = next_candidate_slot + 1U; + } + return next_candidate_slot; +} + +bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_alloc, + ue& u, + bool is_srb0, + dl_harq_process* h_dl_retx, + optional most_recent_tx_ack_slots) +{ + const auto& bwp_cfg_common = cell_cfg.dl_cfg_common.init_dl_bwp; + // Search valid PDSCH time domain resource. + + const bool is_retx = h_dl_retx != nullptr; + + // \ref sched_ref_slot is the slot that we take as reference for the scheduler, which is processed when calling the + // slot_indication(). + // NOTE: we guarantee that \ref sched_ref_slot is a DL slot in the caller. + // TODO: Make this compatible with k0 > 0. + slot_point sched_ref_slot = res_alloc[0].slot; + + // This is to prevent the edge case of the scheduler trying to allocate an SRB PDSCH in the farthest possible slot in + // the future when, in the same slot, there is already an SRB PDSCH allocated. This can happen, for example, if there + // is a retransmission (previously) allocated at slot sched_ref_slot + max_dl_slots_ahead_sched, and then the + // scheduler attempt to allocate a new TX on the same slot. + if (most_recent_tx_ack_slots.has_value() and + sched_ref_slot + max_dl_slots_ahead_sched <= most_recent_tx_ack_slots.value().most_recent_tx_slot) { + return false; + } + + // \ref starting_slot is the slot from which the SRB0 starts scheduling this given UE. Assuming the UE was assigned a + // PDSCH grant for SRB1 that was fragmented, we want to avoid allocating the second part of SRB1 in a PDSCH that is + // scheduled for an earlier slot than the PDSCH of the first part of the SRB1. + // NOTE: The \c most_recent_tx_slot is not necessarily more recent than sched_ref_slot; hence we need to check that + // most_recent_tx_ack_slots.value().most_recent_tx_slot > sched_ref_slot. + slot_point starting_slot = + most_recent_tx_ack_slots.has_value() and most_recent_tx_ack_slots.value().most_recent_tx_slot > sched_ref_slot + ? most_recent_tx_ack_slots.value().most_recent_tx_slot + : sched_ref_slot; + + for (slot_point next_slot = starting_slot; next_slot <= sched_ref_slot + max_dl_slots_ahead_sched; + next_slot = get_next_srb_slot(cell_cfg, next_slot)) { + auto offset_to_sched_ref_slot = static_cast(next_slot - sched_ref_slot); + const cell_slot_resource_allocator& pdcch_alloc = res_alloc[offset_to_sched_ref_slot]; + + for (unsigned time_res_idx = 0; time_res_idx != bwp_cfg_common.pdsch_common.pdsch_td_alloc_list.size(); + ++time_res_idx) { + if (sched_attempts_cnt >= max_sched_attempts) { + return false; + } + + const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(time_res_idx); + const cell_slot_resource_allocator& pdsch_alloc = res_alloc[offset_to_sched_ref_slot + pdsch_td_cfg.k0]; + + if (not cell_cfg.is_dl_enabled(pdsch_alloc.slot)) { + continue; + } + + // We do not support multiplexing of PDSCH for SRB0 and SRB1 when in fallback with CSI-RS. + const bool is_csi_rs_slot = next_slot == sched_ref_slot ? not pdsch_alloc.result.dl.csi_rs.empty() + : csi_helper::is_csi_rs_slot(cell_cfg, pdsch_alloc.slot); + if (is_csi_rs_slot) { + continue; + } + + // Check whether PDSCH time domain resource does not overlap with CORESET. + if (pdsch_td_cfg.symbols.start() < ss_cfg.get_first_symbol_index() + cs_cfg.duration) { + continue; + } + + // Check whether PDSCH time domain resource fits in DL symbols of the slot. + if (pdsch_td_cfg.symbols.stop() > cell_cfg.get_nof_dl_symbol_per_slot(pdsch_alloc.slot)) { + continue; + } + + if (is_retx and h_dl_retx->last_alloc_params().nof_symbols != pdsch_td_cfg.symbols.length()) { + continue; + } + + // Verify there is space in PDSCH and PDCCH result lists for new allocations. + if (pdcch_alloc.result.dl.dl_pdcchs.full() or pdsch_alloc.result.dl.ue_grants.full()) { + logger.debug("rnti={}: Failed to allocate PDSCH for {}. Cause: No space available in scheduler output list", + u.crnti, + is_srb0 ? "SRB0" : "SRB1"); + return false; + } + + // As it is not possible to schedule a PDSCH whose related PUCCH falls in a slot that is the same as or older than + // the most recent already scheduled ACK slot (for the same UE), whenever we detect this is the case we skip the + // allocation in advance. + slot_point most_recent_ack_slot = pdsch_alloc.slot; + if (most_recent_tx_ack_slots.has_value()) { + if (pdsch_alloc.slot + dci_1_0_k1_values.back() <= most_recent_tx_ack_slots.value().most_recent_ack_slot) { + continue; + } + most_recent_ack_slot = most_recent_tx_ack_slots.value().most_recent_ack_slot; + } + + dl_harq_process* candidate_h_dl = + is_srb0 + ? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, most_recent_ack_slot, h_dl_retx) + : schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, most_recent_ack_slot, h_dl_retx); + + const bool alloc_successful = candidate_h_dl != nullptr; + if (alloc_successful) { + if (not is_retx) { + store_harq_tx(u.ue_index, candidate_h_dl, is_srb0); + } + return true; + } + + ++sched_attempts_cnt; + } + } + + // No resource found in UE's carriers and Search spaces. + slot_point pdcch_slot = res_alloc[0].slot; + logger.debug("rnti={}: Not enough PDCCH/PDSCH/PUCCH resources for {} message found in any of the slots:[{},{})", + u.crnti, + is_srb0 ? "SRB0" : "SRB1", + pdcch_slot, + pdcch_slot + max_dl_slots_ahead_sched + 1); + return false; +} + +dl_harq_process* ue_fallback_scheduler::schedule_srb0(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + slot_point most_recent_ack_slot, + dl_harq_process* h_dl_retx) +{ + ue_cell& ue_pcell = u.get_pcell(); + const subcarrier_spacing scs = cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs; + const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(pdsch_time_res); + + pdsch_config_params pdsch_cfg = get_pdsch_config_f1_0_tc_rnti(cell_cfg, pdsch_td_cfg); + + const bool is_retx = h_dl_retx != nullptr; + + // Search for empty HARQ. + dl_harq_process* h_dl = is_retx ? h_dl_retx : ue_pcell.harqs.find_empty_dl_harq(); + if (h_dl == nullptr) { + logger.warning("rnti={}: UE must have empty HARQs during SRB0 PDU allocation", u.crnti); + return nullptr; + } + + cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + pdsch_td_cfg.k0]; + auto cset0_crbs_lim = pdsch_helper::get_ra_crb_limits_common(cell_cfg.dl_cfg_common.init_dl_bwp, ss_cfg.get_id()); + prb_bitmap used_crbs = + pdsch_alloc.dl_res_grid.used_crbs(initial_active_dl_bwp.scs, cset0_crbs_lim, pdsch_cfg.symbols); + + sch_prbs_tbs prbs_tbs{}; + sch_mcs_index mcs_idx = 0; + if (is_retx) { + // Use the same MCS, nof PRBs and TBS as the last allocation. + mcs_idx = h_dl->last_alloc_params().tb[0]->mcs; + prbs_tbs.nof_prbs = h_dl->last_alloc_params().rbs.type1().length(); + prbs_tbs.tbs_bytes = h_dl->last_alloc_params().tb[0].value().tbs_bytes; + } else { + // Fetch the pending bytes in the SRB0 buffer + pending MAC Contention Resolution CEs bytes. + const unsigned pending_bytes = u.pending_dl_srb0_or_srb1_newtx_bytes(true); + + crb_interval unused_crbs = + rb_helper::find_next_empty_interval(used_crbs, cset0_crbs_lim.start(), cset0_crbs_lim.stop()); + + // Try to find least MCS to fit SRB0 message. + while (mcs_idx <= expert_cfg.max_msg4_mcs) { + // As per TS 38.214, clause 5.1.3.1, if the PDSCH is scheduled by a PDCCH with CRC scrambled by TC-RNTI, the UE + // use "Table 5.1.3.1-1: MCS index table 1" for MCS mapping. This is not stated explicitly, but can be inferred + // from the sentence "... the UE shall use I_MCS and Table 5.1.3.1-1 to determine the modulation order (Qm) and + // Target code rate (R) used in the physical downlink shared channel.". + + // At this point, xOverhead is not configured yet. As per TS 38.214, Clause 5.1.3.2, xOverhead is assumed to be 0. + const sch_mcs_description mcs_config = pdsch_mcs_get_config(pdsch_mcs_table::qam64, mcs_idx); + prbs_tbs = get_nof_prbs(prbs_calculator_sch_config{pending_bytes, + static_cast(pdsch_cfg.symbols.length()), + calculate_nof_dmrs_per_rb(pdsch_cfg.dmrs), + pdsch_cfg.nof_oh_prb, + mcs_config, + pdsch_cfg.nof_layers}); + if (unused_crbs.length() >= prbs_tbs.nof_prbs) { + break; + } + ++mcs_idx; + } + + if (prbs_tbs.tbs_bytes < pending_bytes) { + logger.debug( + "rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({})", pending_bytes, prbs_tbs.tbs_bytes, u.crnti); + return nullptr; + } + + if (mcs_idx > expert_cfg.max_msg4_mcs) { + logger.debug("rnti={}: Postponing SRB0 PDU allocation. Cause: MCS index chosen ({}) for SRB0 exceeds maximum" + " allowed MCS index ({})", + u.crnti, + mcs_idx, + expert_cfg.max_msg4_mcs); + return nullptr; + } + } + + crb_interval ue_grant_crbs = rb_helper::find_empty_interval_of_length(used_crbs, prbs_tbs.nof_prbs, 0); + if (ue_grant_crbs.length() < prbs_tbs.nof_prbs) { + logger.debug("rnti={}: Postponed SRB0 PDU scheduling. Cause: Not enough PRBs ({} < {})", + u.crnti, + ue_grant_crbs.length(), + prbs_tbs.nof_prbs); + return nullptr; + } + + // Allocate PDCCH resources. + cell_slot_resource_allocator& pdcch_alloc = res_alloc[slot_offset]; + pdcch_dl_information* pdcch = + pdcch_sch.alloc_dl_pdcch_common(pdcch_alloc, u.crnti, ss_cfg.get_id(), aggregation_level::n4); + if (pdcch == nullptr) { + logger.debug( + "rnti={}: Postponed SRB0 PDU scheduling for slot. Cause: No space in PDCCH.", u.crnti, pdsch_alloc.slot); + return nullptr; + } + + // Allocate PUCCH resources. + unsigned k1 = dci_1_0_k1_values.front(); + // Minimum k1 value supported is 4. + optional pucch_res_indicator; + for (const auto k1_candidate : dci_1_0_k1_values) { + // Skip k1 values that would result in a PUCCH transmission in a slot that is older than the most recent ACK slot. + if (pdsch_alloc.slot + k1_candidate <= most_recent_ack_slot) { + continue; + } + pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue( + res_alloc, u.crnti, slot_offset + pdsch_td_cfg.k0, k1_candidate, *pdcch); + if (pucch_res_indicator.has_value()) { + k1 = k1_candidate; + break; + } + } + if (not pucch_res_indicator.has_value()) { + logger.debug( + "rnti={}: Failed to allocate PDSCH for SRB0 for slot={}. Cause: No space in PUCCH", u.crnti, pdsch_alloc.slot); + pdcch_sch.cancel_last_pdcch(pdcch_alloc); + return nullptr; + } + + // Mark resources as occupied in the ResourceGrid. + pdsch_alloc.dl_res_grid.fill(grant_info{scs, pdsch_td_cfg.symbols, ue_grant_crbs}); + + const bool is_srb0 = true; + dci_dl_rnti_config_type dci_type = dci_dl_rnti_config_type::tc_rnti_f1_0; + fill_srb_grant(u, + pdsch_alloc.slot, + *h_dl, + *pdcch, + dci_type, + pdsch_alloc.result.dl.ue_grants.emplace_back(), + pucch_res_indicator.value(), + pdsch_time_res, + k1, + mcs_idx, + ue_grant_crbs, + pdsch_cfg, + prbs_tbs.tbs_bytes, + is_retx, + is_srb0); + + return h_dl; +} + +dl_harq_process* ue_fallback_scheduler::schedule_srb1(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + slot_point most_recent_ack_slot, + dl_harq_process* h_dl_retx) +{ + ue_cell& ue_pcell = u.get_pcell(); + const subcarrier_spacing scs = cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs; + const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(pdsch_time_res); + + const bool is_retx = h_dl_retx != nullptr; + + // Search for empty HARQ. + dl_harq_process* h_dl = is_retx ? h_dl_retx : ue_pcell.harqs.find_empty_dl_harq(); + if (h_dl == nullptr) { + return nullptr; + } + + dci_dl_rnti_config_type dci_type = dci_dl_rnti_config_type::c_rnti_f1_0; + if (is_retx) { + dci_type = h_dl->last_alloc_params().dci_cfg_type; + } else if (u.is_conres_ce_pending()) { + dci_type = dci_dl_rnti_config_type::tc_rnti_f1_0; + } + srsran_assert(dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 or dci_type == dci_dl_rnti_config_type::c_rnti_f1_0, + "Only DCI 1_0 with TC-RNTI or C-RNTI is supported for SRB1 scheduling"); + + pdsch_config_params pdsch_cfg = dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 + ? get_pdsch_config_f1_0_tc_rnti(cell_cfg, pdsch_td_cfg) + : get_pdsch_config_f1_0_c_rnti(cell_cfg, nullptr, pdsch_td_cfg); + + // For DCI 1-0 scrambled with TC-RNTI, as per TS 38.213, Section 7.3.1.2.1, we should consider the size of CORESET#0 + // as the size for the BWP. + // For DCI 1-0 scrambled with C-RNTI, if the DCI is monitored in a common search space and CORESET#0 is configured + // for the cell, as per TS 38.213, Section 7.3.1.0, we should consider the size of CORESET#0 as the size for the BWP. + cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + pdsch_td_cfg.k0]; + prb_bitmap used_crbs = pdsch_alloc.dl_res_grid.used_crbs( + initial_active_dl_bwp.scs, + pdsch_helper::get_ra_crb_limits_common(cell_cfg.dl_cfg_common.init_dl_bwp, ss_cfg.get_id()), + pdsch_cfg.symbols); + + crb_interval ue_grant_crbs; + sch_mcs_tbs final_mcs_tbs; + + if (is_retx) { + const unsigned final_nof_prbs = h_dl->last_alloc_params().rbs.type1().length(); + final_mcs_tbs.mcs = h_dl->last_alloc_params().tb.front().value().mcs; + final_mcs_tbs.tbs = h_dl->last_alloc_params().tb.front().value().tbs_bytes; + + ue_grant_crbs = rb_helper::find_empty_interval_of_length(used_crbs, final_nof_prbs, 0); + if (ue_grant_crbs.empty() or ue_grant_crbs.length() < final_nof_prbs) { + return nullptr; + } + + } else { + // Find available symbol x RB resources. + const unsigned pending_bytes = dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 + ? u.pending_dl_srb0_or_srb1_newtx_bytes(false) + : u.pending_dl_newtx_bytes(lcid_t::LCID_SRB1); + grant_prbs_mcs mcs_prbs_estimate = ue_pcell.required_dl_prbs(pdsch_td_cfg, pending_bytes, dci_type); + + if (mcs_prbs_estimate.n_prbs == 0) { + return nullptr; + } + + // [Implementation-defined] In case of partial slots and nof. PRBs allocated equals to 1 probability of KO is + // high due to code not being able to cope with interference. So the solution is to increase the PRB allocation + // to greater than 1 PRB. + const bool set_min_nof_prbs = not cell_cfg.is_fully_dl_enabled(pdsch_alloc.slot) and mcs_prbs_estimate.n_prbs == 1; + const unsigned min_nof_prbs_partial_slots = 2U; + if (set_min_nof_prbs) { + mcs_prbs_estimate.n_prbs = min_nof_prbs_partial_slots; + } + + ue_grant_crbs = rb_helper::find_empty_interval_of_length(used_crbs, mcs_prbs_estimate.n_prbs, 0); + if (ue_grant_crbs.empty() or (set_min_nof_prbs and ue_grant_crbs.length() < min_nof_prbs_partial_slots)) { + return nullptr; + } + + const unsigned final_nof_prbs = ue_grant_crbs.length(); + // As \c txDirectCurrentLocation, in \c SCS-SpecificCarrier, TS 38.331, "If this field (\c txDirectCurrentLocation) + // is absent for downlink within ServingCellConfigCommon and ServingCellConfigCommonSIB, the UE assumes the default + // value of 3300 (i.e. "Outside the carrier")". + bool contains_dc = false; + if (cell_cfg.dl_cfg_common.freq_info_dl.scs_carrier_list.back().tx_direct_current_location.has_value()) { + contains_dc = dc_offset_helper::is_contained( + cell_cfg.dl_cfg_common.freq_info_dl.scs_carrier_list.back().tx_direct_current_location.value(), + ue_grant_crbs); + } + optional mcs_tbs = compute_dl_mcs_tbs(pdsch_cfg, mcs_prbs_estimate.mcs, final_nof_prbs, contains_dc); + + // If there is not MCS-TBS info, it means no MCS exists such that the effective code rate is <= 0.95. + if (not mcs_tbs.has_value()) { + logger.warning( + "ue={} rnti={}: Failed to allocate PDSCH. Cause: no MCS such that code rate <= 0.95.", u.ue_index, u.crnti); + return nullptr; + } + final_mcs_tbs = mcs_tbs.value(); + } + + // Allocate PDCCH resources. + cell_slot_resource_allocator& pdcch_alloc = res_alloc[slot_offset]; + pdcch_dl_information* pdcch = + pdcch_sch.alloc_dl_pdcch_common(pdcch_alloc, u.crnti, ss_cfg.get_id(), aggregation_level::n4); + if (pdcch == nullptr) { + logger.debug("rnti={}: Postponed SRB0 PDU scheduling. Cause: No space in PDCCH.", u.crnti); + return nullptr; + } + + // Allocate PUCCH resources. + unsigned k1 = dci_1_0_k1_values.front(); + // Minimum k1 value supported is 4. + optional pucch_res_indicator; + for (const auto k1_candidate : dci_1_0_k1_values) { + // Skip the k1 values that would result in a PUCCH allocation that would overlap with the most recent ACK slot. + if (pdsch_alloc.slot + k1_candidate <= most_recent_ack_slot) { + continue; + } + pucch_res_indicator = pucch_alloc.alloc_common_pucch_harq_ack_ue( + res_alloc, u.crnti, slot_offset + pdsch_td_cfg.k0, k1_candidate, *pdcch); + if (pucch_res_indicator.has_value()) { + k1 = k1_candidate; + break; + } + } + if (not pucch_res_indicator.has_value()) { + logger.debug( + "rnti={}: Failed to allocate PDSCH for SRB0 for slot={}. Cause: No space in PUCCH", u.crnti, pdsch_alloc.slot); + pdcch_sch.cancel_last_pdcch(pdcch_alloc); + return nullptr; + } + + // Mark resources as occupied in the ResourceGrid. + pdsch_alloc.dl_res_grid.fill(grant_info{scs, pdsch_td_cfg.symbols, ue_grant_crbs}); + + const bool is_srb0 = false; + fill_srb_grant(u, + pdsch_alloc.slot, + *h_dl, + *pdcch, + dci_type, + pdsch_alloc.result.dl.ue_grants.emplace_back(), + pucch_res_indicator.value(), + pdsch_time_res, + k1, + final_mcs_tbs.mcs, + ue_grant_crbs, + pdsch_cfg, + final_mcs_tbs.tbs, + is_retx, + is_srb0); + + return h_dl; +} + +void ue_fallback_scheduler::fill_srb_grant(ue& u, + slot_point pdsch_slot, + dl_harq_process& h_dl, + pdcch_dl_information& pdcch, + dci_dl_rnti_config_type dci_type, + dl_msg_alloc& msg, + unsigned pucch_res_indicator, + unsigned pdsch_time_res, + unsigned k1, + sch_mcs_index mcs_idx, + const crb_interval& ue_grant_crbs, + const pdsch_config_params& pdsch_params, + unsigned tbs_bytes, + bool is_retx, + bool is_srb0) +{ + // Allocate DL HARQ. + // NOTE: We do not multiplex the SRB1 PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. + static constexpr uint8_t srb_dai = 0; + if (not is_retx) { + const bool is_fallback = true; + h_dl.new_tx(pdsch_slot, + k1, + expert_cfg.max_nof_harq_retxs, + srb_dai, + u.get_pcell().channel_state_manager().get_wideband_cqi(), + pdsch_params.nof_layers, + is_fallback); + } else { + const unsigned harq_bit_idx = 0U; + h_dl.new_retx(pdsch_slot, k1, harq_bit_idx); + } + + // Fill DL PDCCH DCI. + static const uint8_t msg4_rv = 0; + srsran_sanity_check(is_srb0 ? dci_type == dci_dl_rnti_config_type::tc_rnti_f1_0 : true, "Invalid DCI type for SRB0"); + switch (dci_type) { + case dci_dl_rnti_config_type::tc_rnti_f1_0: { + build_dci_f1_0_tc_rnti(pdcch.dci, + cell_cfg.dl_cfg_common.init_dl_bwp, + ue_grant_crbs, + pdsch_time_res, + k1, + pucch_res_indicator, + mcs_idx, + msg4_rv, + h_dl); + break; + } + case dci_dl_rnti_config_type::c_rnti_f1_0: { + build_dci_f1_0_c_rnti(pdcch.dci, + u.get_pcell().cfg().search_space(pdcch.ctx.context.ss_id), + cell_cfg.dl_cfg_common.init_dl_bwp, + ue_grant_crbs, + pdsch_time_res, + k1, + pucch_res_indicator, + srb_dai, + mcs_idx, + msg4_rv, + h_dl); + break; + } + default: { + srsran_assert(false, "Invalid DCI type for SRB1"); + } + } + + // Fill PDSCH PDU. + msg.context.ue_index = u.ue_index; + msg.context.k1 = k1; + msg.context.ss_id = pdcch.ctx.context.ss_id; + msg.context.nof_retxs = h_dl.tb(0).nof_retxs; + msg.context.olla_offset = 0; + + switch (dci_type) { + case dci_dl_rnti_config_type::tc_rnti_f1_0: { + build_pdsch_f1_0_tc_rnti(msg.pdsch_cfg, + pdsch_params, + tbs_bytes, + u.crnti, + cell_cfg, + pdcch.dci.tc_rnti_f1_0, + ue_grant_crbs, + not is_retx); + + // Set MAC logical channels to schedule in this PDU. + if (not is_retx) { + u.build_dl_fallback_transport_block_info( + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, is_srb0); + } + break; + } + // This is only for SRB1. + case dci_dl_rnti_config_type::c_rnti_f1_0: { + build_pdsch_f1_0_c_rnti(msg.pdsch_cfg, + pdsch_params, + tbs_bytes, + u.crnti, + cell_cfg, + u.get_pcell().cfg().search_space(pdcch.ctx.context.ss_id), + pdcch.dci.c_rnti_f1_0, + ue_grant_crbs, + not is_retx); + // Set MAC logical channels to schedule in this PDU. + if (not is_retx) { + u.build_dl_transport_block_info( + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB1); + } + break; + } + default: { + srsran_assert(false, "Invalid DCI type for SRB1"); + } + } + + // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. + h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); +} + +const pdsch_time_domain_resource_allocation& ue_fallback_scheduler::get_pdsch_td_cfg(unsigned pdsch_time_res_idx) const +{ + return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; +} + +optional +ue_fallback_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const +{ + optional most_recent_tx_ack_slot; + for (const auto& ue_proc : ongoing_ues_ack_retxs) { + if (ue_proc.ue_index == ue_idx) { + slot_point h_dl_slot_tx = ue_proc.h_dl->slot_tx(); + slot_point h_dl_slot_ack = ue_proc.h_dl->slot_ack(); + if (not most_recent_tx_ack_slot.has_value()) { + most_recent_tx_ack_slot.emplace( + most_recent_tx_slots{.most_recent_tx_slot = h_dl_slot_tx, .most_recent_ack_slot = h_dl_slot_ack}); + continue; + } + if (h_dl_slot_tx > most_recent_tx_ack_slot.value().most_recent_tx_slot) { + most_recent_tx_ack_slot.value().most_recent_tx_slot = h_dl_slot_tx; + } + if (h_dl_slot_ack > most_recent_tx_ack_slot.value().most_recent_ack_slot) { + most_recent_tx_ack_slot.value().most_recent_ack_slot = h_dl_slot_ack; + } + } + } + return most_recent_tx_ack_slot; +} + +void ue_fallback_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) +{ + srsran_sanity_check(ongoing_ues_ack_retxs.end() == + std::find_if(ongoing_ues_ack_retxs.begin(), + ongoing_ues_ack_retxs.end(), + [ue_index, h_dl](const ack_and_retx_tracker& tracker) { + return tracker.match_ue_harq(ue_index, h_dl); + }), + "This UE and HARQ process were already in the list"); + + ongoing_ues_ack_retxs.emplace_back(ue_index, h_dl, is_srb0, ues); +} + +void ue_fallback_scheduler::update_ongoing_ue_retxs() +{ + if (ongoing_ues_ack_retxs.empty()) { + return; + } + + // Only remove the {UE, HARQ-process} elements that have been retransmitted and positively acked. The rest of the + // elements are potential candidate for retransmissions. + for (std::vector::iterator it_ue_harq = ongoing_ues_ack_retxs.begin(); + it_ue_harq != ongoing_ues_ack_retxs.end();) { + if (not ues.contains(it_ue_harq->ue_index)) { + it_ue_harq = ongoing_ues_ack_retxs.erase(it_ue_harq); + continue; + } + + dl_harq_process& h_dl = *it_ue_harq->h_dl; + if (h_dl.empty()) { + it_ue_harq = ongoing_ues_ack_retxs.erase(it_ue_harq); + continue; + } + ++it_ue_harq; + } +} diff --git a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h new file mode 100644 index 0000000000..ab31b94478 --- /dev/null +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h @@ -0,0 +1,171 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "../policy/ue_allocator.h" +#include "../support/sch_pdu_builder.h" +#include "../support/slot_event_list.h" +#include "ue_repository.h" +#include "srsran/scheduler/scheduler_configurator.h" +#include +#include + +namespace srsran { + +/// Defines SRB0 scheduler that is used to allocate grants for UE's SRB0 DL messages in a given slot. +class ue_fallback_scheduler +{ +public: + explicit ue_fallback_scheduler(const scheduler_ue_expert_config& expert_cfg_, + const cell_configuration& cell_cfg_, + pdcch_resource_allocator& pdcch_sch_, + pucch_allocator& pucch_alloc_, + ue_repository& ues_); + + /// Handles DL buffer state reported by upper layers. + /// \param[in] ue_index UE's DU Index for which SRB0 message needs to be scheduled. + void handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0); + + /// Schedule UE's SRB0 DL grants for a given slot and one or more cells. + /// \param[in] res_alloc Resource Grid of the cell where the DL grant is going to be allocated. + void run_slot(cell_resource_allocator& res_alloc); + +private: + /// Erase the UEs' HARQ processes that have been acked from the SRB scheduler cache. + void update_ongoing_ue_retxs(); + + // Holds the most recent slot with PDSCH for SRB0/SRB1 and the most recent slot with the corresponding PUCCH. + struct most_recent_tx_slots { + slot_point most_recent_tx_slot; + slot_point most_recent_ack_slot; + }; + + /// \brief Tries to schedule SRB0 message for a UE. Returns true if successful, false otherwise. + bool schedule_srb(cell_resource_allocator& res_alloc, + ue& u, + bool is_srb0, + dl_harq_process* h_dl_retx, + optional most_recent_tx_ack_slots); + + /// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space. + dl_harq_process* schedule_srb0(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + slot_point most_recent_ack_slot, + dl_harq_process* h_dl_retx); + + /// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space. + dl_harq_process* schedule_srb1(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + slot_point most_recent_ack_slot, + dl_harq_process* h_dl_retx = nullptr); + + void fill_srb_grant(ue& u, + slot_point pdsch_slot, + dl_harq_process& h_dl, + pdcch_dl_information& pdcch, + dci_dl_rnti_config_type dci_type, + dl_msg_alloc& msg, + unsigned pucch_res_indicator, + unsigned pdsch_time_res, + unsigned k1, + sch_mcs_index mcs_idx, + const crb_interval& ue_grant_crbs, + const pdsch_config_params& pdsch_params, + unsigned tbs_bytes, + bool is_retx, + bool is_srb0); + + const pdsch_time_domain_resource_allocation& get_pdsch_td_cfg(unsigned pdsch_time_res_idx) const; + + struct srb_ue { + du_ue_index_t ue_index; + bool is_srb0; + }; + + /// List of UE's DU Indexes for which SRB0 and SRB1 messages needs to be scheduled. + std::vector pending_ues; + + /// Class that keeps track of the UEs' that are waiting for the SRB HARQ processes to be ACKed or retransmitted. + class ack_and_retx_tracker + { + public: + explicit ack_and_retx_tracker(du_ue_index_t ue_idx, dl_harq_process* h_dl_, bool is_srb0_, ue_repository& ues_) : + ue_index(ue_idx), is_srb0(is_srb0_), h_dl(h_dl_) + { + } + explicit ack_and_retx_tracker(const ack_and_retx_tracker& other) = default; + + bool match_ue_harq(du_ue_index_t ue_idx_, dl_harq_process* h_dl_) const + { + return ue_index == ue_idx_ and h_dl == h_dl_; + } + + du_ue_index_t ue_index; + bool is_srb0; + dl_harq_process* h_dl; + }; + + void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); + + // If there are any pending SRB0 or SRB1 transmissions for the UE, the function returns the most recent slot with + // PDSCH for SRB0/SRB1 and the most recent slot with the corresponding PUCCH. + optional get_most_recent_slot_tx(du_ue_index_t ue_idx) const; + + const scheduler_ue_expert_config& expert_cfg; + const cell_configuration& cell_cfg; + // TODO: Find proper values for these 2 parameters. + // Set the max number of slots the scheduler can look ahead in the resource grid (with respect to the current slot) to + // find PDSCH space for SRB0 or SRB1. + const unsigned max_dl_slots_ahead_sched = 10U; + // Set the max number of attempts the scheduler can do while running through the nested loops over the PDSCH time + // allocation indices and the ahead slots for all UEs. This is to avoid excessive long iterations in case many UEs. + // NOTE: max_sched_attempts = (max_dl_slots_ahead_sched + 1) * max_pdsch_time_res guarantees that at 1 UE will be + // allocated in a TDD period of 10 slots. + const unsigned max_sched_attempts = 22U; + // Counter for the scheduling attempts per function call. + unsigned sched_attempts_cnt = 0; + pdcch_resource_allocator& pdcch_sch; + pucch_allocator& pucch_alloc; + ue_repository& ues; + + bwp_configuration initial_active_dl_bwp; + // See 3GPP TS 38.213, clause 10.1, + // A UE monitors PDCCH candidates in one or more of the following search spaces sets + // - a Type1-PDCCH CSS set configured by ra-SearchSpace in PDCCH-ConfigCommon for a DCI format with + // CRC scrambled by a RA-RNTI, a MsgB-RNTI, or a TC-RNTI on the primary cell. + search_space_configuration ss_cfg; + coreset_configuration cs_cfg; + + /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. + std::vector ongoing_ues_ack_retxs; + + std::vector dci_1_0_k1_values; + + srslog::basic_logger& logger; +}; + +} // namespace srsran diff --git a/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h index 11cad32776..a69ead088c 100644 --- a/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h +++ b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h @@ -149,7 +149,7 @@ class ue_pdsch_param_candidate_searcher // Create list of DL HARQ processes with pending retx, sorted from oldest to newest. for (unsigned i = 0; i != ue_cc.harqs.nof_dl_harqs(); ++i) { const dl_harq_process& h = ue_cc.harqs.dl_harq(i); - if (h.has_pending_retx()) { + if (h.has_pending_retx() and (not h.last_alloc_params().is_fallback)) { dl_harq_candidates.push_back(&h); } } diff --git a/lib/scheduler/ue_scheduling/ue_repository.cpp b/lib/scheduler/ue_scheduling/ue_repository.cpp index b8fb365a57..03c70ec752 100644 --- a/lib/scheduler/ue_scheduling/ue_repository.cpp +++ b/lib/scheduler/ue_scheduling/ue_repository.cpp @@ -21,6 +21,7 @@ */ #include "ue_repository.h" +#include "../cell/resource_grid_util.h" using namespace srsran; @@ -65,15 +66,23 @@ static auto search_rnti(const std::vector>& rnt void ue_repository::slot_indication(slot_point sl_tx) { - for (ue_config_delete_event& p : ues_to_rem) { - if (not p.valid()) { + last_sl_tx = sl_tx; + + for (std::pair& p : ues_to_rem) { + auto& rem_ev = p.second; + if (not rem_ev.valid()) { // Already removed. continue; } - const du_ue_index_t ue_idx = p.ue_index(); + if (p.first > sl_tx) { + // UE is not yet ready to be removed as there may be still pending allocations for it in the resource grid. + continue; + } + + const du_ue_index_t ue_idx = rem_ev.ue_index(); if (not ues.contains(ue_idx)) { logger.error("ue={}: Unexpected UE removal from UE repository", ue_idx); - p.reset(); + rem_ev.reset(); continue; } ue& u = *ues[ue_idx]; @@ -96,13 +105,13 @@ void ue_repository::slot_indication(slot_point sl_tx) ues.erase(ue_idx); // Marks UE config removal as complete. - p.reset(); + rem_ev.reset(); logger.debug("ue={} rnti={}: UE has been successfully removed.", ue_idx, crnti); } // In case the elements at the front of the ring has been marked for removal, pop them from the queue. - while (not ues_to_rem.empty() and not ues_to_rem[0].valid()) { + while (not ues_to_rem.empty() and not ues_to_rem[0].second.valid()) { ues_to_rem.pop(); } @@ -128,10 +137,16 @@ void ue_repository::schedule_ue_rem(ue_config_delete_event ev) { if (contains(ev.ue_index())) { // Start deactivation of UE bearers. - ues[ev.ue_index()]->deactivate(); + auto& u = ues[ev.ue_index()]; + u->deactivate(); // Register UE for later removal. - ues_to_rem.push(std::move(ev)); + // We define a time window when the UE removal is not allowed, as there are pending CSI/SR PDUs in the resource grid + // ready to be sent to the PHY. Removing the UE earlier would mean that its PUCCH resources would become available + // to a newly created UE and there could be a PUCCH collision. + slot_point rem_slot = + last_sl_tx + get_max_slot_ul_alloc_delay(u->get_pcell().cfg().cell_cfg_common.ntn_cs_koffset) + 1; + ues_to_rem.push(std::make_pair(rem_slot, std::move(ev))); } } diff --git a/lib/scheduler/ue_scheduling/ue_repository.h b/lib/scheduler/ue_scheduling/ue_repository.h index b227010499..d93d8096ec 100644 --- a/lib/scheduler/ue_scheduling/ue_repository.h +++ b/lib/scheduler/ue_scheduling/ue_repository.h @@ -83,8 +83,12 @@ class ue_repository // Mapping of RNTIs to UE indexes. std::vector> rnti_to_ue_index_lookup; - // Queue of UEs marked for later removal. - ring_buffer ues_to_rem{MAX_NOF_DU_UES}; + // Queue of UEs marked for later removal. For each UE, we store the slot after which its removal can be safely + // carried out, and the original UE removal command. + ring_buffer> ues_to_rem{MAX_NOF_DU_UES}; + + // Last slot indication. + slot_point last_sl_tx; }; } // namespace srsran diff --git a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp index 911d130608..c4221a8c6a 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp @@ -42,7 +42,8 @@ void ue_scheduler_impl::add_cell(const ue_scheduler_cell_params& params) { ue_res_grid_view.add_cell(*params.cell_res_alloc); cells[params.cell_index] = std::make_unique(expert_cfg, params, ue_db); - event_mng.add_cell(*params.cell_res_alloc, cells[params.cell_index]->srb0_sched, cells[params.cell_index]->uci_sched); + event_mng.add_cell( + *params.cell_res_alloc, cells[params.cell_index]->fallback_sched, cells[params.cell_index]->uci_sched); ue_alloc.add_cell(params.cell_index, *params.pdcch_sched, *params.uci_alloc, *params.cell_res_alloc); } @@ -167,7 +168,7 @@ void ue_scheduler_impl::run_slot(slot_point slot_tx, du_cell_index_t cell_index) cells[cell_index]->uci_sched.run_slot(*cells[cell_index]->cell_res_alloc); // Run cell-specific SRB0 scheduler. - cells[cell_index]->srb0_sched.run_slot(*cells[cell_index]->cell_res_alloc); + cells[cell_index]->fallback_sched.run_slot(*cells[cell_index]->cell_res_alloc); // Synchronize all carriers. Last thread to reach this synchronization point, runs UE scheduling strategy. sync_point.wait( diff --git a/lib/scheduler/ue_scheduling/ue_scheduler_impl.h b/lib/scheduler/ue_scheduling/ue_scheduler_impl.h index 7217a32fe5..c451d1b00d 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.h +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.h @@ -30,9 +30,9 @@ #include "../uci_scheduling/uci_scheduler_impl.h" #include "ue_cell_grid_allocator.h" #include "ue_event_manager.h" +#include "ue_fallback_scheduler.h" #include "ue_repository.h" #include "ue_scheduler.h" -#include "ue_srb0_scheduler.h" #include "srsran/adt/slotted_array.h" #include "srsran/adt/unique_function.h" #include "srsran/scheduler/config/scheduler_expert_config.h" @@ -80,13 +80,13 @@ class ue_scheduler_impl final : public ue_scheduler /// PUCCH scheduler. uci_scheduler_impl uci_sched; - /// SRB0 scheduler. - ue_srb0_scheduler srb0_sched; + /// Fallback scheduler. + ue_fallback_scheduler fallback_sched; cell(const scheduler_ue_expert_config& expert_cfg, const ue_scheduler_cell_params& params, ue_repository& ues) : cell_res_alloc(params.cell_res_alloc), uci_sched(params.cell_res_alloc->cfg, *params.uci_alloc, ues), - srb0_sched(expert_cfg, params.cell_res_alloc->cfg, *params.pdcch_sched, *params.pucch_alloc, ues) + fallback_sched(expert_cfg, params.cell_res_alloc->cfg, *params.pdcch_sched, *params.pucch_alloc, ues) { } }; diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp deleted file mode 100644 index f0fa5bf288..0000000000 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * Copyright 2021-2024 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "ue_srb0_scheduler.h" -#include "../support/dci_builder.h" -#include "../support/dmrs_helpers.h" -#include "../support/pdsch/pdsch_resource_allocation.h" -#include "../support/prbs_calculator.h" -#include "srsran/ran/sch/tbs_calculator.h" - -using namespace srsran; - -ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cfg_, - const cell_configuration& cell_cfg_, - pdcch_resource_allocator& pdcch_sch_, - pucch_allocator& pucch_alloc_, - ue_repository& ues_) : - expert_cfg(expert_cfg_), - cell_cfg(cell_cfg_), - pdcch_sch(pdcch_sch_), - pucch_alloc(pucch_alloc_), - ues(ues_), - initial_active_dl_bwp(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params), - ss_cfg(cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common - .search_spaces[cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common.ra_search_space_id]), - cs_cfg(cell_cfg.get_common_coreset(ss_cfg.get_coreset_id())), - logger(srslog::fetch_basic_logger("SCHED")) -{ -} - -void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) -{ - if (ues.empty()) { - return; - } - - const cell_slot_resource_allocator& pdcch_alloc = res_alloc[0]; - if (not cell_cfg.is_dl_enabled(pdcch_alloc.slot)) { - return; - } - // Note: Unable at the moment to multiplex CSI and PDSCH. - if (not res_alloc[0].result.dl.csi_rs.empty()) { - return; - } - - // Schedule SRB0 messages. - auto it = pending_ues.begin(); - while (it != pending_ues.end()) { - // Check if UE exists. - if (not ues.contains(*it)) { - it = pending_ues.erase(it); - continue; - } - - auto& u = ues[*it]; - if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb0(res_alloc, u)) { - it = pending_ues.erase(it); - } else { - ++it; - } - } -} - -void ue_srb0_scheduler::handle_dl_buffer_state_indication(du_ue_index_t ue_index) -{ - pending_ues.push_back(ue_index); -} - -bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u) -{ - const auto& bwp_cfg_common = cell_cfg.dl_cfg_common.init_dl_bwp; - // Search valid PDSCH time domain resource. - for (unsigned time_res_idx = 0; time_res_idx != bwp_cfg_common.pdsch_common.pdsch_td_alloc_list.size(); - ++time_res_idx) { - const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(time_res_idx); - - // Fetch PDSCH resource grid allocators. - const cell_slot_resource_allocator& pdsch_alloc = res_alloc[pdsch_td_cfg.k0]; - - if (not cell_cfg.is_dl_enabled(pdsch_alloc.slot)) { - continue; - } - - // Check whether PDSCH time domain resource does not overlap with CORESET. - if (pdsch_td_cfg.symbols.start() < ss_cfg.get_first_symbol_index() + cs_cfg.duration) { - continue; - } - - // Check whether PDSCH time domain resource fits in DL symbols of the slot. - if (pdsch_td_cfg.symbols.stop() > cell_cfg.get_nof_dl_symbol_per_slot(pdsch_alloc.slot)) { - continue; - } - - if (schedule_srb0(u, res_alloc, time_res_idx)) { - return true; - } - } - - // No resource found in UE's carriers and Search spaces. - logger.debug("rnti={}: Not enough PDSCH space for SRB0 message. Will re-try in next slot.", u.crnti); - return false; -} - -bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, unsigned pdsch_time_res) -{ - ue_cell& ue_pcell = u.get_pcell(); - const subcarrier_spacing scs = cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs; - const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(pdsch_time_res); - - // Fetch PDCCH and PDSCH resource grid allocators. - cell_slot_resource_allocator& pdcch_alloc = res_alloc[0]; - cell_slot_resource_allocator& pdsch_alloc = res_alloc[pdsch_td_cfg.k0]; - - // Verify there is space in PDSCH and PDCCH result lists for new allocations. - if (pdsch_alloc.result.dl.ue_grants.full() or pdcch_alloc.result.dl.dl_pdcchs.full()) { - logger.debug("rnti={}: Failed to allocate PDSCH for SRB0. Cause: No space available in scheduler output list.", - u.crnti); - return false; - } - - // Search for empty HARQ. - dl_harq_process* h_dl = ue_pcell.harqs.find_empty_dl_harq(); - if (h_dl == nullptr) { - logger.warning("rnti={}: UE must have empty HARQs during SRB0 PDU allocation", u.crnti); - return false; - } - - // Find available symbol x RB resources. - const unsigned pending_bytes = u.pending_dl_srb0_newtx_bytes(); - - pdsch_config_params pdsch_cfg = get_pdsch_config_f1_0_tc_rnti(cell_cfg, pdsch_td_cfg); - - prb_bitmap used_crbs = pdsch_alloc.dl_res_grid.used_crbs( - initial_active_dl_bwp.scs, - pdsch_helper::get_ra_crb_limits_common(cell_cfg.dl_cfg_common.init_dl_bwp, ss_cfg.get_id()), - pdsch_cfg.symbols); - const unsigned starting_crb_idx = 0; - crb_interval unused_crbs = rb_helper::find_next_empty_interval(used_crbs, starting_crb_idx, used_crbs.size()); - // Try to find least MCS to fit SRB0 message. - // See 38.214, table 5.1.3.1-1: MCS index table 1 for PDSCH. - sch_mcs_index mcs_idx = 0; - // Assumption. - // TODO: As per Section 5.1.3.2, TS 38.214, need to derive xOverhead from PDSCH-ServingCellconfig. - // Assumed to be not configured hence set to 0 as per spec. - sch_prbs_tbs prbs_tbs{}; - while (mcs_idx <= expert_cfg.max_msg4_mcs) { - // See 38.214, clause 5.1.3.1 - the UE shall use I_MCS and Table 5.1.3.1-1 to determine the modulation order (Qm) - // and Target code rate (R) used in the physical downlink shared channel. - const sch_mcs_description mcs_config = pdsch_mcs_get_config(pdsch_mcs_table::qam64, mcs_idx); - prbs_tbs = get_nof_prbs(prbs_calculator_sch_config{pending_bytes, - static_cast(pdsch_cfg.symbols.length()), - calculate_nof_dmrs_per_rb(pdsch_cfg.dmrs), - pdsch_cfg.nof_oh_prb, - mcs_config, - pdsch_cfg.nof_layers}); - if (unused_crbs.length() >= prbs_tbs.nof_prbs) { - break; - } - ++mcs_idx; - } - - if (prbs_tbs.tbs_bytes < pending_bytes) { - logger.debug( - "rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({}).", pending_bytes, prbs_tbs.tbs_bytes, u.crnti); - return false; - } - - if (mcs_idx > expert_cfg.max_msg4_mcs) { - logger.debug("rnti={}: MCS index chosen ({}) for SRB0 exceeds maximum allowed MCS index ({}).", - u.crnti, - mcs_idx, - expert_cfg.max_msg4_mcs); - return false; - } - - crb_interval ue_grant_crbs = rb_helper::find_empty_interval_of_length(used_crbs, prbs_tbs.nof_prbs, 0); - if (ue_grant_crbs.length() < prbs_tbs.nof_prbs) { - logger.debug("rnti={}: Postponed SRB0 PDU scheduling. Cause: Not enough PRBs ({} < {})", - u.crnti, - ue_grant_crbs.length(), - prbs_tbs.nof_prbs); - return false; - } - - // Allocate PDCCH resources. - pdcch_dl_information* pdcch = - pdcch_sch.alloc_dl_pdcch_common(pdcch_alloc, u.crnti, ss_cfg.get_id(), aggregation_level::n4); - if (pdcch == nullptr) { - logger.debug("rnti={}: Postponed SRB0 PDU scheduling. Cause: No space in PDCCH.", u.crnti); - return false; - } - - // Allocate PUCCH resources. - unsigned k1 = 4; - // Minimum k1 value supported is 4. - static const std::array dci_1_0_k1_values = {4, 5, 6, 7, 8}; - optional pucch_res_indicator; - for (const auto k1_candidate : dci_1_0_k1_values) { - pucch_res_indicator = - pucch_alloc.alloc_common_pucch_harq_ack_ue(res_alloc, u.crnti, pdsch_td_cfg.k0, k1_candidate, *pdcch); - if (pucch_res_indicator.has_value()) { - k1 = k1_candidate; - break; - } - } - if (not pucch_res_indicator.has_value()) { - logger.debug("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH."); - pdcch_sch.cancel_last_pdcch(pdcch_alloc); - return false; - } - - // Mark resources as occupied in the ResourceGrid. - pdsch_alloc.dl_res_grid.fill(grant_info{scs, pdsch_td_cfg.symbols, ue_grant_crbs}); - - fill_srb0_grant(u, - pdsch_alloc.slot, - *h_dl, - *pdcch, - pdsch_alloc.result.dl.ue_grants.emplace_back(), - pucch_res_indicator.value(), - pdsch_time_res, - k1, - mcs_idx, - ue_grant_crbs, - pdsch_cfg, - prbs_tbs.tbs_bytes); - - return true; -} - -void ue_srb0_scheduler::fill_srb0_grant(ue& u, - slot_point pdsch_slot, - dl_harq_process& h_dl, - pdcch_dl_information& pdcch, - dl_msg_alloc& msg, - unsigned pucch_res_indicator, - unsigned pdsch_time_res, - unsigned k1, - sch_mcs_index mcs_idx, - const crb_interval& ue_grant_crbs, - const pdsch_config_params& pdsch_params, - unsigned tbs_bytes) -{ - static constexpr uint8_t srb0_dai = 0; - // Allocate DL HARQ. - h_dl.new_tx(pdsch_slot, - k1, - expert_cfg.max_nof_harq_retxs, - srb0_dai, - u.get_pcell().channel_state_manager().get_wideband_cqi(), - u.get_pcell().channel_state_manager().get_nof_dl_layers()); - - // Fill DL PDCCH DCI. - static const uint8_t msg4_rv = 0; - build_dci_f1_0_tc_rnti(pdcch.dci, - cell_cfg.dl_cfg_common.init_dl_bwp, - ue_grant_crbs, - pdsch_time_res, - k1, - pucch_res_indicator, - mcs_idx, - msg4_rv, - h_dl); - - // Fill PDSCH PDU. - msg.context.ue_index = u.ue_index; - msg.context.k1 = k1; - msg.context.ss_id = pdcch.ctx.context.ss_id; - msg.context.nof_retxs = h_dl.tb(0).nof_retxs; - msg.context.olla_offset = 0; - build_pdsch_f1_0_tc_rnti( - msg.pdsch_cfg, pdsch_params, tbs_bytes, u.crnti, cell_cfg, pdcch.dci.tc_rnti_f1_0, ue_grant_crbs, true); - - // Set MAC logical channels to schedule in this PDU. - u.build_dl_srb0_transport_block_info(msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes); - - // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. - h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); -} - -const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg(unsigned pdsch_time_res_idx) const -{ - return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; -} diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h deleted file mode 100644 index bdd41e64a8..0000000000 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright 2021-2024 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#include "../policy/ue_allocator.h" -#include "../support/sch_pdu_builder.h" -#include "../support/slot_event_list.h" -#include "ue_repository.h" -#include "srsran/scheduler/scheduler_configurator.h" -#include - -namespace srsran { - -/// Defines SRB0 scheduler that is used to allocate grants for UE's SRB0 DL messages in a given slot. -class ue_srb0_scheduler -{ -public: - explicit ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cfg_, - const cell_configuration& cell_cfg_, - pdcch_resource_allocator& pdcch_sch_, - pucch_allocator& pucch_alloc_, - ue_repository& ues_); - - /// Handles DL buffer state reported by upper layers. - /// \param[in] ue_index UE's DU Index for which SRB0 message needs to be scheduled. - void handle_dl_buffer_state_indication(du_ue_index_t ue_index); - - /// Schedule UE's SRB0 DL grants for a given slot and one or more cells. - /// \param[in] res_alloc Resource Grid of the cell where the DL grant is going to be allocated. - void run_slot(cell_resource_allocator& res_alloc); - -private: - /// \brief Tries to schedule SRB0 message for a UE. Returns true if successful, false otherwise. - bool schedule_srb0(cell_resource_allocator& res_alloc, ue& u); - - /// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space. - bool schedule_srb0(ue& u, cell_resource_allocator& res_alloc, unsigned pdsch_time_res); - - void fill_srb0_grant(ue& u, - slot_point pdsch_slot, - dl_harq_process& h_dl, - pdcch_dl_information& pdcch, - dl_msg_alloc& msg, - unsigned pucch_res_indicator, - unsigned pdsch_time_res, - unsigned k1, - sch_mcs_index mcs_idx, - const crb_interval& ue_grant_crbs, - const pdsch_config_params& pdsch_params, - unsigned tbs_bytes); - - const pdsch_time_domain_resource_allocation& get_pdsch_td_cfg(unsigned pdsch_time_res_idx) const; - - const scheduler_ue_expert_config& expert_cfg; - const cell_configuration& cell_cfg; - pdcch_resource_allocator& pdcch_sch; - pucch_allocator& pucch_alloc; - ue_repository& ues; - - bwp_configuration initial_active_dl_bwp; - // See 3GPP TS 38.213, clause 10.1, - // A UE monitors PDCCH candidates in one or more of the following search spaces sets - // - a Type1-PDCCH CSS set configured by ra-SearchSpace in PDCCH-ConfigCommon for a DCI format with - // CRC scrambled by a RA-RNTI, a MsgB-RNTI, or a TC-RNTI on the primary cell. - search_space_configuration ss_cfg; - coreset_configuration cs_cfg; - - /// List of UE's DU Indexes for which SRB0 messages needs to be scheduled. - std::vector pending_ues; - - srslog::basic_logger& logger; -}; - -} // namespace srsran diff --git a/lib/srsvec/CMakeLists.txt b/lib/srsvec/CMakeLists.txt index f6f74fc5e8..eb8d7021bc 100644 --- a/lib/srsvec/CMakeLists.txt +++ b/lib/srsvec/CMakeLists.txt @@ -33,10 +33,11 @@ set(SOURCES prod.cpp sc_prod.cpp subtract.cpp + unwrap.cpp ) add_library(srsvec STATIC ${SOURCES}) target_link_libraries(srsvec srslog) install(TARGETS srsvec - EXPORT srsran_export) \ No newline at end of file + EXPORT srsran_export) diff --git a/lib/srsvec/unwrap.cpp b/lib/srsvec/unwrap.cpp new file mode 100644 index 0000000000..adad8b315c --- /dev/null +++ b/lib/srsvec/unwrap.cpp @@ -0,0 +1,73 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/// \file +/// \brief Phase angle unwrapping definitions. + +#include "srsran/srsvec/unwrap.h" +#include +#include + +using namespace srsran; + +/// \brif Unwraps a list of floats. +/// +/// The inputs are assumed to take values in the range \f$[-\alpha, \alpha)\f$. Whenever the jump between two +/// consecutive values is larger than \f$\alpha\f$, the second value is shifted by \f$\pm 2 \alpha\f$, depending on the +/// sign of the jump. The typical application is the unwrapping of phase angles with \f$\alpha = \pi\f$. +/// +/// \param[in,out] list Input and output list of numbers. +/// \param[in] tol The tolerance \f$\alpha\f$. +/// +/// \warning The list of numbers is modified in-place. +static void unwrap_list(span list, float tol = static_cast(M_PI)) +{ + float width = std::abs(tol); + float k = 0; + + auto* a_last = std::prev(list.end()); + for (auto* a = list.begin(); a != a_last; ++a) { + float old_a = *a; + float next_a = *std::next(a); + + *a += 2.0F * k * width; + + float jump = next_a - old_a; + if (std::abs(jump) > width) { + k = k - std::copysign(1.0F, jump); + } + } + + *a_last += 2.0F * k * width; +} + +void srsvec::unwrap_arguments(span arguments, span cplx_numbers) +{ + srsran_assert(arguments.size() == cplx_numbers.size(), + "Input and output lists should have the same length, given {} and {}.", + arguments.size(), + cplx_numbers.size()); + + std::transform(cplx_numbers.begin(), cplx_numbers.end(), arguments.begin(), [](cf_t a) { return std::arg(a); }); + + unwrap_list(arguments); +} diff --git a/lib/support/bit_encoding.cpp b/lib/support/bit_encoding.cpp index 563393e8bb..f621216c4c 100644 --- a/lib/support/bit_encoding.cpp +++ b/lib/support/bit_encoding.cpp @@ -161,7 +161,7 @@ bool bit_decoder::unpack_bytes(srsran::span bytes) } if (offset == 0) { // Aligned case - std::copy(buffer.begin(), buffer.end(), bytes.begin()); + std::copy(it, it + bytes.size(), bytes.begin()); it += bytes.size(); } else { // Unaligned case diff --git a/lib/support/byte_buffer_chain.cpp b/lib/support/byte_buffer_chain.cpp index 91e5f7a24f..0a465566b4 100644 --- a/lib/support/byte_buffer_chain.cpp +++ b/lib/support/byte_buffer_chain.cpp @@ -26,19 +26,26 @@ using namespace srsran; -byte_buffer_chain::byte_buffer_chain() : - // Allocate memory block from pool for the array of slices. - mem_block(detail::get_default_byte_buffer_segment_pool().allocate_node()), +byte_buffer_chain::byte_buffer_chain(void* mem) : + mem_block(mem), // Number of slices that fit in the memory block. - max_slices(detail::get_default_byte_buffer_segment_pool().memory_block_size() / sizeof(buffer_storage_type)) + max_slices(detail::get_default_byte_buffer_segment_pool().memory_block_size() / sizeof(buffer_storage_type)), + // Initialize slice array in the allocated memory block. + slices_ptr(static_cast(align_next(mem_block.get(), alignof(buffer_storage_type)))) { + srsran_assert(mem, "Invalid memory block"); +} + +expected byte_buffer_chain::create() +{ + // Allocate memory block from pool for the array of slices. + auto* mem_block = detail::get_default_byte_buffer_segment_pool().allocate_node(); if (mem_block == nullptr) { srslog::fetch_basic_logger("ALL").warning("POOL: Failed to allocate memory block for byte_buffer_chain"); - return; + return default_error_t{}; } - // Initialize slice array in the allocated memory block. - slices_ptr = static_cast(align_next(mem_block.get(), alignof(buffer_storage_type))); + return {mem_block}; } void byte_buffer_chain::block_deleter::operator()(void* p) diff --git a/lib/support/cpu_architecture_info.cpp b/lib/support/cpu_architecture_info.cpp index 4aaa8a29a8..ce1982dabe 100644 --- a/lib/support/cpu_architecture_info.cpp +++ b/lib/support/cpu_architecture_info.cpp @@ -116,9 +116,23 @@ cpu_architecture_info::cpu_description cpu_architecture_info::discover_cpu_archi // Parse /sys/devices/system/cpu/cpu*/topology/thread_siblings_list to get the lists of logical cores belonging to // the same physical core. - std::set thread_siblings_set; - std::string cpu_system_path = "/sys/devices/system/cpu"; - ::DIR* dir = ::opendir(cpu_system_path.c_str()); + auto sort_function = [](std::string a, std::string b) { + auto get_first_cpu = [](const std::string& line) { + std::string str; + std::istringstream iss(line); + std::getline(iss, str, ','); + if (str.find('-') != std::string::npos) { + std::getline(iss, str, '-'); + } + return parse_one_cpu(str); + }; + unsigned cpu_id_a = get_first_cpu(a); + unsigned cpu_id_b = get_first_cpu(b); + return cpu_id_a < cpu_id_b; + }; + std::set thread_siblings_set(sort_function); + std::string cpu_system_path = "/sys/devices/system/cpu"; + ::DIR* dir = ::opendir(cpu_system_path.c_str()); if (dir) { ::dirent* entry; struct ::stat info; @@ -143,7 +157,7 @@ cpu_architecture_info::cpu_description cpu_architecture_info::discover_cpu_archi for (const auto& mask : thread_siblings_set) { cpuinfo.logical_cpu_lists.emplace_back(); auto& bitmask = cpuinfo.logical_cpu_lists.back(); - bitmask.resize(cpuinfo.nof_cpus); + bitmask.resize(CPU_SETSIZE); std::istringstream iss(mask); while (iss.good()) { diff --git a/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 11e38ed559..dd3646b79a 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -699,8 +699,11 @@ class du_high_bench mac_rx_data_indication rx_ind; rx_ind.sl_rx = next_sl_tx - tx_rx_delay; rx_ind.cell_index = to_du_cell_index(0); - rx_ind.pdus.push_back(mac_rx_pdu{ - du_ue_index_to_rnti(ue_idx), 0, 0, {0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}}); + rx_ind.pdus.push_back( + mac_rx_pdu{du_ue_index_to_rnti(ue_idx), + 0, + 0, + byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}).value()}); du_hi->get_pdu_handler().handle_rx_data_indication(std::move(rx_ind)); // Wait for UE Context Modification Response to arrive to CU. @@ -740,19 +743,19 @@ class du_high_bench pdcp_sn_list[bearer_idx] = (pdcp_sn_list[bearer_idx] + 1) % (1U << 18U); // We perform a deep-copy of the byte buffer to better simulate a real deployment, where there is stress over // the byte buffer pool. - byte_buffer pdu_copy = pdcp_pdu.deep_copy(); - if (pdu_copy.empty()) { + auto pdu_copy = pdcp_pdu.deep_copy(); + if (pdu_copy.is_error()) { test_logger.warning("Byte buffer segment pool depleted"); return; } if (i == nof_dl_pdus_per_slot - 1 and last_dl_pdu_size != 0) { // If it is last DL PDU. - if (!pdu_copy.resize(last_dl_pdu_size)) { + if (!pdu_copy.value().resize(last_dl_pdu_size)) { test_logger.warning("Unable to resize PDU to {} bytes", last_dl_pdu_size); return; } } - du_notif->on_new_sdu(pdcp_tx_pdu{.buf = std::move(pdu_copy), .pdcp_sn = pdcp_sn_list[bearer_idx]}); + du_notif->on_new_sdu(pdcp_tx_pdu{.buf = std::move(pdu_copy.value()), .pdcp_sn = pdcp_sn_list[bearer_idx]}); } } })) { @@ -1002,7 +1005,7 @@ class du_high_bench // Construct LBSR MAC subPDU for LCG 1. // NOTE: LBSR buffer size is populated in the constructor. - byte_buffer bsr_mac_subpdu{0x3e, 0x02, 0x02}; + byte_buffer bsr_mac_subpdu = byte_buffer::create({0x3e, 0x02, 0x02}).value(); /// Size of the UL Buffer status report to push for UL Tx. unsigned ul_bsr_bytes; diff --git a/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp b/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp index 6bf4b9c4aa..7a9b600535 100644 --- a/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp +++ b/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp @@ -28,11 +28,13 @@ using namespace srsran; -const std::array k_128_int = +static constexpr std::array k_128_int = {0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31}; -const std::array k_128_enc = +static constexpr std::array k_128_enc = {0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31}; +namespace { + /// Mocking class of the surrounding layers invoked by the PDCP. class pdcp_tx_gen_frame : public pdcp_tx_lower_notifier, public pdcp_tx_upper_control_notifier { @@ -42,12 +44,8 @@ class pdcp_tx_gen_frame : public pdcp_tx_lower_notifier, public pdcp_tx_upper_co void on_protocol_failure() final {} /// PDCP TX lower layer data notifier - void on_new_pdu(pdcp_tx_pdu pdu) final - { - byte_buffer_chain buf{std::move(pdu.buf)}; - pdu_list.push_back(std::move(buf)); - } - void on_discard_pdu(uint32_t pdcp_sn) final {} + void on_new_pdu(pdcp_tx_pdu pdu) final { pdu_list.push_back(byte_buffer_chain::create(std::move(pdu.buf)).value()); } + void on_discard_pdu(uint32_t pdcp_sn) final {} std::vector pdu_list; }; @@ -80,6 +78,8 @@ struct app_params { std::string log_filename = "stdout"; }; +} // namespace + static void usage(const char* prog, const bench_params& params, const app_params& app) { fmt::print("Usage: {} [-R repetitions] [-s silent]\n", prog); diff --git a/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp index 505a9d9a9d..2c9c8f643c 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp @@ -639,7 +639,7 @@ static pdsch_processor_factory& get_processor_factory() TESTASSERT(pdsch_proc_factory); // Create PDSCH processor pool. - pdsch_proc_factory = create_pdsch_processor_pool(std::move(pdsch_proc_factory), nof_threads); + pdsch_proc_factory = create_pdsch_processor_pool(std::move(pdsch_proc_factory), nof_threads, true); TESTASSERT(pdsch_proc_factory); return *pdsch_proc_factory; diff --git a/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp index c6b5e6ab2a..268c8f09d3 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp @@ -41,9 +41,7 @@ #include "srsran/hal/phy/upper/channel_processors/pusch/hw_accelerator_factories.h" #include "srsran/hal/phy/upper/channel_processors/pusch/hw_accelerator_pusch_dec_factory.h" #endif // HWACC_PUSCH_ENABLED -#include #include -#include #include using namespace srsran; @@ -136,12 +134,9 @@ static std::unique_ptr> static std::unique_ptr> executor = nullptr; // Thread shared variables. -static std::mutex mutex_pending_count; -static std::mutex mutex_finish_count; -static std::condition_variable cvar_count; -static std::atomic thread_quit = {}; -static unsigned pending_count = 0; -static unsigned finish_count = 0; +static std::atomic thread_quit = {}; +static std::atomic pending_count = {0}; +static std::atomic finish_count = {0}; #ifdef HWACC_PUSCH_ENABLED static bool ext_softbuffer = true; @@ -162,7 +157,7 @@ struct test_profile { {modulation_scheme::QAM16, 658.0F}, {modulation_scheme::QAM64, 873.0F}, {modulation_scheme::QAM256, 948.0F}}; - std::vector rv_set = {0, 2}; + std::vector rv_set = {0}; }; // Profile selected during test execution. @@ -576,9 +571,13 @@ static pusch_processor_factory& get_pusch_processor_factory() } TESTASSERT(dft_factory, "Cannot create DFT factory."); + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + TESTASSERT(ta_estimator_factory, "Cannot create TA estimator factory."); + // Create port channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); TESTASSERT(port_chan_estimator_factory); // Create DM-RS for PUSCH channel estimator. @@ -637,7 +636,7 @@ static pusch_processor_factory& get_pusch_processor_factory() pusch_proc_factory = create_pusch_processor_factory_sw(pusch_proc_factory_config); TESTASSERT(pusch_proc_factory); - pusch_proc_factory = create_pusch_processor_pool(std::move(pusch_proc_factory), nof_threads); + pusch_proc_factory = create_pusch_processor_pool(std::move(pusch_proc_factory), nof_threads, true); TESTASSERT(pusch_proc_factory); return *pusch_proc_factory; @@ -664,8 +663,6 @@ static void thread_process(pusch_processor& proc, unsigned tbs, const resource_grid_reader& grid) { - pusch_processor_result_notifier_adaptor result_notifier; - // Compute the number of codeblocks. unsigned nof_codeblocks = ldpc::compute_nof_codeblocks(units::bits(tbs), config.codeword.value().ldpc_base_graph); @@ -686,34 +683,27 @@ static void thread_process(pusch_processor& proc, // Prepare receive data buffer. std::vector data(tbs / 8); - // Notify finish count. - { - std::unique_lock lock(mutex_finish_count); - finish_count++; - cvar_count.notify_all(); - } - while (!thread_quit) { - // Wait for pending. - { - std::unique_lock lock(mutex_pending_count); - while (pending_count == 0) { - cvar_count.wait_until(lock, std::chrono::system_clock::now() + std::chrono::milliseconds(2)); + // If the pending count is equal to or lower than zero, wait for a new start. + while (pending_count.fetch_sub(1) <= 0) { + // Wait for pending to non-negative. + while (pending_count.load() <= 0) { + // Sleep. + std::this_thread::sleep_for(std::chrono::microseconds(10)); // Quit if signaled. if (thread_quit) { return; } } - pending_count--; } + // Prepare notifier. + pusch_processor_result_notifier_adaptor result_notifier; + // Reserve buffer. unique_rx_buffer rm_buffer = buffer_pool->get_pool().reserve(config.slot, buffer_id, nof_codeblocks, true); - // Reset notifier. - result_notifier.reset(); - // Process PDU. proc.process(data, std::move(rm_buffer), result_notifier, grid, config); @@ -721,11 +711,7 @@ static void thread_process(pusch_processor& proc, result_notifier.wait_for_completion(); // Notify finish count. - { - std::unique_lock lock(mutex_finish_count); - finish_count++; - cvar_count.notify_all(); - } + ++finish_count; } } @@ -834,8 +820,9 @@ int main(int argc, char** argv) TESTASSERT(validator->is_valid(config)); // Reset finish counter. - finish_count = 0; - thread_quit = false; + finish_count = 0; + pending_count = 0; + thread_quit = false; // Prepare threads for the current case. std::vector threads(nof_threads); @@ -850,11 +837,8 @@ int main(int argc, char** argv) } // Wait for finish thread init. - { - std::unique_lock lock(mutex_finish_count); - while (finish_count != nof_threads) { - cvar_count.wait_until(lock, std::chrono::system_clock::now() + std::chrono::milliseconds(2)); - } + while (pending_count.load() != -static_cast(nof_threads)) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); } // Calculate the peak throughput, considering that the number of bits is for a slot. @@ -872,21 +856,14 @@ int main(int argc, char** argv) peak_throughput_Mbps); // Run the benchmark. - perf_meas.new_measure(to_string(meas_description), nof_threads * batch_size_per_thread * tbs, []() { + perf_meas.new_measure(to_string(meas_description), nof_threads * batch_size_per_thread * tbs, []() mutable { // Notify start. - { - std::unique_lock lock(mutex_pending_count); - pending_count = nof_threads * batch_size_per_thread; - finish_count = 0; - cvar_count.notify_all(); - } + finish_count = 0; + pending_count = nof_threads * batch_size_per_thread; // Wait for finish. - { - std::unique_lock lock(mutex_finish_count); - while (finish_count != (nof_threads * batch_size_per_thread)) { - cvar_count.wait_until(lock, std::chrono::system_clock::now() + std::chrono::milliseconds(2)); - } + while (finish_count.load() != (nof_threads * batch_size_per_thread)) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }); diff --git a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index b14b5778d6..532e58a8a5 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -182,8 +182,10 @@ std::vector generate_pdus(bench_params params, rx_order order) int num_pdus = 0; int pdu_size = params.pdu_size; for (int i = 0; i < num_sdus; i++) { - rlc_sdu sdu; - byte_buffer pdcp_hdr_buf = {0x80, 0x00, 0x16}; + rlc_sdu sdu; + auto pdcp_hdr = byte_buffer::create({0x80, 0x00, 0x16}); + report_error_if_not(!pdcp_hdr.is_error(), "Failed to allocate byte_buffer"); + byte_buffer pdcp_hdr_buf = std::move(pdcp_hdr.value()); byte_buffer sdu_buf = std::move(sdu_list[i]); sdu.pdcp_sn = i; sdu.buf = std::move(pdcp_hdr_buf); @@ -194,7 +196,9 @@ std::vector generate_pdus(bench_params params, rx_order order) pdu_buf.resize(pdu_size); size_t pdu_len = rlc_tx->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - pdus.emplace_back(pdu_buf); + auto buf = byte_buffer::create(pdu_buf); + report_error_if_not(!buf.is_error(), "Failed to allocate byte_buffer"); + pdus.emplace_back(std::move(buf.value())); num_pdus++; } } diff --git a/tests/benchmarks/rlc/rlc_handle_status_report.cpp b/tests/benchmarks/rlc/rlc_handle_status_report.cpp index 303cc6ed85..32892e3306 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -137,12 +137,16 @@ void benchmark_status_pdu_handling(rlc_am_status_pdu status, const bench_params& rlc->set_status_provider(tester.get()); for (int i = 0; i < 2048; i++) { - rlc_sdu sdu; - byte_buffer pdcp_hdr_buf = {0x80, 0x00, 0x16}; - byte_buffer sdu_buf = {0x00, 0x01, 0x02, 0x04}; - sdu.pdcp_sn = i; - sdu.buf = std::move(pdcp_hdr_buf); - report_error_if_not(sdu.buf.append(std::move(sdu_buf)), "Failed to allocate SDU"); + rlc_sdu sdu; + auto pdcp_hdr = byte_buffer::create({0x80, 0x00, 0x16}); + report_error_if_not(!pdcp_hdr.is_error(), "Failed to allocate byte_buffer"); + byte_buffer pdcp_hdr_buf = std::move(pdcp_hdr.value()); + auto sdu_buf = byte_buffer::create({0x00, 0x01, 0x02, 0x04}); + report_error_if_not(!sdu_buf.is_error(), "Failed to allocate byte_buffer"); + byte_buffer sdu_buffer = std::move(sdu_buf.value()); + sdu.pdcp_sn = i; + sdu.buf = std::move(pdcp_hdr_buf); + report_error_if_not(sdu.buf.append(std::move(sdu_buffer)), "Failed to allocate SDU"); rlc->handle_sdu(std::move(sdu)); std::array pdu_buf; rlc->pull_pdu(pdu_buf); diff --git a/tests/e2e/tests/iperf.py b/tests/e2e/tests/iperf.py index 0c76ae4fdd..7a38ea8323 100644 --- a/tests/e2e/tests/iperf.py +++ b/tests/e2e/tests/iperf.py @@ -489,9 +489,9 @@ def test_zmq_smoke( ), ) @mark.zmq -@mark.flaky( - reruns=2, only_rerun=["failed to start", "Attach timeout reached", "iperf did not achieve the expected data rate"] -) +# @mark.flaky( +# reruns=2, only_rerun=["failed to start", "Attach timeout reached", "iperf did not achieve the expected data rate"] +# ) # pylint: disable=too-many-arguments def test_zmq( retina_manager: RetinaTestManager, diff --git a/tests/e2e/tests/viavi.py b/tests/e2e/tests/viavi.py index 25b49a97ea..7df1d239cf 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -107,18 +107,22 @@ def test_viavi_manual( gnb_startup_timeout=gnb_startup_timeout, gnb_stop_timeout=gnb_stop_timeout, log_search=log_search, + max_rb_size=-1, ) @mark.parametrize( - "campaign_filename, test_name, test_timeout, post_commands", + "campaign_filename, test_name, test_timeout, post_commands, max_rb_size", ( - param("C:\\ci\\CI 4x4 ORAN-FH.xml", "1UE static DL + UL UDP - Dell", 45 * 60, "", id="1UE Bidirectional UDP"), + param( + "C:\\ci\\CI 4x4 ORAN-FH.xml", "1UE static DL + UL UDP - Dell", 45 * 60, "", -1, id="1UE Bidirectional UDP" + ), param( "C:\\ci\\CI 4x4 ORAN-FH.xml", "32UE static DL + UL UDP - Dell", 45 * 60, - "cell_cfg pdsch --max_rb_size 45", + "", + 45, id="32UE Bidirectional UDP", ), ), @@ -139,6 +143,7 @@ def test_viavi( test_name: str, test_timeout: int, post_commands: str, + max_rb_size: int, # Test extra params always_download_artifacts: bool = True, gnb_startup_timeout: int = GNB_STARTUP_TIMEOUT, @@ -167,6 +172,7 @@ def test_viavi( gnb_stop_timeout=gnb_stop_timeout, log_search=log_search, post_commands=post_commands, + max_rb_size=max_rb_size, ) @@ -191,6 +197,7 @@ def _test_viavi( log_search: bool = True, warning_as_errors: bool = False, post_commands: str = "", + max_rb_size: int = -1, ): """ Runs a test using Viavi @@ -201,8 +208,18 @@ def _test_viavi( "gnb_id": 1, "log_level": "warning", "pcap": False, + "max_rb_size": max_rb_size, + "dl_arfcn": 625000, + "band": 78, + "channel_bandwidth_MHz": 100, + "common_scs": 30, + "tac": 7, + "pci": 1, + "nof_antennas_dl": 4, + "nof_antennas_ul": 1, + "prach_config_index": 159, }, - "templates": {"cell": str(Path(__file__).joinpath("../viavi/config.yml").resolve())}, + "templates": {"extra": str(Path(__file__).joinpath("../viavi/config.yml").resolve())}, }, } if metrics_server is not None: diff --git a/tests/e2e/tests/viavi/config.yml b/tests/e2e/tests/viavi/config.yml index 602f1acfcd..82b899609d 100644 --- a/tests/e2e/tests/viavi/config.yml +++ b/tests/e2e/tests/viavi/config.yml @@ -18,25 +18,11 @@ # and at http://www.gnu.org/licenses/. # -cu_cp: - pdu_session_setup_timeout: 5 - inactivity_timer: 5 - rrc: - force_reestablishment_fallback: true - cell_cfg: - dl_arfcn: 625000 - band: 78 - channel_bandwidth_MHz: 100 - common_scs: 30 - plmn: "{{mcc}}{{mnc}}" - tac: 7 - pci: 1 sib: t301: 2000 t311: 3000 prach: - prach_config_index: 159 prach_root_sequence_index: 1 zero_correlation_zone: 0 prach_frequency_start: 12 @@ -50,7 +36,6 @@ cell_cfg: mcs_table: qam256 max_alloc_attempts: 8 max_pdschs_per_slot: 8 - # max_rb_size: 45 # <-- enable this only for 32UE ul_common: max_ul_grants_per_slot: 16 max_pucchs_per_slot: 14 @@ -58,8 +43,6 @@ cell_cfg: mcs_table: qam256 min_k2: 2 max_puschs_per_slot: 8 - nof_antennas_dl: 4 - nof_antennas_ul: 1 tdd_ul_dl_cfg: nof_dl_symbols: 7 nof_dl_slots: 7 diff --git a/tests/integrationtests/du_high/du_high_test.cpp b/tests/integrationtests/du_high/du_high_test.cpp index b3577976c4..2408d9a807 100644 --- a/tests/integrationtests/du_high/du_high_test.cpp +++ b/tests/integrationtests/du_high/du_high_test.cpp @@ -74,6 +74,41 @@ TEST_F(du_high_tester, when_two_concurrent_ccch_msg_are_received_then_two_ue_con ASSERT_TRUE(test_helpers::is_init_ul_rrc_msg_transfer_valid(cu_notifier.last_f1ap_msgs[1], to_rnti(0x4602))); } +TEST_F(du_high_tester, when_ue_context_setup_completes_then_drb_is_active) +{ + // Create UE. + rnti_t rnti = to_rnti(0x4601); + ASSERT_TRUE(add_ue(rnti)); + ASSERT_TRUE(run_rrc_setup(rnti)); + ASSERT_TRUE(run_ue_context_setup(rnti)); + + // Ensure DU<->CU-UP tunnel was created. + ASSERT_EQ(cu_up_sim.last_drb_id.value(), drb_id_t::drb1); + + // Forward several DRB PDUs. + const unsigned nof_pdcp_pdus = 100, pdcp_pdu_size = 128; + pdcp_tx_pdu f1u_pdu{byte_buffer::create(test_rgen::random_vector(pdcp_pdu_size)).value(), nullopt}; + for (unsigned i = 0; i < nof_pdcp_pdus; ++i) { + cu_up_sim.du_notif->on_new_sdu(f1u_pdu); + } + + // Ensure DRB is active by verifying that the DRB PDUs are scheduled. + unsigned bytes_sched = 0; + phy.cell.last_dl_data.reset(); + while (bytes_sched < nof_pdcp_pdus * pdcp_pdu_size and this->run_until([this]() { + return phy.cell.last_dl_data.has_value() and not phy.cell.last_dl_data.value().ue_pdus.empty(); + })) { + for (unsigned i = 0; i != phy.cell.last_dl_data.value().ue_pdus.size(); ++i) { + if (phy.cell.last_dl_res.value().dl_res->ue_grants[i].pdsch_cfg.codewords[0].new_data) { + bytes_sched += phy.cell.last_dl_data.value().ue_pdus[i].pdu.size(); + } + } + phy.cell.last_dl_data.reset(); + } + ASSERT_GE(bytes_sched, nof_pdcp_pdus * pdcp_pdu_size) + << "Not enough PDSCH grants were scheduled to meet the enqueued PDCP PDUs"; +} + TEST_F(du_high_tester, when_ue_context_release_received_then_ue_gets_deleted) { // Create UE. @@ -89,19 +124,6 @@ TEST_F(du_high_tester, when_ue_context_release_received_then_ue_gets_deleted) for (unsigned i = 0; i != MAX_COUNT; ++i) { this->run_slot(); - // Handle PUCCH of the SRB message containing RRC Release. - for (const pucch_info& pucch : this->phy.cell.last_ul_res->ul_res->pucchs) { - if (pucch.format == srsran::pucch_format::FORMAT_1 and pucch.format_1.harq_ack_nof_bits > 0) { - mac_uci_indication_message uci_msg; - uci_msg.sl_rx = this->phy.cell.last_ul_res->slot; - uci_msg.ucis = {mac_uci_pdu{ - .rnti = to_rnti(0x4601), - .pdu = mac_uci_pdu::pucch_f0_or_f1_type{.harq_info = mac_uci_pdu::pucch_f0_or_f1_type::harq_information{ - .harqs = {uci_pucch_f0_or_f1_harq_values::ack}}}}}; - this->du_hi->get_control_info_handler(to_du_cell_index(0)).handle_uci(uci_msg); - } - } - // Stop loop, When UE Context Release complete has been sent to CU. if (not cu_notifier.last_f1ap_msgs.empty()) { break; @@ -113,6 +135,43 @@ TEST_F(du_high_tester, when_ue_context_release_received_then_ue_gets_deleted) (gnb_cu_ue_f1ap_id_t)cmd->gnb_cu_ue_f1ap_id)); } +TEST_F(du_high_tester, when_ue_context_setup_release_starts_then_drb_activity_stops) +{ + // Create UE. + rnti_t rnti = to_rnti(0x4601); + ASSERT_TRUE(add_ue(rnti)); + ASSERT_TRUE(run_rrc_setup(rnti)); + ASSERT_TRUE(run_ue_context_setup(rnti)); + + // CU-UP forwards many DRB PDUs. + const unsigned nof_pdcp_pdus = 100, pdcp_pdu_size = 128; + pdcp_tx_pdu f1u_pdu{byte_buffer::create(test_rgen::random_vector(pdcp_pdu_size)).value(), nullopt}; + for (unsigned i = 0; i < nof_pdcp_pdus; ++i) { + cu_up_sim.du_notif->on_new_sdu(f1u_pdu); + } + + // DU receives UE Context Release Request. + cu_notifier.last_f1ap_msgs.clear(); + f1ap_message msg = generate_ue_context_release_command(); + this->du_hi->get_f1ap_message_handler().handle_message(msg); + + // Ensure the DU does not keep to schedule DRB PDUs. + unsigned bytes_sched = 0; + phy.cell.last_dl_data.reset(); + while (bytes_sched < nof_pdcp_pdus * pdcp_pdu_size and this->run_until([this]() { + return phy.cell.last_dl_data.has_value() and not phy.cell.last_dl_data.value().ue_pdus.empty(); + })) { + for (unsigned i = 0; i != phy.cell.last_dl_data.value().ue_pdus.size(); ++i) { + if (phy.cell.last_dl_res.value().dl_res->ue_grants[i].pdsch_cfg.codewords[0].new_data) { + bytes_sched += phy.cell.last_dl_data.value().ue_pdus[i].pdu.size(); + } + } + phy.cell.last_dl_data.reset(); + } + ASSERT_LT(bytes_sched, nof_pdcp_pdus * pdcp_pdu_size) + << "Scheduler did not stop scheduling DRB after UE context release request reception"; +} + TEST_F(du_high_tester, when_du_high_is_stopped_then_ues_are_removed) { // Create UE. diff --git a/tests/integrationtests/du_high/test_utils/du_high_test_bench.cpp b/tests/integrationtests/du_high/test_utils/du_high_test_bench.cpp index e55a150626..5b29b0d2e7 100644 --- a/tests/integrationtests/du_high/test_utils/du_high_test_bench.cpp +++ b/tests/integrationtests/du_high/test_utils/du_high_test_bench.cpp @@ -215,6 +215,10 @@ bool du_high_test_bench::run_until(unique_function condition, unsigned m bool du_high_test_bench::add_ue(rnti_t rnti) { + if (ues.count(rnti) > 0) { + return false; + } + cu_notifier.last_f1ap_msgs.clear(); // Send UL-CCCH message. @@ -223,7 +227,99 @@ bool du_high_test_bench::add_ue(rnti_t rnti) // Wait for Init UL RRC Message to come out of the F1AP. bool ret = run_until([this]() { return not cu_notifier.last_f1ap_msgs.empty(); }, 1000 * (next_slot.numerology() + 1)); - return ret and test_helpers::is_init_ul_rrc_msg_transfer_valid(cu_notifier.last_f1ap_msgs.back(), rnti); + if (not ret or not test_helpers::is_init_ul_rrc_msg_transfer_valid(cu_notifier.last_f1ap_msgs.back(), rnti)) { + return false; + } + + gnb_du_ue_f1ap_id_t du_ue_id = int_to_gnb_du_ue_f1ap_id( + cu_notifier.last_f1ap_msgs.back().pdu.init_msg().value.init_ul_rrc_msg_transfer()->gnb_du_ue_f1ap_id); + gnb_cu_ue_f1ap_id_t cu_ue_id = int_to_gnb_cu_ue_f1ap_id(next_cu_ue_id++); + ues.insert(std::make_pair(rnti, ue_sim_context{rnti, du_ue_id, cu_ue_id})); + + return ret; +} + +bool du_high_test_bench::run_rrc_setup(rnti_t rnti) +{ + auto it = ues.find(rnti); + if (it == ues.end()) { + return false; + } + + // Send DL RRC Message which contains RRC Setup. + f1ap_message msg = generate_dl_rrc_message_transfer( + *it->second.du_ue_id, *it->second.cu_ue_id, srb_id_t::srb0, byte_buffer::create({0x1, 0x2, 0x3}).value()); + du_hi->get_f1ap_message_handler().handle_message(msg); + + // Wait for contention resolution to be sent to the PHY. + bool ret = run_until([&]() { + if (phy.cell.last_dl_res.has_value() and phy.cell.last_dl_res.value().dl_res != nullptr) { + auto& dl_res = *phy.cell.last_dl_res.value().dl_res; + for (const dl_msg_alloc& grant : dl_res.ue_grants) { + if (grant.pdsch_cfg.rnti == rnti and + std::any_of(grant.tb_list[0].lc_chs_to_sched.begin(), + grant.tb_list[0].lc_chs_to_sched.end(), + [](const dl_msg_lc_info& lc_grant) { return lc_grant.lcid == lcid_dl_sch_t::UE_CON_RES_ID; })) { + return true; + } + } + } + return false; + }); + if (not ret) { + return false; + } + + // Wait for Msg4 to be ACKed. + unsigned msg4_k1 = 4; + for (unsigned i = 0; i != msg4_k1; ++i) { + run_slot(); + } + + // UE sends RRC Setup Complete. Wait until F1AP forwards UL RRC Message to CU-CP. + cu_notifier.last_f1ap_msgs.clear(); + du_hi->get_pdu_handler().handle_rx_data_indication( + test_helpers::create_pdu_with_sdu(next_slot, rnti, lcid_t::LCID_SRB1)); + ret = run_until([this]() { return not cu_notifier.last_f1ap_msgs.empty(); }); + if (not ret or not test_helpers::is_ul_rrc_msg_transfer_valid(cu_notifier.last_f1ap_msgs.back(), srb_id_t::srb1)) { + return false; + } + return true; +} + +bool du_high_test_bench::run_ue_context_setup(rnti_t rnti) +{ + auto it = ues.find(rnti); + if (it == ues.end()) { + return false; + } + + // DU receives UE Context Setup Request. + cu_notifier.last_f1ap_msgs.clear(); + f1ap_message msg = generate_ue_context_setup_request({drb_id_t::drb1}); + asn1::f1ap::ue_context_setup_request_s& cmd = msg.pdu.init_msg().value.ue_context_setup_request(); + cmd->gnb_du_ue_f1ap_id = gnb_du_ue_f1ap_id_to_uint(*it->second.du_ue_id); + cmd->gnb_cu_ue_f1ap_id = gnb_cu_ue_f1ap_id_to_uint(*it->second.cu_ue_id); + cmd->drbs_to_be_setup_list[0] + .value() + .drbs_to_be_setup_item() + .qos_info.choice_ext() + .value() + .drb_info() + .drb_qos.qos_characteristics.non_dyn_5qi() + .five_qi = 7U; + cmd->drbs_to_be_setup_list[0].value().drbs_to_be_setup_item().rlc_mode.value = + asn1::f1ap::rlc_mode_opts::rlc_um_bidirectional; + this->du_hi->get_f1ap_message_handler().handle_message(msg); + + // Wait until DU sends UE Context Setup Response. + bool ret = this->run_until([this]() { return not cu_notifier.last_f1ap_msgs.empty(); }); + if (not ret or cu_notifier.last_f1ap_msgs.size() != 1 or + not test_helpers::is_ue_context_setup_response_valid(cu_notifier.last_f1ap_msgs.back())) { + return false; + } + + return true; } void du_high_test_bench::run_slot() @@ -245,4 +341,21 @@ void du_high_test_bench::run_slot() EXPECT_TRUE(dl_result.has_value() and dl_result->slot == next_slot); ++next_slot; + + // Process results. + handle_slot_results(); +} + +void du_high_test_bench::handle_slot_results() +{ + // Auto-generate UCI indications. + if (phy.cell.last_ul_res.has_value() and this->phy.cell.last_ul_res->ul_res != nullptr) { + const ul_sched_result& ul_res = *this->phy.cell.last_ul_res->ul_res; + slot_point sl_rx = this->phy.cell.last_ul_res->slot; + + if (not ul_res.pucchs.empty()) { + mac_uci_indication_message uci_ind = test_helpers::create_uci_indication(sl_rx, ul_res.pucchs); + this->du_hi->get_control_info_handler(to_du_cell_index(0)).handle_uci(uci_ind); + } + } } diff --git a/tests/integrationtests/du_high/test_utils/du_high_test_bench.h b/tests/integrationtests/du_high/test_utils/du_high_test_bench.h index 0bbee8427d..4006a660bd 100644 --- a/tests/integrationtests/du_high/test_utils/du_high_test_bench.h +++ b/tests/integrationtests/du_high/test_utils/du_high_test_bench.h @@ -56,14 +56,22 @@ class du_high_test_bench { public: du_high_test_bench(); - ~du_high_test_bench(); + virtual ~du_high_test_bench(); bool add_ue(rnti_t rnti); + /// Run the RRC setup procedure for the given RNTI from the moment the CU-CP sends an RRC Setup (via DL RRC Message + /// Transfer) until the CU receives the RRC Setup Complete (via UL RRC Message Transfer). + bool run_rrc_setup(rnti_t rnti); + + bool run_ue_context_setup(rnti_t rnti); + void run_slot(); bool run_until(unique_function condition, unsigned max_slot_count = 1000); + virtual void handle_slot_results(); + du_high_worker_manager workers; dummy_f1c_test_client cu_notifier; srs_du::cu_up_simulator cu_up_sim; @@ -76,6 +84,17 @@ class du_high_test_bench std::unique_ptr du_hi; slot_point next_slot; + +private: + struct ue_sim_context { + rnti_t rnti = rnti_t::INVALID_RNTI; + optional du_ue_id; + optional cu_ue_id; + }; + + std::unordered_map ues; + + unsigned next_cu_ue_id = 0; }; } // namespace srs_du diff --git a/tests/integrationtests/ofh/CMakeLists.txt b/tests/integrationtests/ofh/CMakeLists.txt index 924aa9f1df..80e2b32553 100644 --- a/tests/integrationtests/ofh/CMakeLists.txt +++ b/tests/integrationtests/ofh/CMakeLists.txt @@ -24,3 +24,14 @@ add_executable(ofh_integration_test ofh_integration_test.cpp) target_link_libraries(ofh_integration_test srslog srsran_ru_ofh srsran_phy_support srsran_support) add_test(ofh_integration_test ofh_integration_test) set_tests_properties(ofh_integration_test PROPERTIES LABELS "tsan;NO_MEMCHECK") + +if (DPDK_FOUND) + add_executable(ru_emulator ru_emulator_cli11_schema.cpp ru_emulator.cpp) + target_compile_options(ru_emulator PRIVATE ${DPDK_CFLAGS}) + + target_link_libraries(ru_emulator srslog srsran_ofh_dpdk_ethernet + srsran_phy_support srsran_support hal_dpdk ${DPDK_LIBRARIES}) + + target_include_directories(ru_emulator PRIVATE ${CMAKE_SOURCE_DIR}) + include_directories(${CMAKE_SOURCE_DIR}/external) +endif (DPDK_FOUND) diff --git a/tests/integrationtests/ofh/helpers.h b/tests/integrationtests/ofh/helpers.h new file mode 100644 index 0000000000..cffc6e5b70 --- /dev/null +++ b/tests/integrationtests/ofh/helpers.h @@ -0,0 +1,99 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/adt/span.h" +#include "srsran/ofh/ethernet/ethernet_mac_address.h" +#include "srsran/ran/bs_channel_bandwidth.h" +#include "srsran/ru/ru_ofh_configuration.h" + +using namespace srsran; + +/// Helper function to convert array of port indexes to string. +inline std::string port_ids_to_str(span ports) +{ + fmt::memory_buffer str_buffer; + fmt::format_to(str_buffer, "{"); + for (unsigned i = 0, e = ports.size(); i != e; ++i) { + fmt::format_to(str_buffer, "{}{}", ports[i], (i == (e - 1)) ? "}" : ", "); + } + return to_string(str_buffer); +} + +/// Helper function to parse list of ports provided as a string. +inline std::vector parse_port_id(const std::string& port_id_str) +{ + std::vector port_ids; + size_t start_pos = port_id_str.find('{'); + size_t end_pos = port_id_str.find('}'); + if (start_pos == std::string::npos || end_pos == std::string::npos) { + return port_ids; + } + std::string ports_comma_separated = port_id_str.substr(start_pos + 1, end_pos - 1); + std::stringstream ss(ports_comma_separated); + int port; + while (ss >> port) { + port_ids.push_back(port); + if (ss.peek() == ',' || ss.peek() == ' ') { + ss.ignore(); + } + } + return port_ids; +} + +/// Parses the string containing Ethernet MAC address. +inline bool parse_mac_address(const std::string& mac_str, ether::mac_address& mac) +{ + std::array data = {}; + int bytes_read = std::sscanf( + mac_str.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]); + if (bytes_read != ether::ETH_ADDR_LEN) { + fmt::print("Invalid MAC address provided: {}\n", mac_str); + return false; + } + + std::copy(data.begin(), data.end(), mac.begin()); + + return true; +} + +/// Validates the bandwidth argument provided as a user input. +inline bool is_valid_bw(unsigned bandwidth) +{ + // Bandwidth cannot be less than 5MHz. + if (bandwidth < 5U) { + return false; + } + + // Check from [5-25] in steps of 5. + if (bandwidth < 26U) { + return ((bandwidth % 5) == 0); + } + + // Check from [30-100] in steps of 10. + if (bandwidth < 101U) { + return ((bandwidth % 10) == 0); + } + + return false; +} diff --git a/tests/integrationtests/ofh/ofh_integration_test.cpp b/tests/integrationtests/ofh/ofh_integration_test.cpp index ba79b9b98b..50a5300c19 100644 --- a/tests/integrationtests/ofh/ofh_integration_test.cpp +++ b/tests/integrationtests/ofh/ofh_integration_test.cpp @@ -21,6 +21,7 @@ */ #include "../../../lib/phy/support/resource_grid_impl.h" +#include "helpers.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/circular_map.h" #include "srsran/ofh/ecpri/ecpri_constants.h" @@ -114,39 +115,6 @@ class dummy_ru_error_notifier : public ru_error_notifier static test_parameters test_params; -/// Helper function to convert array of port indexes to string. -static std::string port_ids_to_str(span ports) -{ - std::stringstream ss; - ss << "{"; - for (unsigned i = 0, e = ports.size() - 1; i != e; ++i) { - ss << ports[i] << ", "; - } - ss << ports[ports.size() - 1] << "}"; - return ss.str(); -} - -/// Helper function to parse list of ports provided as a string. -static std::vector parse_port_id(const std::string& port_id_str) -{ - std::vector port_ids; - size_t start_pos = port_id_str.find('{'); - size_t end_pos = port_id_str.find('}'); - if (start_pos == std::string::npos || end_pos == std::string::npos) { - return port_ids; - } - std::string ports_comma_separated = port_id_str.substr(start_pos + 1, end_pos - 1); - std::stringstream ss(ports_comma_separated); - int port; - while (ss >> port) { - port_ids.push_back(port); - if (ss.peek() == ',' || ss.peek() == ' ') { - ss.ignore(); - } - } - return port_ids; -} - /// Prints usage information of the app. static void usage(const char* prog) { @@ -181,55 +149,6 @@ static void usage(const char* prog) fmt::print("\t-h Show this message\n"); } -/// Validates the bandwidth argument provided as a user input. -static bool validate_bw(unsigned bandwidth) -{ - switch (bandwidth) { - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz5): - test_params.bw = bs_channel_bandwidth_fr1::MHz5; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz10): - test_params.bw = bs_channel_bandwidth_fr1::MHz10; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz15): - test_params.bw = bs_channel_bandwidth_fr1::MHz15; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz20): - test_params.bw = bs_channel_bandwidth_fr1::MHz20; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz25): - test_params.bw = bs_channel_bandwidth_fr1::MHz25; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz30): - test_params.bw = bs_channel_bandwidth_fr1::MHz30; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz40): - test_params.bw = bs_channel_bandwidth_fr1::MHz40; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz50): - test_params.bw = bs_channel_bandwidth_fr1::MHz50; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz60): - test_params.bw = bs_channel_bandwidth_fr1::MHz60; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz70): - test_params.bw = bs_channel_bandwidth_fr1::MHz70; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz80): - test_params.bw = bs_channel_bandwidth_fr1::MHz80; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz90): - test_params.bw = bs_channel_bandwidth_fr1::MHz90; - break; - case bs_channel_bandwidth_to_MHz(bs_channel_bandwidth_fr1::MHz100): - test_params.bw = bs_channel_bandwidth_fr1::MHz100; - break; - default: - return false; - } - return true; -} - /// Parses arguments of the app. static void parse_args(int argc, char** argv) { @@ -267,9 +186,11 @@ static void parse_args(int argc, char** argv) break; case 'w': if (optarg != nullptr) { - if (!validate_bw(std::strtol(optarg, nullptr, 10))) { + if (!is_valid_bw(std::strtol(optarg, nullptr, 10))) { fmt::print("Invalid bandwidth\n"); invalid_arg = true; + } else { + test_params.bw = MHz_to_bs_channel_bandwidth(std::strtol(optarg, nullptr, 10)); } } break; diff --git a/tests/integrationtests/ofh/ru_emulator.cpp b/tests/integrationtests/ofh/ru_emulator.cpp new file mode 100644 index 0000000000..5e73a6d88b --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator.cpp @@ -0,0 +1,691 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "../../../lib/ofh/ethernet/dpdk/dpdk_ethernet_port_context.h" +#include "helpers.h" +#include "ru_emulator_appconfig.h" +#include "ru_emulator_cli11_schema.h" +#include "srsran/adt/circular_map.h" +#include "srsran/hal/dpdk/dpdk_eal_factory.h" +#include "srsran/ofh/compression/compression_params.h" +#include "srsran/ofh/ecpri/ecpri_constants.h" +#include "srsran/ofh/ecpri/ecpri_packet_properties.h" +#include "srsran/ofh/ethernet/ethernet_frame_notifier.h" +#include "srsran/ofh/ethernet/ethernet_gateway.h" +#include "srsran/ofh/ethernet/ethernet_mac_address.h" +#include "srsran/ofh/ethernet/ethernet_properties.h" +#include "srsran/ofh/ethernet/ethernet_receiver.h" +#include "srsran/ofh/ofh_constants.h" +#include "srsran/ofh/serdes/ofh_message_properties.h" +#include "srsran/ran/resource_block.h" +#include "srsran/ran/slot_point.h" +#include "srsran/srslog/logger.h" +#include "srsran/support/config_parsers.h" +#include "srsran/support/executors/task_execution_manager.h" +#include "srsran/support/executors/task_executor.h" +#include "srsran/support/format_utils.h" +#include "srsran/support/signal_handler.h" +#include "fmt/chrono.h" +#include +#include +#include + +using namespace srsran; +using namespace ofh; +using namespace ether; + +/// Ethernet packet size. +static constexpr unsigned ETHERNET_FRAME_SIZE = 9000; + +namespace { + +/// RU emulator configuration structure. +struct ru_emulator_config { + /// Static compression parameters. + ru_compression_params compr_params; + /// Cell bandwidth in number of PRBs. + unsigned nof_prb; + /// RU emulator Ethernet MAC address. + mac_address ru_mac; + /// DU Ethernet MAC address. + mac_address du_mac; + /// VLAN tag. + unsigned vlan_tag; +}; + +/// Helper structure used to group OFH header parameters. +struct header_parameters { + uint8_t port; + unsigned payload_size; + unsigned start_prb; + unsigned nof_prbs; +}; + +} // namespace + +/// Fills the given array with random bytes. +static void fill_random_data(span frame, unsigned seed) +{ + std::mt19937 rgen(seed); + std::uniform_int_distribution dist{0, 255}; + std::generate(frame.begin(), frame.end(), [&]() { return dist(rgen); }); +} + +/// Fills static OFH header parameters given the static RU config. +void set_static_header_params(span frame, header_parameters params, const ru_emulator_config& cfg) +{ + static const uint8_t hdr_template[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x00, 0x00, 0x02, 0xae, 0xfe, 0x10, 0x00, 0x1d, 0xea, 0x00, 0x00, + 0x00, 0x80, 0x10, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00}; + + // Copy default header. + std::memcpy(frame.data(), hdr_template, sizeof(hdr_template)); + + // Set MAC addresses. + std::memcpy(&frame[0], cfg.du_mac.data(), ETH_ADDR_LEN); + std::memcpy(&frame[ETH_ADDR_LEN], cfg.ru_mac.data(), ETH_ADDR_LEN); + + // Set VLAN tag. + frame[15] = cfg.vlan_tag; + + // Set correct payload size. + uint16_t payload_size = ::htons(params.payload_size); + std::memcpy(&frame[20], &payload_size, sizeof(uint16_t)); + + // Set port ID. + frame[23] = params.port; + + // Set start PRB and number of PRBs. + frame[31] = uint8_t(params.start_prb >> 8u) & 0x3; + frame[32] = uint8_t(params.start_prb); + frame[33] = uint8_t((params.nof_prbs == cfg.nof_prb) ? 0 : params.nof_prbs); + + // Set compression header. + uint8_t octet = 0U; + octet |= uint8_t(cfg.compr_params.data_width) << 4U; + octet |= uint8_t(to_value(cfg.compr_params.type)); + frame[34] = octet; +} + +/// Returns pre-generated test data for each symbol for each configured eAxC. +std::vector>>> generate_test_data(const ru_emulator_config& cfg, + span ul_eaxc) +{ + // Vector of bytes for each frame (up to 2) of each OFDM symbol of each eAxC. + std::vector>>> test_data; + + const units::bytes ecpri_iq_data_header_size(8); + const units::bytes ofh_header_size(10); + const units::bytes ether_header_size(18); + + unsigned headers_size = (ether_header_size + ecpri_iq_data_header_size + ofh_header_size).value(); + // Size in bytes of one PRB using the given static compression parameters. + units::bytes prb_size = units::bits(cfg.compr_params.data_width * NOF_SUBCARRIERS_PER_RB * 2 + + (cfg.compr_params.type == compression_type::BFP ? 8 : 0)) + .round_up_to_bytes(); + unsigned iq_data_size = cfg.nof_prb * prb_size.value(); + + // It is assumed that maximum 2 packets required to send symbol data for antenna. + unsigned nof_frames = ((headers_size + iq_data_size) > ETHERNET_FRAME_SIZE) ? 2u : 1u; + // Save number of PRBs to be sent in each allocated frame. + std::vector nof_frame_prbs; + if (nof_frames == 1) { + nof_frame_prbs.push_back(cfg.nof_prb); + } else { + unsigned nof_prbs_first = (ETHERNET_FRAME_SIZE - headers_size) / prb_size.value(); + unsigned nof_prbs_second = cfg.nof_prb - nof_prbs_first; + nof_frame_prbs.push_back(nof_prbs_first); + nof_frame_prbs.push_back(nof_prbs_second); + } + + // Initializes IQ data and Ethernet packet headers for all configured eAxCs (timestamp and sequence index + // will be updated on every transmission). + for (unsigned port = 0, last = ul_eaxc.size(); port != last; ++port) { + test_data.emplace_back(); + auto& eaxc_frames = test_data.back(); + + for (unsigned symbol = 0, end = get_nsymb_per_slot(cyclic_prefix::NORMAL); symbol != end; ++symbol) { + eaxc_frames.emplace_back(); + auto& symbol_frames = eaxc_frames.back(); + + unsigned start_prb = 0; + for (unsigned j = 0; j != nof_frames; ++j) { + unsigned data_size = nof_frame_prbs[j] * prb_size.value(); + + symbol_frames.emplace_back(); + std::vector& frame = symbol_frames.back(); + frame.resize(headers_size + data_size); + + // Prepare header. + span frame_header(frame.data(), headers_size); + header_parameters params; + params.port = port; + params.payload_size = data_size + ofh_header_size.value() + ecpri::ECPRI_COMMON_HEADER_SIZE.value(); + params.start_prb = start_prb; + params.nof_prbs = nof_frame_prbs[j]; + + set_static_header_params(frame_header, params, cfg); + + // Prepare IQ data. + fill_random_data(span(frame).last(data_size), ul_eaxc[port] + symbol); + + start_prb += nof_frame_prbs[j]; + } + } + } + return test_data; +} + +namespace { + +/// Aggregates information received in UL C-Plane message. +struct uplink_request { + unsigned eaxc; + slot_point slot; +}; + +/// Encapsulates DPDK Ethernet transmitter and receiver functionalities. +class dpdk_transceiver : public gateway, public receiver +{ + enum class status { idle, running, stop_requested, stopped }; + +public: + dpdk_transceiver(srslog::basic_logger& logger_, + task_executor& executor_, + std::shared_ptr port_ctx_ptr_) : + logger(logger_), executor(executor_), port_ctx_ptr(port_ctx_ptr_), port_ctx(*port_ctx_ptr) + { + srsran_assert(port_ctx_ptr, "Invalid port context"); + } + + // See interface for documentation. + void start(frame_notifier& notifier_) override + { + notifier = ¬ifier_; + + std::promise p; + std::future fut = p.get_future(); + + if (!executor.defer([this, &p]() { + trx_status.store(status::running, std::memory_order_relaxed); + // Signal start() caller thread that the operation is complete. + p.set_value(); + receive_loop(); + })) { + report_error("Unable to start the DPDK ethernet frame receiver"); + } + + // Block waiting for timing executor to start. + fut.wait(); + + logger.info("Started the DPDK ethernet frame receiver"); + } + + // See interface for documentation. + void stop() override + { + logger.info("Requesting stop of the DPDK ethernet frame receiver"); + trx_status.store(status::stop_requested, std::memory_order_relaxed); + + // Wait for the receiver thread to stop. + while (trx_status.load(std::memory_order_acquire) != status::stopped) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + logger.info("Stopped the DPDK ethernet frame receiver"); + } + + // See interface for documentation. + void send(span> frames) override + { + if (frames.size() >= MAX_BURST_SIZE) { + logger.warning("Unable to send a transmission burst size of '{}' frames in the DPDK Ethernet transmitter", + frames.size()); + return; + } + + static_vector<::rte_mbuf*, MAX_BURST_SIZE> mbufs(frames.size()); + if (::rte_pktmbuf_alloc_bulk(port_ctx.get_mempool(), mbufs.data(), frames.size()) < 0) { + logger.warning("Not enough entries in the mempool to send '{}' frames in the DPDK Ethernet transmitter", + frames.size()); + return; + } + + for (unsigned idx = 0, end = frames.size(); idx != end; ++idx) { + const auto frame = frames[idx]; + ::rte_mbuf* mbuf = mbufs[idx]; + + if (::rte_pktmbuf_append(mbuf, frame.size()) == nullptr) { + ::rte_pktmbuf_free(mbuf); + logger.warning("Unable to append '{}' bytes to the allocated mbuf in the DPDK Ethernet transmitter", + frame.size()); + ::rte_pktmbuf_free_bulk(mbufs.data(), mbufs.size()); + return; + } + mbuf->data_len = frame.size(); + mbuf->pkt_len = frame.size(); + + uint8_t* data = rte_pktmbuf_mtod(mbuf, uint8_t*); + std::memcpy(data, frame.data(), frame.size()); + } + + unsigned nof_sent_packets = ::rte_eth_tx_burst(port_ctx.get_port_id(), 0, mbufs.data(), mbufs.size()); + + if (SRSRAN_UNLIKELY(nof_sent_packets < mbufs.size())) { + logger.warning("DPDK dropped '{}' packets out of a total of '{}' in the tx burst", + mbufs.size() - nof_sent_packets, + mbufs.size()); + for (unsigned buf_idx = nof_sent_packets, last_idx = mbufs.size(); buf_idx != last_idx; ++buf_idx) { + ::rte_pktmbuf_free(mbufs[buf_idx]); + } + } + } + +private: + void receive_loop() + { + if (trx_status.load(std::memory_order_relaxed) == status::stop_requested) { + trx_status.store(status::stopped, std::memory_order_release); + return; + } + + receive(); + + // Retry the task deferring when it fails. + while (!executor.defer([this]() { receive_loop(); })) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + } + + void receive() + { + std::array<::rte_mbuf*, MAX_BURST_SIZE> mbufs; + unsigned num_frames = ::rte_eth_rx_burst(port_ctx.get_port_id(), 0, mbufs.data(), MAX_BURST_SIZE); + if (num_frames == 0) { + std::this_thread::sleep_for(std::chrono::microseconds(1)); + return; + } + + for (auto mbuf : span<::rte_mbuf*>(mbufs.data(), num_frames)) { + ::rte_vlan_strip(mbuf); + + uint8_t* data = rte_pktmbuf_mtod(mbuf, uint8_t*); + unsigned length = mbuf->pkt_len; + notifier->on_new_frame(span(data, length)); + + ::rte_pktmbuf_free(mbuf); + } + } + + srslog::basic_logger& logger; + task_executor& executor; + std::shared_ptr port_ctx_ptr; + dpdk_port_context& port_ctx; + frame_notifier* notifier; + std::atomic trx_status{status::idle}; +}; + +/// Analyzes content of received OFH packets. +class packet_inspector +{ +public: + static bool is_uplink_cplane(span packet, srslog::basic_logger& logger) + { + // Drop malformed packet. + if (packet.size() < 26) { + logger.debug("Dropping packet of size smaller than 26 bytes"); + return false; + } + + // Verify the Ethernet type is eCPRI. + uint16_t eth_type = (uint16_t(packet[12]) << 8u) | packet[13]; + if (eth_type != ECPRI_ETH_TYPE) { + logger.debug("Dropping packet as it is not of eCPRI type"); + return false; + } + + // Skip U-Plane packets. + auto message_type = static_cast(packet[15]); + if (message_type == ecpri::message_type::iq_data) { + logger.debug("Discarding U-Plane packet"); + return false; + } + + // Check the filter index in the byte 26, bits 0-3. + auto filter_index = static_cast(packet[22] & 0x0f); + if (filter_index != filter_index_type::standard_channel_filter) { + logger.debug("Discarding packet with non-standard filter"); + return false; + } + + // Check direction, which is codified in the byte 26, bit 7. + auto direction = static_cast((packet[22] & 0x80) >> 7u); + logger.debug("Packet direction is {}", direction == data_direction::uplink ? "uplink" : "downlink"); + return direction == data_direction::uplink; + } + + static uplink_request get_uplink_params(span packet) + { + uplink_request ul_request; + + // First, peek the eAxC. + ul_request.eaxc = packet[19]; + + // Second, peek the timestamp. + // Slot is codified in the bytes 27-29 of the Ethernet packet. + uint8_t frame = packet[23]; + uint8_t subframe_and_slot = packet[24]; + uint8_t subframe = subframe_and_slot >> 4; + unsigned slot_id = 0; + slot_id |= (subframe_and_slot & 0x0f) << 2; + + uint8_t slot_and_symbol = packet[25]; + slot_id |= slot_and_symbol >> 6; + ul_request.slot = slot_point(to_numerology_value(subcarrier_spacing::kHz30), frame, subframe, slot_id); + return ul_request; + } +}; + +/// RU emulator receives OFH traffic and replies with UL packets to a DU. +class ru_emulator : public frame_notifier +{ + srslog::basic_logger& logger; + task_executor& executor; + dpdk_transceiver& transceiver; + + // RU emulator configuration. + const ru_emulator_config cfg; + // Pre-generated test data for each symbol for each configured eAxC. + std::vector>>> test_data; + // Keeps track of last used seq_id for each eAxC. + circular_map seq_counters; + // Stores the list of configured eAxC. + static_vector ul_eaxc; + // Counts number of received UL C-Plane packets for PUSCH. + std::atomic nof_rx_cplane_packets; + +public: + ru_emulator(srslog::basic_logger& logger_, + task_executor& executor_, + dpdk_transceiver& transceiver_, + ru_emulator_config cfg_, + std::vector ul_eaxc_) : + logger(logger_), executor(executor_), transceiver(transceiver_), cfg(cfg_), nof_rx_cplane_packets(0) + { + ul_eaxc.assign(ul_eaxc_.begin(), ul_eaxc_.end()); + for (auto eaxc : ul_eaxc) { + srsran_assert(eaxc <= MAX_SUPPORTED_EAXC_ID_VALUE, "Unsupported eAxC value requested"); + seq_counters.insert(eaxc, 0); + } + + test_data = generate_test_data(cfg, ul_eaxc); + } + + // See interface for documentation. + void on_new_frame(span payload) override + { + if (!executor.execute([this, payload, rx_payload = [payload]() -> std::array { + std::array buffer; + std::memcpy(buffer.data(), payload.data(), payload.size()); + return buffer; + }()]() { process_new_frame(span(rx_payload.data(), payload.size())); })) { + logger.warning("Failed to dispatch uplink task"); + } + } + + void start() { transceiver.start(*this); } + + unsigned get_statistics() const { return nof_rx_cplane_packets.load(std::memory_order_relaxed); } + +private: + void process_new_frame(span payload) + { + if (!packet_inspector::is_uplink_cplane(payload, logger)) { + return; + } + ++nof_rx_cplane_packets; + + auto ul_request = packet_inspector::get_uplink_params(payload); + if (std::find(ul_eaxc.begin(), ul_eaxc.end(), ul_request.eaxc) == ul_eaxc.end()) { + logger.info("Dropping received packet as its eAxC = '{}' is not configured in the RU emulator", ul_request.eaxc); + return; + } + if (!ul_request.slot.valid()) { + logger.warning("Dropping malformed packet as its timestamp is not correct"); + return; + } + + // Set correct header parameters and send UL U-Plane packets for each symbol. + static_vector, MAX_BURST_SIZE> frame_burst; + auto& eaxc_frames = test_data[ul_request.eaxc]; + + for (unsigned symbol = 0, end = get_nsymb_per_slot(cyclic_prefix::NORMAL); symbol != end; ++symbol) { + auto& symbol_frames = eaxc_frames[symbol]; + // Set runtime header parameters. + for (auto& frame : symbol_frames) { + set_runtime_header_params(frame, ul_request.slot, symbol, ul_request.eaxc); + frame_burst.emplace_back(frame.data(), frame.size()); + } + } + // Send symbols. + transceiver.send(frame_burst); + } + + void set_runtime_header_params(span frame, slot_point slot, unsigned symbol, unsigned eaxc) + { + // Set timestamp. + uint8_t octet = 0; + frame[27] = uint8_t(slot.sfn()); + // Subframe index; offset: 4, 4 bits long. + octet |= uint8_t(slot.subframe_index()) << 4u; + // Four MSBs of the slot index within 1ms subframe; offset: 4, 6 bits long. + octet |= uint8_t(slot.subframe_slot_index() >> 2u); + frame[28] = octet; + + octet = 0; + octet |= uint8_t(slot.subframe_slot_index() & 0x3) << 6u; + octet |= uint8_t(symbol); + frame[29] = octet; + + // Set sequence index. + uint8_t& seq_id = seq_counters[eaxc]; + frame[24] = seq_id++; + } +}; + +/// Manages the workers of the RU emulators. +struct worker_manager { + static constexpr uint32_t task_worker_queue_size = 128; + + worker_manager(unsigned nof_emulators) { create_executors(nof_emulators); } + + void create_executors(unsigned nof_emulators) + { + using namespace execution_config_helper; + + // Executor for Open Fronthaul messages reception. + { + const std::string name = "ru_rx"; + const std::string exec_name = "ru_rx_exec"; + + const single_worker ru_worker{name, + {concurrent_queue_policy::lockfree_spsc, 2}, + {{exec_name}}, + std::chrono::microseconds{1}, + os_thread_realtime_priority::max() - 1}; + if (!exec_mng.add_execution_context(create_execution_context(ru_worker))) { + report_fatal_error("Failed to instantiate {} execution context", ru_worker.name); + } + ru_rx_exec = exec_mng.executors().at(exec_name); + } + + for (unsigned i = 0; i != nof_emulators; ++i) { + // Executors for the RU emulators. + { + const std::string name = "ru_emu_#" + std::to_string(i); + const std::string exec_name = "ru_emu_exec_#" + std::to_string(i); + const single_worker ru_worker{name, + {concurrent_queue_policy::lockfree_spsc, task_worker_queue_size}, + {{exec_name}}, + std::chrono::microseconds{5}, + os_thread_realtime_priority::max() - 5}; + if (!exec_mng.add_execution_context(create_execution_context(ru_worker))) { + report_fatal_error("Failed to instantiate {} execution context", ru_worker.name); + } + ru_emulators_exec.push_back(exec_mng.executors().at(exec_name)); + } + } + } + + void stop() { exec_mng.stop(); } + + task_execution_manager exec_mng; + task_executor* ru_rx_exec = nullptr; + std::vector ru_emulators_exec; +}; + +} // namespace + +static std::string config_file; + +const int MAX_CONFIG_FILES(6); +static std::atomic is_running = {true}; + +static void local_signal_handler() +{ + is_running = false; +} + +int main(int argc, char** argv) +{ + // Set signal handler. + register_signal_handler(local_signal_handler); + + // Setup and configure config parsing. + CLI::App app("RU emulator application"); + app.config_formatter(create_yaml_config_parser()); + app.allow_config_extras(CLI::config_extras_mode::error); + app.set_config("-c,", config_file, "Read config from file", false)->expected(1, MAX_CONFIG_FILES); + + ru_emulator_appconfig ru_emulator_parsed_cfg; + // Configure CLI11 with the RU emulator application configuration schema. + configure_cli11_with_ru_emulator_appconfig_schema(app, ru_emulator_parsed_cfg); + + // Parse arguments. + CLI11_PARSE(app, argc, argv); + + if (ru_emulator_parsed_cfg.ru_cfg.empty()) { + report_error("Invalid configuration detected, at least one RU configuration must be provided\n"); + } + + // Set up logging. + srslog::sink* log_sink = (ru_emulator_parsed_cfg.log_cfg.filename == "stdout") + ? srslog::create_stdout_sink() + : srslog::create_file_sink(ru_emulator_parsed_cfg.log_cfg.filename); + if (log_sink == nullptr) { + report_error("Could not create application main log sink.\n"); + } + srslog::set_default_sink(*log_sink); + srslog::init(); + + srslog::basic_logger& logger = srslog::fetch_basic_logger("RU_EMU", false); + logger.set_level(srslog::str_to_basic_level(ru_emulator_parsed_cfg.log_cfg.level)); + + // Initialize DPDK EAL. + std::unique_ptr eal; + // Prepend the application name in argv[0] as it is expected by EAL. + eal = dpdk::create_dpdk_eal(std::string(argv[0]) + " " + ru_emulator_parsed_cfg.dpdk_config.eal_args, + srslog::fetch_basic_logger("EAL", false)); + if (!eal) { + report_error("Failed to initialize DPDK EAL\n"); + } + + // Create workers and executors. + worker_manager workers(ru_emulator_parsed_cfg.ru_cfg.size()); + + // Set up DPDK transceivers and create RU emulators. + std::vector> transceivers; + std::vector> ru_emulators; + + for (unsigned i = 0, e = ru_emulator_parsed_cfg.ru_cfg.size(); i != e; ++i) { + ru_emulator_ofh_appconfig ru_cfg = ru_emulator_parsed_cfg.ru_cfg[i]; + dpdk_port_config port_cfg; + port_cfg.pcie_id = ru_cfg.network_interface; + port_cfg.mtu_size = units::bytes{ETHERNET_FRAME_SIZE}; + port_cfg.is_promiscuous_mode_enabled = false; + auto ctx = dpdk_port_context::create(port_cfg); + transceivers.push_back(std::make_unique(logger, *workers.ru_rx_exec, ctx)); + + ru_emulator_config emu_cfg; + emu_cfg.nof_prb = + get_max_Nprb(bs_channel_bandwidth_to_MHz(ru_cfg.bandwidth), subcarrier_spacing::kHz30, frequency_range::FR1); + emu_cfg.compr_params = {to_compression_type(ru_cfg.ul_compr_method), ru_cfg.ul_compr_bitwidth}; + emu_cfg.vlan_tag = ru_cfg.vlan_tag; + if (!parse_mac_address(ru_cfg.ru_mac_address, emu_cfg.ru_mac)) { + report_error("Invalid MAC address provided: '{}'", ru_cfg.ru_mac_address); + } + if (!parse_mac_address(ru_cfg.du_mac_address, emu_cfg.du_mac)) { + report_error("Invalid MAC address provided: '{}'", ru_cfg.du_mac_address); + } + + ru_emulators.push_back(std::make_unique( + logger, *workers.ru_emulators_exec[i], *transceivers[i], emu_cfg, ru_cfg.ru_ul_port_id)); + } + + // Start RU emulators. + for (auto& ru : ru_emulators) { + ru->start(); + } + fmt::print("Running. Waiting for incoming packets...\n"); + + while (is_running) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + + auto now = std::chrono::system_clock::now(); + std::tm current_time = fmt::gmtime(std::chrono::system_clock::to_time_t(now)); + + fmt::memory_buffer buffer; + for (unsigned i = 0, e = ru_emulators.size(); i != e; ++i) { + auto nof_rx_pacckets = ru_emulators[i]->get_statistics(); + if (nof_rx_pacckets) { + fmt::format_to(buffer, + "Cell #{}: {:%F}T{:%H:%M:%S} Received {} UL C-Plane packets\n", + i, + current_time, + current_time, + nof_rx_pacckets); + } + } + fmt::print(to_c_str(buffer)); + } + + for (auto& txrx : transceivers) { + txrx->stop(); + } + workers.stop(); + srslog::flush(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + fmt::print("\nRU emulator app stopped\n"); + + return 0; +} diff --git a/tests/integrationtests/ofh/ru_emulator_appconfig.h b/tests/integrationtests/ofh/ru_emulator_appconfig.h new file mode 100644 index 0000000000..d5a2aa5685 --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_appconfig.h @@ -0,0 +1,75 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "srsran/ran/bs_channel_bandwidth.h" +#include +#include + +namespace srsran { + +/// RU emulator OFH configuration parameters. +struct ru_emulator_ofh_appconfig { + /// Ethernet network interface PCI bus identifier. + std::string network_interface; + /// RU emulator MAC address. + std::string ru_mac_address; + /// Distributed Unit MAC address. + std::string du_mac_address; + /// V-LAN Tag control information field. + unsigned vlan_tag; + /// RU Uplink ports. + std::vector ru_ul_port_id = {0, 1}; + /// RU emulator operating bandwidth. + bs_channel_bandwidth_fr1 bandwidth = srsran::bs_channel_bandwidth_fr1::MHz100; + /// Uplink compression method. + std::string ul_compr_method = "bfp"; + /// Uplink compression bitwidth. + unsigned ul_compr_bitwidth = 9; +}; + +/// RU emulator logging parameters. +struct ru_emulator_log_appconfig { + /// Log level + std::string level = "info"; + /// Path to log file or "stdout" to print to console. + std::string filename = "stdout"; +}; + +/// DPDK configuration. +struct ru_emulator_dpdk_appconfig { + /// EAL configuration arguments. + std::string eal_args; +}; + +/// RU emulator application configuration. +struct ru_emulator_appconfig { + /// Logging configuration. + ru_emulator_log_appconfig log_cfg; + /// Individual RU emulators configurations. + std::vector ru_cfg = {{}}; + /// DPDK configuration. + ru_emulator_dpdk_appconfig dpdk_config; +}; + +} // namespace srsran diff --git a/tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp b/tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp new file mode 100644 index 0000000000..d7fcd8a173 --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp @@ -0,0 +1,116 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "ru_emulator_cli11_schema.h" +#include "helpers.h" +#include "ru_emulator_appconfig.h" +#include "srsran/support/cli11_utils.h" +#include "srsran/support/config_parsers.h" + +using namespace srsran; + +static void configure_cli11_log_args(CLI::App& app, ru_emulator_log_appconfig& log_params) +{ + auto level_check = [](const std::string& value) -> std::string { + if (value == "info" || value == "debug" || value == "warning" || value == "error") { + return {}; + } + return "Log level value not supported. Accepted values [info,debug,warning,error]"; + }; + + app.add_option("--filename", log_params.filename, "Log file output path")->capture_default_str(); + app.add_option("--level", log_params.level, "Log level")->capture_default_str()->check(level_check); +} + +static void configure_cli11_ru_emu_dpdk_args(CLI::App& app, ru_emulator_dpdk_appconfig& config) +{ + app.add_option("--eal_args", config.eal_args, "EAL configuration parameters used to initialize DPDK"); +} + +static void configure_cli11_ru_emu_args(CLI::App& app, ru_emulator_ofh_appconfig& config) +{ + app.add_option_function( + "--bandwidth", + [&config](unsigned value) { config.bandwidth = MHz_to_bs_channel_bandwidth(value); }, + "Channel bandwidth in MHz") + ->check([](const std::string& value) -> std::string { + std::stringstream ss(value); + unsigned bw; + ss >> bw; + const std::string& error_message = "Error in the channel bandwidth property. Valid values " + "[5,10,15,20,25,30,40,50,60,70,80,90,100]"; + + return is_valid_bw(bw) ? "" : error_message; + }); + + auto compression_method_check = [](const std::string& value) -> std::string { + if (value == "none" || value == "bfp") { + return {}; + } + + return "Compression method not supported. Accepted values [none, bfp]"; + }; + + app.add_option("--compr_method_ul", config.ul_compr_method, "Uplink compression method") + ->capture_default_str() + ->check(compression_method_check); + app.add_option("--compr_bitwidth_ul", config.ul_compr_bitwidth, "Uplink compression bit width") + ->capture_default_str() + ->check(CLI::IsMember({9, 16})); + app.add_option("--network_interface", config.network_interface, "PCIe identifier of network device") + ->capture_default_str(); + app.add_option("--ru_mac_addr", config.ru_mac_address, "Radio Unit MAC address")->capture_default_str(); + app.add_option("--du_mac_addr", config.du_mac_address, "Distributed Unit MAC address")->capture_default_str(); + app.add_option("--vlan_tag", config.vlan_tag, "V-LAN identifier")->capture_default_str()->check(CLI::Range(1, 4094)); + app.add_option("--ul_port_id", config.ru_ul_port_id, "RU uplink port identifier")->capture_default_str(); +} + +void srsran::configure_cli11_with_ru_emulator_appconfig_schema(CLI::App& app, ru_emulator_appconfig& ru_emu_parsed_cfg) +{ + // Logging section. + CLI::App* log_subcmd = app.add_subcommand("log", "Logging configuration")->configurable(); + configure_cli11_log_args(*log_subcmd, ru_emu_parsed_cfg.log_cfg); + + // RU emulators section. + CLI::App* ru_subcmd = + app.add_subcommand("ru_emu", "Open Fronthaul Radio Unit emulator configuration")->configurable(); + + // Cell parameters. + ru_subcmd->add_option_function>( + "--cells", + [&ru_emu_parsed_cfg](const std::vector& values) { + ru_emu_parsed_cfg.ru_cfg.resize(values.size()); + + for (unsigned i = 0, e = values.size(); i != e; ++i) { + CLI::App subapp("RU emulators"); + subapp.config_formatter(create_yaml_config_parser()); + subapp.allow_config_extras(CLI::config_extras_mode::error); + configure_cli11_ru_emu_args(subapp, ru_emu_parsed_cfg.ru_cfg[i]); + std::istringstream ss(values[i]); + subapp.parse_from_stream(ss); + } + }, + "Sets the RU emulator configuration"); + + CLI::App* dpdk_subcmd = app.add_subcommand("dpdk", "DPDK configuration")->configurable(); + configure_cli11_ru_emu_dpdk_args(*dpdk_subcmd, ru_emu_parsed_cfg.dpdk_config); +} diff --git a/tests/integrationtests/ofh/ru_emulator_cli11_schema.h b/tests/integrationtests/ofh/ru_emulator_cli11_schema.h new file mode 100644 index 0000000000..7a8475bdab --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_cli11_schema.h @@ -0,0 +1,34 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +#include "CLI/CLI11.hpp" + +namespace srsran { + +struct ru_emulator_appconfig; + +/// Configures the given CLI11 application with the RU emulator application configuration schema. +void configure_cli11_with_ru_emulator_appconfig_schema(CLI::App& app, ru_emulator_appconfig& ru_emu_parsed_cfg); + +} // namespace srsran diff --git a/tests/integrationtests/rlc/rlc_stress_test_f1.h b/tests/integrationtests/rlc/rlc_stress_test_f1.h index 2a94e85d19..c5f083267d 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_f1.h +++ b/tests/integrationtests/rlc/rlc_stress_test_f1.h @@ -83,7 +83,7 @@ class f1ap_dummy : public pdcp_tx_lower_notifier, for (uint8_t byte : pdu) { report_error_if_not(buf.append(byte), "Failed to allocate byte buffer"); } - pdcp_rx_lower->handle_pdu(byte_buffer_chain{std::move(buf)}); + pdcp_rx_lower->handle_pdu(byte_buffer_chain::create(std::move(buf)).value()); } // RLC -> F1 -> RRC diff --git a/tests/integrationtests/rlc/rlc_stress_test_mac.cpp b/tests/integrationtests/rlc/rlc_stress_test_mac.cpp index 9294a31f0c..29fc23b1ea 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_mac.cpp +++ b/tests/integrationtests/rlc/rlc_stress_test_mac.cpp @@ -44,7 +44,7 @@ std::vector mac_dummy::run_tx_tti(uint32_t tti) if (bsr.load(std::memory_order_relaxed) > 0) { unsigned nwritten = rlc_tx_lower->pull_pdu(tx_pdu); expected pdu = - byte_buffer_chain::create(byte_buffer_slice{span(tx_pdu.data(), nwritten)}); + byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()); if (!pdu) { report_fatal_error_if_not(pdu, "Failed to create PDU buffer"); } @@ -85,7 +85,7 @@ void mac_dummy::run_rx_tti() } // Write PDU copy in RX - rlc_rx_lower->handle_pdu(byte_buffer(pdu_it->begin(), pdu_end)); + rlc_rx_lower->handle_pdu(byte_buffer::create(pdu_it->begin(), pdu_end).value()); // Write PCAP // TODO: write PCAP diff --git a/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp b/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp index 9aec1d3099..4ff582ce43 100644 --- a/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp +++ b/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp @@ -36,3 +36,29 @@ bool srsran::test_helpers::is_init_ul_rrc_msg_transfer_valid(const f1ap_message& const asn1::f1ap::init_ul_rrc_msg_transfer_s& rrcmsg = msg.pdu.init_msg().value.init_ul_rrc_msg_transfer(); return rrcmsg->c_rnti == to_value(rnti); } + +bool srsran::test_helpers::is_ul_rrc_msg_transfer_valid(const f1ap_message& msg, srb_id_t srb_id) +{ + if (not(msg.pdu.type() == asn1::f1ap::f1ap_pdu_c::types_opts::init_msg and + msg.pdu.init_msg().proc_code == ASN1_F1AP_ID_UL_RRC_MSG_TRANSFER)) { + return false; + } + const asn1::f1ap::ul_rrc_msg_transfer_s& rrcmsg = msg.pdu.init_msg().value.ul_rrc_msg_transfer(); + if (rrcmsg->srb_id != srb_id_to_uint(srb_id) or rrcmsg->rrc_container.empty()) { + return false; + } + return true; +} + +bool srsran::test_helpers::is_ue_context_setup_response_valid(const f1ap_message& msg) +{ + if (not(msg.pdu.type() == asn1::f1ap::f1ap_pdu_c::types_opts::successful_outcome and + msg.pdu.successful_outcome().proc_code == ASN1_F1AP_ID_UE_CONTEXT_SETUP)) { + return false; + } + const asn1::f1ap::ue_context_setup_resp_s& resp = msg.pdu.successful_outcome().value.ue_context_setup_resp(); + if (not resp->drbs_setup_list_present) { + return false; + } + return true; +} diff --git a/tests/test_doubles/f1ap/f1ap_test_message_validators.h b/tests/test_doubles/f1ap/f1ap_test_message_validators.h index afef1cc7d7..d223573c28 100644 --- a/tests/test_doubles/f1ap/f1ap_test_message_validators.h +++ b/tests/test_doubles/f1ap/f1ap_test_message_validators.h @@ -22,6 +22,8 @@ #pragma once +#include "srsran/f1ap/common/f1ap_ue_id.h" +#include "srsran/ran/lcid.h" #include "srsran/ran/rnti.h" namespace srsran { @@ -32,5 +34,9 @@ namespace test_helpers { bool is_init_ul_rrc_msg_transfer_valid(const f1ap_message& msg, rnti_t rnti); -} +bool is_ul_rrc_msg_transfer_valid(const f1ap_message& msg, srb_id_t srb_id); + +bool is_ue_context_setup_response_valid(const f1ap_message& msg); + +} // namespace test_helpers } // namespace srsran \ No newline at end of file diff --git a/tests/test_doubles/f1u/dummy_f1u_du_gateway.h b/tests/test_doubles/f1u/dummy_f1u_du_gateway.h index bd28efc58c..aa758c2699 100644 --- a/tests/test_doubles/f1u/dummy_f1u_du_gateway.h +++ b/tests/test_doubles/f1u/dummy_f1u_du_gateway.h @@ -51,6 +51,9 @@ class cu_up_simulator : public f1u_du_gateway f1u_dummy_bearer bearer; srs_du::f1u_rx_sdu_notifier* du_notif = nullptr; + optional last_ue_idx; + optional last_drb_id; + f1u_bearer* create_du_bearer(uint32_t ue_index, drb_id_t drb_id, srs_du::f1u_config config, @@ -60,7 +63,9 @@ class cu_up_simulator : public f1u_du_gateway timer_factory timers, task_executor& ue_executor) override { - du_notif = &du_rx; + du_notif = &du_rx; + last_ue_idx = ue_index; + last_drb_id = drb_id; return &bearer; } diff --git a/tests/test_doubles/mac/mac_test_messages.cpp b/tests/test_doubles/mac/mac_test_messages.cpp index 143bf6132b..c22c913da3 100644 --- a/tests/test_doubles/mac/mac_test_messages.cpp +++ b/tests/test_doubles/mac/mac_test_messages.cpp @@ -21,6 +21,7 @@ */ #include "mac_test_messages.h" +#include "srsran/scheduler/scheduler_slot_handler.h" using namespace srsran; @@ -29,5 +30,84 @@ mac_rx_data_indication srsran::test_helpers::create_ccch_message(slot_point sl_r return mac_rx_data_indication{ sl_rx, to_du_cell_index(0), - {mac_rx_pdu{rnti, 0, 0, {0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}}}}; + {mac_rx_pdu{rnti, + 0, + 0, + byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}).value()}}}; +} + +mac_rx_data_indication srsran::test_helpers::create_pdu_with_sdu(slot_point sl_rx, rnti_t rnti, lcid_t lcid) +{ + return mac_rx_data_indication{ + sl_rx, + to_du_cell_index(0), + {mac_rx_pdu{ + rnti, + 0, + 0, + byte_buffer::create({(uint8_t)lcid, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05, 0xdf, 0x80, 0x10, 0x5e, + 0x40, 0x03, 0x40, 0x40, 0x3c, 0x44, 0x3c, 0x3f, 0xc0, 0x00, 0x04, 0x0c, 0x95, + 0x1d, 0xa6, 0x0b, 0x80, 0xb8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}) + .value()}}}; +} + +mac_uci_pdu srsran::test_helpers::create_uci_pdu(const pucch_info& pucch) +{ + mac_uci_pdu pdu{}; + + pdu.rnti = pucch.crnti; + + switch (pucch.format) { + case pucch_format::FORMAT_1: { + auto& uci_f1 = pdu.pdu.emplace(); + const auto& pucch_f1 = pucch.format_1; + + if (pucch_f1.harq_ack_nof_bits > 0) { + uci_f1.harq_info.emplace(); + uci_f1.harq_info->harqs.resize(pucch_f1.harq_ack_nof_bits, uci_pucch_f0_or_f1_harq_values::ack); + } + + if (pucch_f1.sr_bits != sr_nof_bits::no_sr) { + uci_f1.sr_info.emplace(); + uci_f1.sr_info->detected = false; + } + } break; + case pucch_format::FORMAT_2: { + auto& uci_f2 = pdu.pdu.emplace(); + const auto& pucch_f2 = pucch.format_2; + + if (pucch_f2.harq_ack_nof_bits > 0) { + uci_f2.harq_info.emplace(); + uci_f2.harq_info->is_valid = true; + uci_f2.harq_info->payload.resize(pucch_f2.harq_ack_nof_bits); + uci_f2.harq_info->payload.fill(true); + } + + if (pucch_f2.sr_bits != sr_nof_bits::no_sr) { + uci_f2.sr_info.emplace(); + uci_f2.sr_info->resize(sr_nof_bits_to_uint(pucch_f2.sr_bits)); + } + + if (pucch_f2.csi_part1_bits > 0) { + uci_f2.csi_part1_info.emplace(); + uci_f2.csi_part1_info->is_valid = true; + uci_f2.csi_part1_info->payload.resize(pucch_f2.csi_part1_bits); + uci_f2.csi_part1_info->payload.fill(true); + } + } break; + default: + report_fatal_error("Unsupported PUCCH format"); + } + + return pdu; +} + +mac_uci_indication_message srsran::test_helpers::create_uci_indication(slot_point sl_rx, span pucchs) +{ + mac_uci_indication_message uci_ind; + uci_ind.sl_rx = sl_rx; + for (const auto& pucch : pucchs) { + uci_ind.ucis.push_back(create_uci_pdu(pucch)); + } + return uci_ind; } diff --git a/tests/test_doubles/mac/mac_test_messages.h b/tests/test_doubles/mac/mac_test_messages.h index 932af37960..fe3d926bbb 100644 --- a/tests/test_doubles/mac/mac_test_messages.h +++ b/tests/test_doubles/mac/mac_test_messages.h @@ -22,13 +22,25 @@ #pragma once +#include "srsran/mac/mac_cell_control_information_handler.h" #include "srsran/mac/mac_pdu_handler.h" namespace srsran { + +struct pucch_info; + namespace test_helpers { /// Creates a CCCH message with the given RNTI. mac_rx_data_indication create_ccch_message(slot_point sl_rx, rnti_t rnti); +mac_rx_data_indication create_pdu_with_sdu(slot_point sl_rx, rnti_t rnti, lcid_t lcid); + +/// \brief Generate MAC UCI PDU from PUCCH information, with all HARQ-ACKs set to ACK, SRs set as not detected and CSI +/// set as 1s. +mac_uci_pdu create_uci_pdu(const pucch_info& pucch); + +mac_uci_indication_message create_uci_indication(slot_point sl_rx, span pucchs); + } // namespace test_helpers } // namespace srsran \ No newline at end of file diff --git a/tests/unittests/adt/byte_buffer_chain_test.cpp b/tests/unittests/adt/byte_buffer_chain_test.cpp index b07a5149fe..d4511919a4 100644 --- a/tests/unittests/adt/byte_buffer_chain_test.cpp +++ b/tests/unittests/adt/byte_buffer_chain_test.cpp @@ -51,7 +51,9 @@ class byte_buffer_chain_test : public testing::Test TEST_F(byte_buffer_chain_test, empty_container_in_valid_state) { - byte_buffer_chain chain; + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& chain = buffer.value(); ASSERT_TRUE(chain.empty()); ASSERT_EQ(chain.length(), 0U); ASSERT_EQ(chain.nof_slices(), 0); @@ -76,12 +78,14 @@ TEST_F(byte_buffer_chain_test, empty_container_in_valid_state) TEST_F(byte_buffer_chain_test, append_byte_buffer) { - byte_buffer_chain buf; - - byte_buffer other_buffer{1, 2, 3, 4, 5}; - byte_buffer other_buffer2{6, 7, 8}; - byte_buffer buf_concat = other_buffer.deep_copy(); - ASSERT_TRUE(buf_concat.append(other_buffer2.deep_copy())); + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& buf = buffer.value(); + + byte_buffer other_buffer = byte_buffer::create({1, 2, 3, 4, 5}).value(); + byte_buffer other_buffer2 = byte_buffer::create({6, 7, 8}).value(); + byte_buffer buf_concat = other_buffer.deep_copy().value(); + ASSERT_TRUE(buf_concat.append(other_buffer2.deep_copy().value())); ASSERT_TRUE(buf.append(other_buffer.copy())); ASSERT_TRUE(buf.append(other_buffer2.copy())); @@ -107,21 +111,23 @@ TEST_F(byte_buffer_chain_test, append_byte_buffer) ASSERT_EQ(buf, buf_concat); // Test copy - byte_buffer buf_copy = buf.deep_copy(); + byte_buffer buf_copy = buf.deep_copy().value(); ASSERT_EQ(buf_copy.length(), buf_concat.length()); ASSERT_EQ(buf_copy, buf_concat); } TEST_F(byte_buffer_chain_test, prepend_buffer) { - std::vector vec = {1, 2, 3}; - byte_buffer_chain buf; - byte_buffer buf2{vec}; + std::vector vec = {1, 2, 3}; + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& buf = buffer.value(); + byte_buffer buf2 = byte_buffer::create(vec).value(); ASSERT_TRUE(buf.empty()); // Set header using a span of bytes. - ASSERT_TRUE(buf.prepend(buf2.deep_copy())); + ASSERT_TRUE(buf.prepend(buf2.deep_copy().value())); ASSERT_FALSE(buf.empty()); ASSERT_EQ(3, buf.length()); ASSERT_EQ(buf, vec); @@ -143,7 +149,7 @@ TEST_F(byte_buffer_chain_test, prepend_buffer) // Set header by ref-count increment, avoiding deep copy. buf.clear(); - buf2 = vec; + buf2 = byte_buffer::create(vec).value(); ASSERT_TRUE(buf.prepend(buf2.copy())); ASSERT_EQ(buf, vec); *buf2.begin() = 5; @@ -151,8 +157,8 @@ TEST_F(byte_buffer_chain_test, prepend_buffer) // Set header by deep copy. buf.clear(); - buf2 = vec; - ASSERT_TRUE(buf.prepend(buf2.deep_copy())); + buf2 = byte_buffer::create(vec).value(); + ASSERT_TRUE(buf.prepend(buf2.deep_copy().value())); ASSERT_EQ(buf, vec); *buf2.begin() = 5; ASSERT_EQ(buf, vec); @@ -160,12 +166,14 @@ TEST_F(byte_buffer_chain_test, prepend_buffer) TEST_F(byte_buffer_chain_test, prepend_header_and_append_payload) { - byte_buffer_chain buf; + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& buf = buffer.value(); - byte_buffer header_bytes = {1, 2, 3}; - byte_buffer payload = {4, 5, 6}; + byte_buffer header_bytes = byte_buffer::create({1, 2, 3}).value(); + byte_buffer payload = byte_buffer::create({4, 5, 6}).value(); - ASSERT_TRUE(buf.prepend(header_bytes.deep_copy())); + ASSERT_TRUE(buf.prepend(header_bytes.deep_copy().value())); ASSERT_EQ(header_bytes.length(), buf.length()); ASSERT_TRUE(buf.append(payload.copy())); ASSERT_EQ(header_bytes.length() + payload.length(), buf.length()); @@ -192,13 +200,15 @@ TEST_F(byte_buffer_chain_test, prepend_header_and_append_payload) TEST_F(byte_buffer_chain_test, payload_lifetime) { - byte_buffer_chain buf; + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& buf = buffer.value(); std::vector all_bytes; { - byte_buffer header_bytes = {1, 2, 3}; - byte_buffer payload1 = {4, 5, 6}; - byte_buffer payload2 = {7, 8, 9}; + byte_buffer header_bytes = byte_buffer::create({1, 2, 3}).value(); + byte_buffer payload1 = byte_buffer::create({4, 5, 6}).value(); + byte_buffer payload2 = byte_buffer::create({7, 8, 9}).value(); all_bytes.insert(all_bytes.end(), header_bytes.begin(), header_bytes.end()); all_bytes.insert(all_bytes.end(), payload1.begin(), payload1.end()); @@ -215,12 +225,15 @@ TEST_F(byte_buffer_chain_test, payload_lifetime) TEST_F(byte_buffer_chain_test, slice_chain_formatter) { - byte_buffer pdu, pdu2; + byte_buffer pdu; + byte_buffer pdu2; std::vector bytes = {1, 2, 3, 4, 15, 16, 255}; ASSERT_TRUE(pdu.append(bytes)); ASSERT_TRUE(pdu2.append(bytes)); - byte_buffer_chain chain; + auto buffer = byte_buffer_chain::create(); + ASSERT_FALSE(buffer.is_error()); + byte_buffer_chain& chain = buffer.value(); ASSERT_TRUE(chain.append(byte_buffer_slice{std::move(pdu), 3, 2})); ASSERT_TRUE(chain.append(byte_buffer_slice{std::move(pdu2), 0, 2})); diff --git a/tests/unittests/adt/byte_buffer_test.cpp b/tests/unittests/adt/byte_buffer_test.cpp index 1e5f8a604c..336afd00ca 100644 --- a/tests/unittests/adt/byte_buffer_test.cpp +++ b/tests/unittests/adt/byte_buffer_test.cpp @@ -184,7 +184,7 @@ TEST_F(byte_buffer_tester, empty_byte_buffer_in_valid_state) ASSERT_EQ_LEN(pdu, 0); pdu.clear(); ASSERT_EQ_LEN(pdu, 0); - ASSERT_EQ(pdu, pdu.deep_copy()); + ASSERT_EQ(pdu, pdu.deep_copy().value()); ASSERT_EQ(pdu, pdu.copy()); ASSERT_TRUE(pdu.append(std::vector{})); ASSERT_EQ_LEN(pdu, 0); @@ -193,7 +193,7 @@ TEST_F(byte_buffer_tester, empty_byte_buffer_in_valid_state) TEST_P(one_vector_size_param_test, ctor_with_span) { - byte_buffer pdu{this->bytes}; + byte_buffer pdu = byte_buffer::create(this->bytes).value(); ASSERT_EQ_LEN(pdu, bytes.size()); ASSERT_TRUE(std::equal(pdu.begin(), pdu.end(), bytes.begin(), bytes.end())); @@ -201,8 +201,8 @@ TEST_P(one_vector_size_param_test, ctor_with_span) TEST_P(one_vector_size_param_test, equality_comparison) { - byte_buffer pdu{this->bytes}; - byte_buffer pdu2{this->bytes}; + byte_buffer pdu = byte_buffer::create(this->bytes).value(); + byte_buffer pdu2 = byte_buffer::create(this->bytes).value(); std::list not_a_span{this->bytes.begin(), this->bytes.end()}; // comparison byte_buffer vs span. @@ -217,7 +217,7 @@ TEST_P(one_vector_size_param_test, equality_comparison) // comparison byte_buffer vs other range of larger length. std::vector larger_bytes = concat_vec(bytes, test_rgen::random_vector(random_vec_size())); std::list larger_not_a_span{larger_bytes.begin(), larger_bytes.end()}; - pdu2 = byte_buffer{larger_bytes}; + pdu2 = byte_buffer::create(larger_bytes).value(); ASSERT_NE(pdu, larger_bytes); ASSERT_NE(larger_bytes, pdu); ASSERT_NE(pdu, pdu2); @@ -228,7 +228,7 @@ TEST_P(one_vector_size_param_test, equality_comparison) std::vector shorter_bytes(bytes.begin(), bytes.begin() + test_rgen::uniform_int(0, bytes.size() - 1)); std::list shorter_not_a_span{shorter_bytes.begin(), shorter_bytes.end()}; - pdu2 = byte_buffer{shorter_bytes}; + pdu2 = byte_buffer::create(shorter_bytes).value(); ASSERT_NE(pdu, shorter_bytes); ASSERT_NE(shorter_bytes, pdu); ASSERT_NE(pdu, pdu2); @@ -259,7 +259,7 @@ TEST_P(one_vector_size_param_test, move_ctor) TEST_F(byte_buffer_tester, initializer_list) { - byte_buffer pdu = {1, 2, 3, 4, 5, 6}; + byte_buffer pdu = byte_buffer::create({1, 2, 3, 4, 5, 6}).value(); std::vector bytes{1, 2, 3, 4, 5, 6}; ASSERT_EQ_LEN(pdu, 6); @@ -276,7 +276,7 @@ TEST_P(two_vector_size_param_test, append) ASSERT_EQ_BUFFER(pdu, bytes1); // Append two byte_buffers. - byte_buffer pdu2{bytes2}; + byte_buffer pdu2 = byte_buffer::create(bytes2).value(); ASSERT_EQ(pdu2, bytes2); ASSERT_TRUE(pdu2.append(pdu)); ASSERT_EQ(pdu.length() + bytes2.size(), pdu2.length()); @@ -368,7 +368,7 @@ TEST_F(byte_buffer_tester, deep_copy_for_empty_byte_buffer) { byte_buffer pdu; byte_buffer pdu2; - pdu2 = pdu.deep_copy(); + pdu2 = pdu.deep_copy().value(); ASSERT_TRUE(pdu.empty()); ASSERT_TRUE(pdu.empty()); } @@ -381,7 +381,7 @@ TEST_P(two_vector_size_param_test, deep_copy_for_non_empty_byte_buffer) // Deep copy. byte_buffer pdu2; - pdu2 = pdu.deep_copy(); + pdu2 = pdu.deep_copy().value(); ASSERT_FALSE(pdu.empty()); ASSERT_FALSE(pdu2.empty()); ASSERT_EQ_BUFFER(pdu, pdu2); @@ -494,7 +494,7 @@ TEST_P(three_vector_size_param_test, shallow_copy_prepend_and_append_keeps_valid // When a byte_buffer::prepend causes the byte_buffer head segment to move, any previously existing shallow copies // could become invalidated. To avoid this issue, we perform COW on prepend, when more than one byte_buffer points to // the same head segment. - byte_buffer pdu{bytes1}; + byte_buffer pdu = byte_buffer::create(bytes1).value(); byte_buffer pdu2{pdu.copy()}; ASSERT_TRUE(pdu.prepend(bytes2)); @@ -509,7 +509,7 @@ TEST_P(three_vector_size_param_test, shallow_copy_reserve_prepend_and_append_kee // When a byte_buffer::prepend causes the byte_buffer head segment to move, any previously existing shallow copies // could become invalidated. To avoid this issue, we perform COW on prepend, when more than one byte_buffer point to // the same head segment. - byte_buffer pdu{bytes1}; + byte_buffer pdu = byte_buffer::create(bytes1).value(); byte_buffer pdu2{pdu.copy()}; byte_buffer_view v = pdu.reserve_prepend(bytes2.size()); @@ -529,7 +529,7 @@ TEST_F(byte_buffer_tester, is_contiguous) ASSERT_TRUE(pdu.append(bytes)); ASSERT_TRUE(pdu.is_contiguous()); - ASSERT_TRUE(pdu.append(byte_buffer(bytes2))); + ASSERT_TRUE(pdu.append(byte_buffer::create(bytes2).value())); ASSERT_TRUE(not pdu.is_contiguous()); ASSERT_EQ_BUFFER(pdu, bytes_concat); @@ -770,7 +770,7 @@ TEST_F(byte_buffer_tester, append_rvalue_byte_buffer) std::vector bytes_concat2 = concat_vec(bytes_concat, big_vec); // Chain small vector to empty buffer - byte_buffer pdu2(small_vec); + byte_buffer pdu2 = byte_buffer::create(small_vec).value(); ASSERT_EQ(pdu2, small_vec); ASSERT_TRUE(pdu.prepend(std::move(pdu2))); ASSERT_FALSE(pdu.empty()); @@ -821,15 +821,16 @@ TEST_P(byte_buffer_stress_tester, concurrent_alloc_dealloc_test) bool alloc_or_dealloc = rdist(test_rgen::get()) <= this->P_alloc; if (alloc_or_dealloc) { // Allocation of new buffer. - byte_buffer buf(span(randbytes.data(), test_rgen::uniform_int(1U, max_buffer_size))); - if (buf.empty()) { + auto buf = + byte_buffer::create(span(randbytes.data(), test_rgen::uniform_int(1U, max_buffer_size))); + if (buf.is_error()) { // pool is depleted. continue; } if (free_list.empty()) { - allocated_buffers.push_back(std::move(buf)); + allocated_buffers.push_back(std::move(buf.value())); } else { - allocated_buffers[free_list.back()] = std::move(buf); + allocated_buffers[free_list.back()] = std::move(buf.value()); free_list.pop_back(); } } else { @@ -872,28 +873,28 @@ TEST_F(byte_buffer_tester, concurrent_alloc_dealloc_test) // Deplete the pool while (true) { - byte_buffer pdu = byte_buffer{span{randbytes.data(), 10U}}; - if (pdu.empty()) { + auto pdu = byte_buffer::create(span{randbytes.data(), 10U}); + if (pdu.is_error()) { break; } - allocated_buffers.push_back(std::move(pdu)); + allocated_buffers.push_back(std::move(pdu.value())); } // Pool is still empty. - byte_buffer pdu = byte_buffer{span{randbytes.data(), test_rgen::uniform_int(1U, max_buffer_size)}}; - ASSERT_TRUE(pdu.empty()); + auto pdu = byte_buffer::create(span{randbytes.data(), test_rgen::uniform_int(1U, max_buffer_size)}); + ASSERT_TRUE(pdu.is_error()); // Test if a span can be added to a byte_buffer with heap as fallback allocator. size_t sz = test_rgen::uniform_int(1U, max_buffer_size); pdu = byte_buffer{byte_buffer::fallback_allocation_tag{}, span{randbytes.data(), sz}}; - ASSERT_EQ(pdu.length(), sz); + ASSERT_EQ(pdu.value().length(), sz); span expected_bytes{randbytes.data(), sz}; - ASSERT_EQ(pdu, expected_bytes); + ASSERT_EQ(pdu.value(), expected_bytes); // Test if a byte_buffer can be added to a byte_buffer with heap as fallback allocator. pdu = byte_buffer{byte_buffer::fallback_allocation_tag{}, allocated_buffers.front()}; - ASSERT_EQ(pdu.length(), allocated_buffers.front().length()); - ASSERT_EQ(pdu, allocated_buffers.front()); + ASSERT_EQ(pdu.value().length(), allocated_buffers.front().length()); + ASSERT_EQ(pdu.value(), allocated_buffers.front()); } INSTANTIATE_TEST_SUITE_P(byte_buffer_test, @@ -950,7 +951,7 @@ TEST_F(byte_buffer_view_tester, length) TEST_F(byte_buffer_view_tester, segment_iterator) { std::vector bytes = test_rgen::random_vector(random_vec_size()); - byte_buffer pdu{bytes}; + byte_buffer pdu = byte_buffer::create(bytes).value(); unsigned offset = test_rgen::uniform_int(0, bytes.size() - 1); unsigned last_offset = test_rgen::uniform_int(offset + 1, bytes.size()); @@ -980,8 +981,8 @@ TEST_F(byte_buffer_slice_tester, empty_slice_is_in_valid_state) TEST_F(byte_buffer_slice_tester, ctor_with_span) { - std::vector vec = test_rgen::random_vector(test_rgen::uniform_int(1, large_vec_size)); - byte_buffer_slice slice(vec); + std::vector vec = test_rgen::random_vector(test_rgen::uniform_int(1, large_vec_size)); + byte_buffer_slice slice = byte_buffer_slice::create(vec).value(); ASSERT_EQ_LEN(slice, vec.size()); // Test operator[]. @@ -1001,7 +1002,7 @@ TEST_F(byte_buffer_slice_tester, ctor_with_span) TEST_F(byte_buffer_slice_tester, shallow_copy) { std::vector vec = test_rgen::random_vector(test_rgen::uniform_int(1, large_vec_size)); - byte_buffer pdu(vec); + byte_buffer pdu = byte_buffer::create(vec).value(); byte_buffer_slice slice{pdu.copy()}; @@ -1029,9 +1030,9 @@ TEST_F(byte_buffer_slice_tester, shallow_copy) TEST_F(byte_buffer_slice_tester, deep_slice) { std::vector vec = test_rgen::random_vector(random_vec_size()); - byte_buffer pdu{vec}; + byte_buffer pdu = byte_buffer::create(vec).value(); - byte_buffer_slice slice{pdu.deep_copy()}; + byte_buffer_slice slice{pdu.deep_copy().value()}; // Test operator[]. for (unsigned i = 0; i < vec.size(); ++i) { @@ -1066,7 +1067,7 @@ TEST_F(byte_buffer_slice_tester, deep_slice) TEST_F(byte_buffer_slice_tester, move_ctor) { std::vector vec = test_rgen::random_vector(random_vec_size()); - byte_buffer pdu{vec}; + byte_buffer pdu = byte_buffer::create(vec).value(); byte_buffer_slice slice{std::move(pdu)}; ASSERT_TRUE(pdu.empty()); diff --git a/tests/unittests/asn1/asn1_e1ap_test.cpp b/tests/unittests/asn1/asn1_e1ap_test.cpp index 6e4266e926..c5a53eff5e 100644 --- a/tests/unittests/asn1/asn1_e1ap_test.cpp +++ b/tests/unittests/asn1/asn1_e1ap_test.cpp @@ -116,7 +116,7 @@ TEST_F(asn1_e1ap_test, when_bearer_context_setup_request_correct_then_unpacking_ 0x00, 0x2a, 0x00, 0x23, 0x00, 0x40, 0x01, 0x00, 0x02, 0x12, 0x30, 0x05, 0xf5, 0xe1, 0x00, 0x01, 0xf0, 0xac, 0x15, 0x04, 0x86, 0x00, 0x00, 0x00, 0x36, 0x00, 0x03, 0x01, 0x30, 0x0a, 0x20, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x09, 0x7a, 0x00, 0x4d, 0x40, 0x02, 0x00, 0x00}; - srsran::byte_buffer rx_pdu{rx_msg}; + srsran::byte_buffer rx_pdu = byte_buffer::create(rx_msg).value(); #if JSON_OUTPUT pcap_writer->push_pdu(rx_msg); @@ -177,7 +177,7 @@ TEST_F(asn1_e1ap_test, when_bearer_context_setup_response_correct_then_unpacking 0x00, 0x03, 0x40, 0x02, 0x80, 0x00, 0x10, 0x40, 0x23, 0x40, 0x00, 0x01, 0x00, 0x2e, 0x40, 0x1c, 0x00, 0x00, 0x01, 0x01, 0xf0, 0xac, 0x15, 0x06, 0x09, 0x00, 0x00, 0x02, 0x83, 0x00, 0x06, 0x00, 0x1f, 0xac, 0x15, 0x06, 0x09, 0x80, 0x00, 0x02, 0x83, 0x00, 0x00, 0x80}; - srsran::byte_buffer rx_pdu{rx_msg}; + srsran::byte_buffer rx_pdu = byte_buffer::create(rx_msg).value(); #if JSON_OUTPUT pcap_writer->push_pdu(rx_msg); diff --git a/tests/unittests/asn1/asn1_f1ap_test.cpp b/tests/unittests/asn1/asn1_f1ap_test.cpp index c4b4c2d1ae..c7f6eaf7ab 100644 --- a/tests/unittests/asn1/asn1_f1ap_test.cpp +++ b/tests/unittests/asn1/asn1_f1ap_test.cpp @@ -240,7 +240,7 @@ TEST_F(asn1_f1ap_test, when_ue_context_setup_request_correct_then_unpacking_succ 0x22, 0x51, 0x40, 0x08, 0x09, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x66, 0x00, 0x17, 0x02, 0x00, 0x00, 0x00, 0xa1, 0x40, 0x01, 0x40, 0x00, 0x9e, 0x40, 0x04, 0x20, 0x20, 0x3a, 0x00}; - srsran::byte_buffer rx_pdu{rx_msg}; + srsran::byte_buffer rx_pdu = byte_buffer::create(rx_msg).value(); #ifdef JSON_OUTPUT pcap_writer->push_pdu(rx_msg); @@ -279,7 +279,7 @@ TEST_F(asn1_f1ap_test, when_initial_ul_rrc_message_transfer_correct_then_unpacki 0x13, 0xb6, 0x4b, 0x18, 0x14, 0x40, 0x0e, 0x46, 0x8a, 0xcf, 0x12, 0x00, 0x00, 0x09, 0x60, 0x70, 0x82, 0x0f, 0x17, 0x7e, 0x06, 0x08, 0x70, 0x00, 0x00, 0x00, 0xe2, 0x50, 0x38, 0x00, 0x00, 0x40, 0xbd, 0xe8, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x01, 0x95, 0x03, 0x00, 0xc4, 0x00, 0x00, 0x4e, 0x40, 0x02, 0x00, 0x00}; - srsran::byte_buffer rx_pdu{rx_msg}; + srsran::byte_buffer rx_pdu = byte_buffer::create(rx_msg).value(); #ifdef JSON_OUTPUT pcap_writer->push_pdu(rx_msg); @@ -319,7 +319,7 @@ TEST_F(asn1_f1ap_test, when_initial_ul_rrc_message_transfer_packing_correct_then 0x13, 0xb6, 0x4b, 0x18, 0x14, 0x40, 0x0e, 0x46, 0x8a, 0xcf, 0x12, 0x00, 0x00, 0x09, 0x60, 0x70, 0x82, 0x0f, 0x17, 0x7e, 0x06, 0x08, 0x70, 0x00, 0x00, 0x00, 0xe2, 0x50, 0x38, 0x00, 0x00, 0x40, 0xbd, 0xe8, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x01, 0x95, 0x03, 0x00, 0xc4, 0x00, 0x00, 0x4e, 0x40, 0x02, 0x00, 0x00}; - srsran::byte_buffer rx_pdu{rx_msg}; + srsran::byte_buffer rx_pdu = byte_buffer::create(rx_msg).value(); asn1::f1ap::f1ap_pdu_c tx_pdu; diff --git a/tests/unittests/asn1/asn1_ngap_test.cpp b/tests/unittests/asn1/asn1_ngap_test.cpp index 2cf2e953be..8b795cee11 100644 --- a/tests/unittests/asn1/asn1_ngap_test.cpp +++ b/tests/unittests/asn1/asn1_ngap_test.cpp @@ -187,7 +187,7 @@ TEST_F(asn1_ngap_test, ng_setup_request_pack_and_unpack) 0x67, 0x6e, 0x62, 0x31, 0x00, 0x66, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x40, 0x01, 0x60}; // 00150030000004001b00090000f1105000000001005240060180676e62310066000d00000000750000f110000000080015400160 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; @@ -236,7 +236,7 @@ TEST_F(asn1_ngap_test, ng_setup_response_pack_and_unpack) 0x60, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf1, 0x10, 0x38, 0x08, 0x97, 0x00, 0x56, 0x40, 0x01, 0x05, 0x00, 0x50, 0x00, 0x08, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x08}; // 2015005e0000040001003a1b80616d66312e636c7573746572312e6e6574322e616d662e3567632e6d6e633030312e6d63633030312e336770706e6574776f726b2e6f726700600008000000f1103808970056400105005000080000f11000000008 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; @@ -270,7 +270,7 @@ TEST_F(asn1_ngap_test, amf_config_update) const uint8_t ngap_msg[] = { 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x02, 0x80, 0x73, 0x72, 0x73, 0x72, 0x61, 0x6e}; // 0000000F00000100010008028073727372616E - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; @@ -309,7 +309,7 @@ TEST_F(asn1_ngap_test, init_ue_msg_pack_and_unpack) 0x00, 0x00, 0x00, 0x10, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x75, 0x00, 0x5a, 0x40, 0x01, 0x18}; // 000f4080a20000040055000200010026007d7c7e00417100760100f110000001014d436f77425159444b325675417945416e363648396b7a485461465a4b30353741497237412b6e6c736149587852334e6973364c566f75466942343ddfabf5cd652eb2541491484d41432d53484100858bbb1f42f1256f9a37531a772a2cf2b78ff160488402ed489399b6b737420079000f4000f110000000001000f110000075005a400118 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); @@ -341,7 +341,7 @@ TEST_F(asn1_ngap_test, dl_nas_transport_pack_and_unpack) 0xe2, 0x82, 0x84, 0x7c, 0x9f, 0x4c, 0xe5, 0xc1, 0x94, 0x51}; // 0004403e000003000a000200010055000200010026002b2a7e00560002000021681cd489650fdcc7c70eca8fa9be44702010c7f0791fa852e282847c9f4ce5c19451 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); @@ -370,7 +370,7 @@ TEST_F(asn1_ngap_test, ul_ran_status_transfer_pack_and_unpack) 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x75}; // 002e403c000004000a0002000100550002000100260016157e00572d105e86219e7dda9995e3850384cfbea53b0079400f4000f110000000001000f110000075 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); @@ -394,7 +394,7 @@ TEST_F(asn1_ngap_test, ue_context_release_pack_and_unpack) 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0f, 0x40, 0x01, 0x48}; // 002900100000020072000400010001000f400148 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); @@ -415,7 +415,7 @@ TEST_F(asn1_ngap_test, ue_context_release_complete_pack_and_unpack) 0x20, 0x29, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x40, 0x02, 0x00, 0x01, 0x00, 0x55, 0x40, 0x02, 0x00, 0x01}; // 2029000f000002000a40020001005540020001 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); @@ -442,7 +442,7 @@ TEST_F(asn1_ngap_test, session_res_setup_request_pack_and_unpack) 0x01, 0x00, 0x86, 0x00, 0x01, 0x10, 0x00, 0x88, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00}; // 001d006c000004000a000200010055000200010026002e2d7e00680100252e0100c2110006010003300101060603e80603e8290501c0a80c7b25080764656661756c741201004a0027000001000021000003008b000a01f0c0a811d20000000100860001100088000700010000090000 - const srsran::byte_buffer byte_pdu{ngap_msg}; + const srsran::byte_buffer byte_pdu = srsran::byte_buffer::create(ngap_msg).value(); cbit_ref bref(byte_pdu); ngap_pdu_c pdu; ASSERT_EQ(pdu.unpack(bref), SRSASN_SUCCESS); diff --git a/tests/unittests/asn1/asn1_rrc_nr_test.cpp b/tests/unittests/asn1/asn1_rrc_nr_test.cpp index 17e85500bc..c1b06e032d 100644 --- a/tests/unittests/asn1/asn1_rrc_nr_test.cpp +++ b/tests/unittests/asn1/asn1_rrc_nr_test.cpp @@ -160,9 +160,11 @@ TEST_F(asn1_rrc_nr_test, when_eutra_nr_capabilities_correct_then_packing_success TEST_F(asn1_rrc_nr_test, when_ue_mrdc_capabilities_correct_then_unpacking_successful) { - srsran::byte_buffer pdu{0x01, 0x1c, 0x04, 0x81, 0x60, 0x00, 0x1c, 0x4d, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x40, 0x04, 0x04, 0xd0, 0x10, 0x74, 0x06, 0x14, 0xe8, 0x1b, 0x10, - 0x78, 0x00, 0x00, 0x20, 0x00, 0x10, 0x08, 0x08, 0x01, 0x00, 0x20}; + srsran::byte_buffer pdu = + srsran::byte_buffer::create({0x01, 0x1c, 0x04, 0x81, 0x60, 0x00, 0x1c, 0x4d, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x40, 0x04, 0x04, 0xd0, 0x10, 0x74, 0x06, 0x14, 0xe8, 0x1b, 0x10, + 0x78, 0x00, 0x00, 0x20, 0x00, 0x10, 0x08, 0x08, 0x01, 0x00, 0x20}) + .value(); // 011c048160001c4d0000000400400404d010740614e81b107800002000100808010020 asn1::cbit_ref bref{pdu}; @@ -199,7 +201,7 @@ TEST_F(asn1_rrc_nr_test, when_ue_rrc_reconfiguration_correct_then_unpacking_succ "\x08\x82\x00\x07\x10\x80\x0e\x60\x00\x40\x00\x00\x04\x10\xc0\x40" "\x80\xc1\x00\xe0\xd0\x00\x0e\x48\x10\x00\x00\x02\x00\x40\x00\x80" "\x60\x00\x80\x90\x02\x20\x0a\x40\x00\x02\x38\x90\x11\x31\xc8"; - srsran::byte_buffer pdu{rrc_msg}; + srsran::byte_buffer pdu = srsran::byte_buffer::create(rrc_msg).value(); cbit_ref bref(pdu); rrc_recfg_s rrc_recfg; @@ -235,7 +237,7 @@ TEST_F(asn1_rrc_nr_test, when_ue_rrc_reconfiguration_correct_then_unpacking_succ TEST_F(asn1_rrc_nr_test, when_radio_bearer_config_correct_then_unpacking_successful) { uint8_t rrc_msg[] = "\x14\x09\x28\x17\x87\xc0\x0c\x28"; - srsran::byte_buffer pdu{rrc_msg}; + srsran::byte_buffer pdu = srsran::byte_buffer::create(rrc_msg).value(); cbit_ref bref(pdu); radio_bearer_cfg_s radio_bearer_cfg; @@ -279,7 +281,7 @@ TEST_F(asn1_rrc_nr_test, when_cell_group_config_correct_then_unpacking_successfu "\x60\x00\x40\x00\x00\x04\x10\xc0\x40\x80\xc1\x00\xe0\xd0\x00\x0e" "\x48\x10\x00\x00\x02\x00\x40\x00\x80\x60\x00\x80\x90\x02\x20\x0a" "\x40\x00\x02\x38\x90\x11\x31\xc8"; - srsran::byte_buffer pdu{cell_group_config_raw}; + srsran::byte_buffer pdu = srsran::byte_buffer::create(cell_group_config_raw).value(); cbit_ref bref(pdu); cell_group_cfg_s cell_group_cfg; @@ -336,20 +338,23 @@ TEST_F(asn1_rrc_nr_test, when_cell_group_config_correct_then_unpacking_successfu TEST_F(asn1_rrc_nr_test, when_ue_nr_capabilities_rel15_correct_then_unpacking_successful) { // UE caps of a Simcom SIM8262E-M2 5G module with IEs and extensions up to Rel15.4 - srsran::byte_buffer pdu{ - 0xe1, 0xa0, 0x53, 0x80, 0x57, 0x4f, 0x7a, 0x03, 0x16, 0x00, 0x03, 0x06, 0x40, 0x02, 0xc1, 0x00, 0x10, 0x18, 0x09, - 0x31, 0x70, 0x01, 0x9c, 0x3d, 0x09, 0x00, 0x31, 0x20, 0xd0, 0x09, 0x80, 0x40, 0x62, 0x30, 0x01, 0x50, 0x6c, 0x4d, - 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x74, 0x82, 0x40, 0x51, 0x6c, 0xaa, 0x2a, 0x12, 0x1c, 0xfa, 0x06, 0x7d, 0x81, - 0x3e, 0x31, 0xcf, 0x98, 0x63, 0xca, 0x16, 0x07, 0x03, 0x87, 0x81, 0x70, 0x01, 0xdf, 0x00, 0x1c, 0x00, 0x77, 0xc0, - 0x01, 0x22, 0x00, 0x36, 0x50, 0x00, 0x05, 0x00, 0x00, 0x00, 0x12, 0x83, 0xc4, 0xd0, 0x00, 0xc2, 0x68, 0x00, 0x00, - 0x20, 0x2e, 0x10, 0x71, 0x34, 0x00, 0x00, 0x08, 0x78, 0x00, 0xc8, 0x0a, 0x14, 0x29, 0xdb, 0x2d, 0x78, 0xf0, 0x21, - 0x6c, 0xb5, 0xe3, 0x8f, 0x41, 0x28, 0x03, 0xe0, 0x03, 0x01, 0x01, 0x40, 0x18, 0x0c, 0x02, 0x50, 0x06, 0x00, 0x06, - 0x03, 0xe0, 0x20, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, - 0x80, 0x20, 0x00, 0x01, 0x00, 0x46, 0x50, 0xd6, 0x52, 0xd6, 0x4c, 0xde, 0x54, 0xd6, 0x46, 0xd0, 0x08, 0x10, 0x00, - 0x00, 0x01, 0xb0, 0x00, 0x40, 0x00, 0x04, 0x06, 0xc0, 0x01, 0x00, 0x00, 0x20, 0x1b, 0x00, 0x00, 0x94, 0xa2, 0x2a, - 0x94, 0xc5, 0xd2, 0xa8, 0xa1, 0x20, 0x17, 0x80, 0x4a, 0x05, 0x02, 0x81, 0x40, 0xa0, 0x00, 0x48, 0x42, 0x00, 0x00, - 0x84, 0x14, 0x00, 0x80, 0x18, 0x02, 0x00, 0x50, 0x08, 0x00, 0xc1, 0x40, 0x08, 0x00, 0x80, 0x30, 0x01, 0x00, 0xa0, - 0x00, 0x00, 0x20, 0x10, 0x01, 0x81, 0x60, 0x50}; + srsran::byte_buffer pdu = + srsran::byte_buffer::create( + {0xe1, 0xa0, 0x53, 0x80, 0x57, 0x4f, 0x7a, 0x03, 0x16, 0x00, 0x03, 0x06, 0x40, 0x02, 0xc1, 0x00, 0x10, + 0x18, 0x09, 0x31, 0x70, 0x01, 0x9c, 0x3d, 0x09, 0x00, 0x31, 0x20, 0xd0, 0x09, 0x80, 0x40, 0x62, 0x30, + 0x01, 0x50, 0x6c, 0x4d, 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x74, 0x82, 0x40, 0x51, 0x6c, 0xaa, 0x2a, + 0x12, 0x1c, 0xfa, 0x06, 0x7d, 0x81, 0x3e, 0x31, 0xcf, 0x98, 0x63, 0xca, 0x16, 0x07, 0x03, 0x87, 0x81, + 0x70, 0x01, 0xdf, 0x00, 0x1c, 0x00, 0x77, 0xc0, 0x01, 0x22, 0x00, 0x36, 0x50, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x12, 0x83, 0xc4, 0xd0, 0x00, 0xc2, 0x68, 0x00, 0x00, 0x20, 0x2e, 0x10, 0x71, 0x34, 0x00, 0x00, + 0x08, 0x78, 0x00, 0xc8, 0x0a, 0x14, 0x29, 0xdb, 0x2d, 0x78, 0xf0, 0x21, 0x6c, 0xb5, 0xe3, 0x8f, 0x41, + 0x28, 0x03, 0xe0, 0x03, 0x01, 0x01, 0x40, 0x18, 0x0c, 0x02, 0x50, 0x06, 0x00, 0x06, 0x03, 0xe0, 0x20, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x80, + 0x20, 0x00, 0x01, 0x00, 0x46, 0x50, 0xd6, 0x52, 0xd6, 0x4c, 0xde, 0x54, 0xd6, 0x46, 0xd0, 0x08, 0x10, + 0x00, 0x00, 0x01, 0xb0, 0x00, 0x40, 0x00, 0x04, 0x06, 0xc0, 0x01, 0x00, 0x00, 0x20, 0x1b, 0x00, 0x00, + 0x94, 0xa2, 0x2a, 0x94, 0xc5, 0xd2, 0xa8, 0xa1, 0x20, 0x17, 0x80, 0x4a, 0x05, 0x02, 0x81, 0x40, 0xa0, + 0x00, 0x48, 0x42, 0x00, 0x00, 0x84, 0x14, 0x00, 0x80, 0x18, 0x02, 0x00, 0x50, 0x08, 0x00, 0xc1, 0x40, + 0x08, 0x00, 0x80, 0x30, 0x01, 0x00, 0xa0, 0x00, 0x00, 0x20, 0x10, 0x01, 0x81, 0x60, 0x50}) + .value(); // e1a05380574f7a03160003064002c1001018093170019c3d09003120d0098040623001506c4dd608c21a0810748240516caa2a121cfa067d813e31cf9863ca16070387817001df001c0077c0012200365000050000001283c4d000c2680000202e1071340000087800c80a1429db2d78f0216cb5e38f412803e003010140180c025006000603e0200200000001000002008000020040000180200001004650d652d64cde54d646d00810000001b00040000406c0010000201b000094a22a94c5d2a8a12017804a05028140a0004842000084140080180200500800c140080080300100a00000201001816050 asn1::cbit_ref bref{pdu}; @@ -369,84 +374,91 @@ TEST_F(asn1_rrc_nr_test, when_ue_nr_capabilities_rel15_correct_then_unpacking_su TEST_F(asn1_rrc_nr_test, when_ue_nr_capabilities_rel16_correct_then_unpacking_successful) { // UE caps of a QC SM8450 Snapdragon 8 Gen 1 module with AS release set to 16 and also IE and fields up to Rel16 - srsran::byte_buffer pdu{ - 0xe1, 0xa2, 0x53, 0x80, 0x57, 0x4f, 0x7a, 0x03, 0x56, 0x08, 0x03, 0x04, 0x40, 0x0b, 0x04, 0x00, 0x40, 0x60, 0x24, - 0xc5, 0xc0, 0x06, 0x70, 0xf4, 0x1c, 0x01, 0x89, 0x06, 0x80, 0x4c, 0x02, 0x03, 0x11, 0x80, 0x82, 0x83, 0x61, 0x3e, - 0xb0, 0x46, 0x10, 0xd0, 0x40, 0x83, 0xa4, 0x0a, 0x0a, 0x2d, 0x95, 0x45, 0x42, 0x43, 0x9f, 0x40, 0xcf, 0xb0, 0x27, - 0xc6, 0x39, 0xf3, 0x0c, 0x79, 0x42, 0xc0, 0xe0, 0x70, 0xf0, 0x4e, 0x00, 0x3b, 0xe0, 0x03, 0x80, 0x0e, 0xf8, 0x01, - 0x50, 0x6c, 0x4d, 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x74, 0x81, 0x41, 0x45, 0xb2, 0xa8, 0xa8, 0x48, 0x73, 0xe8, - 0x19, 0xf6, 0x04, 0xf8, 0xc7, 0x3e, 0x61, 0x8f, 0x28, 0x58, 0x1c, 0x0e, 0x1e, 0x05, 0xc0, 0x07, 0x7c, 0x00, 0x70, - 0x01, 0xdf, 0x00, 0x03, 0x08, 0x06, 0xca, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x28, 0x36, 0x12, 0xeb, 0x04, 0x61, 0x0d, - 0x04, 0x08, 0x3a, 0x40, 0xa0, 0xa2, 0xd9, 0x54, 0x54, 0x24, 0x39, 0xf4, 0x0c, 0xfb, 0x02, 0x7c, 0x63, 0x9f, 0x30, - 0xc7, 0x94, 0x2c, 0x0e, 0x07, 0x0f, 0x04, 0xe0, 0x03, 0xb0, 0x00, 0x38, 0x00, 0xec, 0x00, 0x05, 0x07, 0xc1, 0xbd, - 0x60, 0x8c, 0x21, 0xa0, 0x81, 0x07, 0x88, 0x14, 0x12, 0x5b, 0x2a, 0x8a, 0x82, 0x87, 0x3e, 0x81, 0x9f, 0x18, 0xe7, - 0xcc, 0x31, 0xe5, 0x0b, 0x03, 0x81, 0xc3, 0xc0, 0x9f, 0xd0, 0x00, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0xa0, 0xf8, - 0x0f, 0xac, 0x11, 0x84, 0x34, 0x10, 0x20, 0xf1, 0x02, 0x82, 0x4b, 0x65, 0x51, 0x50, 0x50, 0xe7, 0xd0, 0x33, 0xe3, - 0x1c, 0xf9, 0x86, 0x3c, 0xa1, 0x60, 0x70, 0x38, 0x78, 0x13, 0xf8, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x14, - 0x1f, 0x01, 0xb5, 0x82, 0x30, 0x86, 0x82, 0x04, 0x1e, 0x20, 0x50, 0x49, 0x6c, 0xaa, 0x2a, 0x0a, 0x1c, 0xfa, 0x06, - 0x7c, 0x63, 0x9f, 0x30, 0xc7, 0x94, 0x2c, 0x0e, 0x07, 0x0f, 0x02, 0x7f, 0xf0, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, - 0x02, 0x83, 0xe0, 0x16, 0xb0, 0x46, 0x10, 0xd0, 0x40, 0x83, 0xc4, 0x0a, 0x09, 0x2d, 0x95, 0x45, 0x41, 0x43, 0x9f, - 0x40, 0xcf, 0x8c, 0x73, 0xe6, 0x18, 0xf2, 0x85, 0x81, 0xc0, 0xe1, 0xe0, 0x4f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0x80, - 0x00, 0x00, 0x50, 0x7c, 0x00, 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x78, 0x81, 0x41, 0x25, 0xb2, 0xa8, 0xa8, 0x28, - 0x73, 0xe8, 0x19, 0xf1, 0x8e, 0x7c, 0xc3, 0x1e, 0x50, 0xb0, 0x38, 0x1c, 0x3c, 0x09, 0xff, 0xc0, 0x00, 0x00, 0x7f, - 0xf0, 0x00, 0x00, 0x0a, 0x0f, 0x82, 0x7a, 0xc1, 0x18, 0x43, 0x41, 0x02, 0x0f, 0x10, 0x28, 0x24, 0xb6, 0x55, 0x15, - 0x05, 0x0e, 0x7d, 0x03, 0x3e, 0x31, 0xcf, 0x98, 0x63, 0xca, 0x16, 0x07, 0x03, 0x87, 0x81, 0x3f, 0x80, 0x00, 0x00, - 0x0f, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x82, 0x70, 0x38, 0x9a, 0x00, 0x00, 0x00, 0x11, 0x07, 0x84, 0xe0, 0x01, - 0x84, 0xd0, 0x00, 0x08, 0x23, 0x0e, 0x09, 0x40, 0xe2, 0x68, 0x00, 0x00, 0x20, 0xe2, 0x0f, 0x09, 0x40, 0x03, 0x09, - 0xa0, 0x00, 0x30, 0xeb, 0x0e, 0x06, 0xc0, 0xe2, 0x68, 0x00, 0x00, 0x40, 0x80, 0x75, 0x07, 0x83, 0x60, 0x01, 0x84, - 0xd0, 0x00, 0x28, 0x48, 0x3a, 0xc3, 0x80, 0x70, 0x38, 0x9a, 0x00, 0x00, 0x18, 0x20, 0x1d, 0x41, 0xe0, 0x38, 0x00, - 0x61, 0x34, 0x00, 0x0e, 0x12, 0x0e, 0xb0, 0xe0, 0x18, 0x0e, 0x26, 0x80, 0x00, 0x08, 0x08, 0x07, 0x50, 0x78, 0x0c, - 0x00, 0x18, 0x4d, 0x00, 0x04, 0x84, 0x83, 0xac, 0x38, 0x02, 0x03, 0x89, 0xa0, 0x00, 0x02, 0x82, 0x01, 0xd4, 0x1e, - 0x01, 0x00, 0x06, 0x13, 0x40, 0x01, 0x61, 0x20, 0xeb, 0x0e, 0x00, 0x00, 0xe2, 0x68, 0x00, 0x00, 0x80, 0x80, 0xba, - 0x83, 0xc0, 0x00, 0x00, 0xc2, 0x68, 0x00, 0x24, 0x24, 0x2e, 0xa1, 0x60, 0x00, 0x0c, 0x01, 0x01, 0xc1, 0xb0, 0x00, - 0x01, 0x81, 0x00, 0x54, 0x2c, 0x00, 0x01, 0xc0, 0x20, 0x00, 0xc0, 0xd8, 0x00, 0x34, 0x20, 0x0a, 0x85, 0xc0, 0x00, - 0x00, 0xc0, 0x10, 0x18, 0x1b, 0x00, 0x07, 0x04, 0x01, 0x50, 0x70, 0x04, 0x07, 0x06, 0xc0, 0x00, 0x07, 0x84, 0x01, - 0x50, 0x78, 0x04, 0x00, 0x18, 0x1b, 0x00, 0x08, 0x04, 0x01, 0x50, 0x70, 0x00, 0x07, 0x06, 0xc0, 0x00, 0x07, 0x84, - 0x01, 0x50, 0x78, 0x00, 0x00, 0x18, 0x1b, 0x00, 0x08, 0x04, 0x01, 0x00, 0x38, 0x26, 0x00, 0x00, 0x45, 0x41, 0xc0, - 0x10, 0x1c, 0x07, 0x00, 0x00, 0x24, 0x10, 0x05, 0x41, 0xe0, 0x10, 0x00, 0x60, 0x1c, 0x00, 0x26, 0x10, 0x05, 0x41, - 0xc0, 0x00, 0x1c, 0x07, 0x00, 0x00, 0x28, 0x10, 0x05, 0x41, 0xe0, 0x00, 0x00, 0x60, 0x1c, 0x00, 0x2a, 0x10, 0x05, - 0x42, 0xc0, 0x00, 0x18, 0x02, 0x03, 0x80, 0xc0, 0x00, 0x05, 0x82, 0x01, 0xd4, 0x2c, 0x00, 0x01, 0xc0, 0x20, 0x00, - 0xc0, 0x30, 0x00, 0x5c, 0x20, 0x1d, 0x42, 0xe0, 0x00, 0x00, 0x60, 0x08, 0x0c, 0x03, 0x00, 0x06, 0x02, 0x01, 0xd4, - 0x1c, 0x00, 0x01, 0xc0, 0x20, 0x00, 0x03, 0x21, 0x00, 0xea, 0x0f, 0x00, 0x00, 0x03, 0x00, 0x40, 0x01, 0xa0, 0x80, - 0x70, 0x94, 0x80, 0xb4, 0x87, 0xe1, 0x4e, 0x85, 0xb1, 0xcf, 0x87, 0x0a, 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x53, 0xa1, - 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe8, 0x5b, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, - 0xc3, 0x85, 0x3a, 0x16, 0xc7, 0x3e, 0x1c, 0x29, 0xd3, 0xb6, 0x39, 0xf0, 0xe1, 0x4e, 0x85, 0xb1, 0xcf, 0x87, 0x0a, - 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x53, 0xa1, 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe8, 0x5b, - 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x89, 0x3a, 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x93, 0xa7, 0x4e, 0xd8, - 0xe7, 0xc3, 0x89, 0x3a, 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x53, 0xa7, 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, 0x63, 0x9f, - 0x0e, 0x14, 0xe9, 0xdb, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x81, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe9, - 0xdb, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x85, 0x3a, 0x76, 0xc7, 0x3e, 0x1c, 0x29, 0xd3, 0xb6, 0x39, - 0xf0, 0xe2, 0x4e, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x24, 0xe9, 0xd3, 0xb6, 0x39, 0xf0, 0xe2, 0x4e, 0x9d, 0x3b, 0x63, - 0x9f, 0x0e, 0x14, 0xe9, 0xdb, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x15, 0x8f, 0x88, 0x42, 0x10, 0xc4, - 0x31, 0x0c, 0x43, 0x10, 0xc4, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0x08, 0x42, 0x10, 0x84, 0x20, 0xf4, 0x12, 0xa0, - 0x3e, 0x00, 0x30, 0x00, 0x70, 0x00, 0x00, 0x10, 0x14, 0x01, 0x80, 0xc0, 0x25, 0x00, 0x60, 0x00, 0x60, 0x3e, 0x05, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x18, 0x02, 0x00, - 0x00, 0x10, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x80, 0x00, 0x06, 0x00, 0x40, 0x00, 0x03, 0x80, 0x20, 0x00, 0x02, 0x00, - 0x10, 0x00, 0x01, 0x20, 0x08, 0x00, 0x00, 0xa0, 0x29, 0x94, 0xb7, 0x95, 0x35, 0x93, 0x35, 0x82, 0x95, 0x81, 0x95, - 0x83, 0x35, 0x82, 0xb5, 0x81, 0x35, 0x81, 0x15, 0x81, 0xb5, 0x80, 0xb4, 0x07, 0x04, 0x00, 0x00, 0x25, 0x94, 0x90, - 0x10, 0x00, 0x01, 0x96, 0x52, 0x40, 0x40, 0x00, 0x0a, 0x59, 0x49, 0x01, 0x00, 0x00, 0x39, 0x65, 0x24, 0x04, 0x00, - 0x01, 0x25, 0x94, 0x90, 0x10, 0x00, 0x05, 0x96, 0x52, 0x40, 0x40, 0x00, 0x1a, 0x59, 0x49, 0x01, 0x00, 0x00, 0x79, - 0x65, 0x24, 0x01, 0xf4, 0xaa, 0x2a, 0x94, 0xc5, 0x52, 0x68, 0xaa, 0x0b, 0x15, 0x40, 0xe2, 0xa8, 0x34, 0x55, 0x02, - 0x8a, 0xa0, 0x31, 0x41, 0xd0, 0xae, 0x02, 0xa8, 0x14, 0x0a, 0x07, 0x03, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, - 0x00, 0x0e, 0x84, 0x21, 0x08, 0x42, 0x10, 0x01, 0x22, 0x01, 0xc4, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x80, - 0x40, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, - 0x00, 0x20, 0x10, 0x00, 0x00, 0x08, 0x00, 0x34, 0x10, 0x10, 0x02, 0x00, 0x00, 0x40, 0x10, 0x01, 0x08, 0x08, 0x01, - 0x00, 0x40, 0x20, 0x08, 0x00, 0x04, 0x04, 0x01, 0x80, 0x00, 0x10, 0x04, 0x00, 0x42, 0x02, 0x00, 0xc0, 0x18, 0x08, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x04, 0x01, 0x00, 0x10, 0x80, 0x80, 0x40, 0x08, 0x02, 0x00, 0x80, 0x00, - 0x40, 0x40, 0x28, 0x00, 0x01, 0x00, 0x40, 0x04, 0x20, 0x20, 0x14, 0x02, 0x80, 0x80, 0x20, 0x00, 0x10, 0x10, 0x0c, - 0x00, 0x00, 0x40, 0x10, 0x01, 0x08, 0x08, 0x06, 0x00, 0xc0, 0x20, 0x08, 0x00, 0x04, 0x04, 0x03, 0x80, 0x00, 0x10, - 0x04, 0x00, 0x42, 0x02, 0x01, 0xc0, 0x20, 0x08, 0x02, 0x00, 0x02, 0x05, 0x01, 0x00, 0x02, 0x02, 0x80, 0x04, 0x04, - 0x00, 0x00, 0x50, 0x0e, 0x00, 0x20, 0x28, 0x00, 0x40, 0x40, 0x00, 0x05, 0x01, 0x20, 0x1e, 0x01, 0x40, 0x2c, 0x02, - 0x00, 0x41, 0x02, 0x80, 0x80, 0x01, 0x01, 0x40, 0x02, 0x02, 0x00, 0x00, 0x28, 0x07, 0x00, 0x90, 0x14, 0x01, 0x60, - 0x20, 0x03, 0x82, 0x80, 0x90, 0x01, 0x00, 0xa0, 0x02, 0x01, 0x00, 0x00, 0x81, 0x40, 0x40, 0x07, 0x80, 0xa0, 0x0b, - 0x01, 0x00, 0x1c, 0x14, 0x03, 0x80, 0x08, 0x0a, 0x00, 0x10, 0x10, 0x00, 0x01, 0x40, 0x48, 0x00, 0x80, 0x50, 0x01, - 0x00, 0x80, 0x00, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x80, 0x40, 0x08, 0x10, 0x10, 0x0e, 0x01, 0x00, 0x40, 0x20, 0x00, - 0x00, 0x08, 0x05, 0x00, 0xa1, 0x01, 0x00, 0xe0, 0x00, 0x04, 0x02, 0x80, 0x50, 0x80, 0x80, 0x70, 0x08, 0x02, 0x01, - 0x40, 0x00, 0x40, 0x40, 0x30, 0x00, 0x01, 0x00, 0xa0, 0x14, 0x20, 0x20, 0x18, 0x03, 0x00, 0x80, 0x50, 0x00, 0x20, - 0x10, 0x14, 0x00, 0x00, 0x40, 0x50, 0x00, 0x01, 0x01, 0x40, 0x14, 0x40, 0x20, 0x28, 0x00, 0x00, 0x80, 0xa0, 0x0a, - 0x02, 0x02, 0x80, 0x00, 0x80, 0x40, 0x50, 0x05, 0x01, 0x01, 0x40, 0x00, 0x04, 0x05, 0x00, 0x00, 0x81, 0x80, 0x60, - 0x01, 0x00, 0xe0, 0x00, 0x0c, 0x05, 0x80, 0x88, 0x07, 0x00, 0x81, 0x03, 0x00, 0xc0, 0x1a, 0x01, 0xc0, 0x20, 0x18, - 0x0b, 0x00, 0x10, 0x0e, 0x00, 0x00, 0xb1, 0x70, 0x14, 0x06, 0x01, 0x4a, 0x20, 0x20, 0x06, 0x73, 0x00}; + srsran::byte_buffer pdu = + srsran::byte_buffer::create( + {0xe1, 0xa2, 0x53, 0x80, 0x57, 0x4f, 0x7a, 0x03, 0x56, 0x08, 0x03, 0x04, 0x40, 0x0b, 0x04, 0x00, 0x40, 0x60, + 0x24, 0xc5, 0xc0, 0x06, 0x70, 0xf4, 0x1c, 0x01, 0x89, 0x06, 0x80, 0x4c, 0x02, 0x03, 0x11, 0x80, 0x82, 0x83, + 0x61, 0x3e, 0xb0, 0x46, 0x10, 0xd0, 0x40, 0x83, 0xa4, 0x0a, 0x0a, 0x2d, 0x95, 0x45, 0x42, 0x43, 0x9f, 0x40, + 0xcf, 0xb0, 0x27, 0xc6, 0x39, 0xf3, 0x0c, 0x79, 0x42, 0xc0, 0xe0, 0x70, 0xf0, 0x4e, 0x00, 0x3b, 0xe0, 0x03, + 0x80, 0x0e, 0xf8, 0x01, 0x50, 0x6c, 0x4d, 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x74, 0x81, 0x41, 0x45, 0xb2, + 0xa8, 0xa8, 0x48, 0x73, 0xe8, 0x19, 0xf6, 0x04, 0xf8, 0xc7, 0x3e, 0x61, 0x8f, 0x28, 0x58, 0x1c, 0x0e, 0x1e, + 0x05, 0xc0, 0x07, 0x7c, 0x00, 0x70, 0x01, 0xdf, 0x00, 0x03, 0x08, 0x06, 0xca, 0x00, 0x00, 0xa0, 0x00, 0x00, + 0x28, 0x36, 0x12, 0xeb, 0x04, 0x61, 0x0d, 0x04, 0x08, 0x3a, 0x40, 0xa0, 0xa2, 0xd9, 0x54, 0x54, 0x24, 0x39, + 0xf4, 0x0c, 0xfb, 0x02, 0x7c, 0x63, 0x9f, 0x30, 0xc7, 0x94, 0x2c, 0x0e, 0x07, 0x0f, 0x04, 0xe0, 0x03, 0xb0, + 0x00, 0x38, 0x00, 0xec, 0x00, 0x05, 0x07, 0xc1, 0xbd, 0x60, 0x8c, 0x21, 0xa0, 0x81, 0x07, 0x88, 0x14, 0x12, + 0x5b, 0x2a, 0x8a, 0x82, 0x87, 0x3e, 0x81, 0x9f, 0x18, 0xe7, 0xcc, 0x31, 0xe5, 0x0b, 0x03, 0x81, 0xc3, 0xc0, + 0x9f, 0xd0, 0x00, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x00, 0xa0, 0xf8, 0x0f, 0xac, 0x11, 0x84, 0x34, 0x10, 0x20, + 0xf1, 0x02, 0x82, 0x4b, 0x65, 0x51, 0x50, 0x50, 0xe7, 0xd0, 0x33, 0xe3, 0x1c, 0xf9, 0x86, 0x3c, 0xa1, 0x60, + 0x70, 0x38, 0x78, 0x13, 0xf8, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x14, 0x1f, 0x01, 0xb5, 0x82, 0x30, + 0x86, 0x82, 0x04, 0x1e, 0x20, 0x50, 0x49, 0x6c, 0xaa, 0x2a, 0x0a, 0x1c, 0xfa, 0x06, 0x7c, 0x63, 0x9f, 0x30, + 0xc7, 0x94, 0x2c, 0x0e, 0x07, 0x0f, 0x02, 0x7f, 0xf0, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x02, 0x83, 0xe0, + 0x16, 0xb0, 0x46, 0x10, 0xd0, 0x40, 0x83, 0xc4, 0x0a, 0x09, 0x2d, 0x95, 0x45, 0x41, 0x43, 0x9f, 0x40, 0xcf, + 0x8c, 0x73, 0xe6, 0x18, 0xf2, 0x85, 0x81, 0xc0, 0xe1, 0xe0, 0x4f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, + 0x00, 0x50, 0x7c, 0x00, 0xd6, 0x08, 0xc2, 0x1a, 0x08, 0x10, 0x78, 0x81, 0x41, 0x25, 0xb2, 0xa8, 0xa8, 0x28, + 0x73, 0xe8, 0x19, 0xf1, 0x8e, 0x7c, 0xc3, 0x1e, 0x50, 0xb0, 0x38, 0x1c, 0x3c, 0x09, 0xff, 0xc0, 0x00, 0x00, + 0x7f, 0xf0, 0x00, 0x00, 0x0a, 0x0f, 0x82, 0x7a, 0xc1, 0x18, 0x43, 0x41, 0x02, 0x0f, 0x10, 0x28, 0x24, 0xb6, + 0x55, 0x15, 0x05, 0x0e, 0x7d, 0x03, 0x3e, 0x31, 0xcf, 0x98, 0x63, 0xca, 0x16, 0x07, 0x03, 0x87, 0x81, 0x3f, + 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x82, 0x70, 0x38, 0x9a, 0x00, 0x00, 0x00, 0x11, + 0x07, 0x84, 0xe0, 0x01, 0x84, 0xd0, 0x00, 0x08, 0x23, 0x0e, 0x09, 0x40, 0xe2, 0x68, 0x00, 0x00, 0x20, 0xe2, + 0x0f, 0x09, 0x40, 0x03, 0x09, 0xa0, 0x00, 0x30, 0xeb, 0x0e, 0x06, 0xc0, 0xe2, 0x68, 0x00, 0x00, 0x40, 0x80, + 0x75, 0x07, 0x83, 0x60, 0x01, 0x84, 0xd0, 0x00, 0x28, 0x48, 0x3a, 0xc3, 0x80, 0x70, 0x38, 0x9a, 0x00, 0x00, + 0x18, 0x20, 0x1d, 0x41, 0xe0, 0x38, 0x00, 0x61, 0x34, 0x00, 0x0e, 0x12, 0x0e, 0xb0, 0xe0, 0x18, 0x0e, 0x26, + 0x80, 0x00, 0x08, 0x08, 0x07, 0x50, 0x78, 0x0c, 0x00, 0x18, 0x4d, 0x00, 0x04, 0x84, 0x83, 0xac, 0x38, 0x02, + 0x03, 0x89, 0xa0, 0x00, 0x02, 0x82, 0x01, 0xd4, 0x1e, 0x01, 0x00, 0x06, 0x13, 0x40, 0x01, 0x61, 0x20, 0xeb, + 0x0e, 0x00, 0x00, 0xe2, 0x68, 0x00, 0x00, 0x80, 0x80, 0xba, 0x83, 0xc0, 0x00, 0x00, 0xc2, 0x68, 0x00, 0x24, + 0x24, 0x2e, 0xa1, 0x60, 0x00, 0x0c, 0x01, 0x01, 0xc1, 0xb0, 0x00, 0x01, 0x81, 0x00, 0x54, 0x2c, 0x00, 0x01, + 0xc0, 0x20, 0x00, 0xc0, 0xd8, 0x00, 0x34, 0x20, 0x0a, 0x85, 0xc0, 0x00, 0x00, 0xc0, 0x10, 0x18, 0x1b, 0x00, + 0x07, 0x04, 0x01, 0x50, 0x70, 0x04, 0x07, 0x06, 0xc0, 0x00, 0x07, 0x84, 0x01, 0x50, 0x78, 0x04, 0x00, 0x18, + 0x1b, 0x00, 0x08, 0x04, 0x01, 0x50, 0x70, 0x00, 0x07, 0x06, 0xc0, 0x00, 0x07, 0x84, 0x01, 0x50, 0x78, 0x00, + 0x00, 0x18, 0x1b, 0x00, 0x08, 0x04, 0x01, 0x00, 0x38, 0x26, 0x00, 0x00, 0x45, 0x41, 0xc0, 0x10, 0x1c, 0x07, + 0x00, 0x00, 0x24, 0x10, 0x05, 0x41, 0xe0, 0x10, 0x00, 0x60, 0x1c, 0x00, 0x26, 0x10, 0x05, 0x41, 0xc0, 0x00, + 0x1c, 0x07, 0x00, 0x00, 0x28, 0x10, 0x05, 0x41, 0xe0, 0x00, 0x00, 0x60, 0x1c, 0x00, 0x2a, 0x10, 0x05, 0x42, + 0xc0, 0x00, 0x18, 0x02, 0x03, 0x80, 0xc0, 0x00, 0x05, 0x82, 0x01, 0xd4, 0x2c, 0x00, 0x01, 0xc0, 0x20, 0x00, + 0xc0, 0x30, 0x00, 0x5c, 0x20, 0x1d, 0x42, 0xe0, 0x00, 0x00, 0x60, 0x08, 0x0c, 0x03, 0x00, 0x06, 0x02, 0x01, + 0xd4, 0x1c, 0x00, 0x01, 0xc0, 0x20, 0x00, 0x03, 0x21, 0x00, 0xea, 0x0f, 0x00, 0x00, 0x03, 0x00, 0x40, 0x01, + 0xa0, 0x80, 0x70, 0x94, 0x80, 0xb4, 0x87, 0xe1, 0x4e, 0x85, 0xb1, 0xcf, 0x87, 0x0a, 0x74, 0xed, 0x8e, 0x7c, + 0x38, 0x53, 0xa1, 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe8, 0x5b, 0x1c, 0xf8, 0x70, + 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x85, 0x3a, 0x16, 0xc7, 0x3e, 0x1c, 0x29, 0xd3, 0xb6, 0x39, 0xf0, 0xe1, 0x4e, + 0x85, 0xb1, 0xcf, 0x87, 0x0a, 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x53, 0xa1, 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, + 0x63, 0x9f, 0x0e, 0x14, 0xe8, 0x5b, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x89, 0x3a, 0x74, 0xed, + 0x8e, 0x7c, 0x38, 0x93, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x89, 0x3a, 0x74, 0xed, 0x8e, 0x7c, 0x38, 0x53, 0xa7, + 0x6c, 0x73, 0xe1, 0xc2, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe9, 0xdb, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, + 0xe7, 0xc3, 0x81, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe9, 0xdb, 0x1c, 0xf8, 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, + 0x85, 0x3a, 0x76, 0xc7, 0x3e, 0x1c, 0x29, 0xd3, 0xb6, 0x39, 0xf0, 0xe2, 0x4e, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, + 0x24, 0xe9, 0xd3, 0xb6, 0x39, 0xf0, 0xe2, 0x4e, 0x9d, 0x3b, 0x63, 0x9f, 0x0e, 0x14, 0xe9, 0xdb, 0x1c, 0xf8, + 0x70, 0xa7, 0x4e, 0xd8, 0xe7, 0xc3, 0x15, 0x8f, 0x88, 0x42, 0x10, 0xc4, 0x31, 0x0c, 0x43, 0x10, 0xc4, 0x21, + 0x08, 0x42, 0x10, 0x84, 0x21, 0x08, 0x42, 0x10, 0x84, 0x20, 0xf4, 0x12, 0xa0, 0x3e, 0x00, 0x30, 0x00, 0x70, + 0x00, 0x00, 0x10, 0x14, 0x01, 0x80, 0xc0, 0x25, 0x00, 0x60, 0x00, 0x60, 0x3e, 0x05, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x10, 0x01, + 0x00, 0x00, 0x0a, 0x00, 0x80, 0x00, 0x06, 0x00, 0x40, 0x00, 0x03, 0x80, 0x20, 0x00, 0x02, 0x00, 0x10, 0x00, + 0x01, 0x20, 0x08, 0x00, 0x00, 0xa0, 0x29, 0x94, 0xb7, 0x95, 0x35, 0x93, 0x35, 0x82, 0x95, 0x81, 0x95, 0x83, + 0x35, 0x82, 0xb5, 0x81, 0x35, 0x81, 0x15, 0x81, 0xb5, 0x80, 0xb4, 0x07, 0x04, 0x00, 0x00, 0x25, 0x94, 0x90, + 0x10, 0x00, 0x01, 0x96, 0x52, 0x40, 0x40, 0x00, 0x0a, 0x59, 0x49, 0x01, 0x00, 0x00, 0x39, 0x65, 0x24, 0x04, + 0x00, 0x01, 0x25, 0x94, 0x90, 0x10, 0x00, 0x05, 0x96, 0x52, 0x40, 0x40, 0x00, 0x1a, 0x59, 0x49, 0x01, 0x00, + 0x00, 0x79, 0x65, 0x24, 0x01, 0xf4, 0xaa, 0x2a, 0x94, 0xc5, 0x52, 0x68, 0xaa, 0x0b, 0x15, 0x40, 0xe2, 0xa8, + 0x34, 0x55, 0x02, 0x8a, 0xa0, 0x31, 0x41, 0xd0, 0xae, 0x02, 0xa8, 0x14, 0x0a, 0x07, 0x03, 0x81, 0xc0, 0xe0, + 0x70, 0x38, 0x1c, 0x0e, 0x00, 0x0e, 0x84, 0x21, 0x08, 0x42, 0x10, 0x01, 0x22, 0x01, 0xc4, 0x00, 0x00, 0x02, + 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x08, 0x00, 0x34, 0x10, 0x10, 0x02, 0x00, + 0x00, 0x40, 0x10, 0x01, 0x08, 0x08, 0x01, 0x00, 0x40, 0x20, 0x08, 0x00, 0x04, 0x04, 0x01, 0x80, 0x00, 0x10, + 0x04, 0x00, 0x42, 0x02, 0x00, 0xc0, 0x18, 0x08, 0x02, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x04, 0x01, 0x00, + 0x10, 0x80, 0x80, 0x40, 0x08, 0x02, 0x00, 0x80, 0x00, 0x40, 0x40, 0x28, 0x00, 0x01, 0x00, 0x40, 0x04, 0x20, + 0x20, 0x14, 0x02, 0x80, 0x80, 0x20, 0x00, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x40, 0x10, 0x01, 0x08, 0x08, 0x06, + 0x00, 0xc0, 0x20, 0x08, 0x00, 0x04, 0x04, 0x03, 0x80, 0x00, 0x10, 0x04, 0x00, 0x42, 0x02, 0x01, 0xc0, 0x20, + 0x08, 0x02, 0x00, 0x02, 0x05, 0x01, 0x00, 0x02, 0x02, 0x80, 0x04, 0x04, 0x00, 0x00, 0x50, 0x0e, 0x00, 0x20, + 0x28, 0x00, 0x40, 0x40, 0x00, 0x05, 0x01, 0x20, 0x1e, 0x01, 0x40, 0x2c, 0x02, 0x00, 0x41, 0x02, 0x80, 0x80, + 0x01, 0x01, 0x40, 0x02, 0x02, 0x00, 0x00, 0x28, 0x07, 0x00, 0x90, 0x14, 0x01, 0x60, 0x20, 0x03, 0x82, 0x80, + 0x90, 0x01, 0x00, 0xa0, 0x02, 0x01, 0x00, 0x00, 0x81, 0x40, 0x40, 0x07, 0x80, 0xa0, 0x0b, 0x01, 0x00, 0x1c, + 0x14, 0x03, 0x80, 0x08, 0x0a, 0x00, 0x10, 0x10, 0x00, 0x01, 0x40, 0x48, 0x00, 0x80, 0x50, 0x01, 0x00, 0x80, + 0x00, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x80, 0x40, 0x08, 0x10, 0x10, 0x0e, 0x01, 0x00, 0x40, 0x20, 0x00, 0x00, + 0x08, 0x05, 0x00, 0xa1, 0x01, 0x00, 0xe0, 0x00, 0x04, 0x02, 0x80, 0x50, 0x80, 0x80, 0x70, 0x08, 0x02, 0x01, + 0x40, 0x00, 0x40, 0x40, 0x30, 0x00, 0x01, 0x00, 0xa0, 0x14, 0x20, 0x20, 0x18, 0x03, 0x00, 0x80, 0x50, 0x00, + 0x20, 0x10, 0x14, 0x00, 0x00, 0x40, 0x50, 0x00, 0x01, 0x01, 0x40, 0x14, 0x40, 0x20, 0x28, 0x00, 0x00, 0x80, + 0xa0, 0x0a, 0x02, 0x02, 0x80, 0x00, 0x80, 0x40, 0x50, 0x05, 0x01, 0x01, 0x40, 0x00, 0x04, 0x05, 0x00, 0x00, + 0x81, 0x80, 0x60, 0x01, 0x00, 0xe0, 0x00, 0x0c, 0x05, 0x80, 0x88, 0x07, 0x00, 0x81, 0x03, 0x00, 0xc0, 0x1a, + 0x01, 0xc0, 0x20, 0x18, 0x0b, 0x00, 0x10, 0x0e, 0x00, 0x00, 0xb1, 0x70, 0x14, 0x06, 0x01, 0x4a, 0x20, 0x20, + 0x06, 0x73, 0x00}) + .value(); // e1a25380574f7a0356080304400b0400406024c5c00670f41c018906804c020311808283613eb04610d04083a40a0a2d954542439f40cfb027c639f30c7942c0e070f04e003be003800ef801506c4dd608c21a081074814145b2a8a84873e819f604f8c73e618f28581c0e1e05c0077c007001df00030806ca0000a00000283612eb04610d04083a40a0a2d954542439f40cfb027c639f30c7942c0e070f04e003b0003800ec000507c1bd608c21a081078814125b2a8a82873e819f18e7cc31e50b0381c3c09fd0000007f4000000a0f80fac1184341020f102824b65515050e7d033e31cf9863ca16070387813f8000000fe000000141f01b582308682041e2050496caa2a0a1cfa067c639f30c7942c0e070f027ff000001ffc00000283e016b04610d04083c40a092d954541439f40cf8c73e618f28581c0e1e04ffe000003ff800000507c00d608c21a081078814125b2a8a82873e819f18e7cc31e50b0381c3c09ffc000007ff000000a0f827ac1184341020f102824b65515050e7d033e31cf9863ca16070387813f8000000fe0000000f8c38270389a000000110784e00184d00008230e0940e268000020e20f09400309a00030eb0e06c0e26800004080750783600184d00028483ac38070389a000018201d41e038006134000e120eb0e0180e26800008080750780c00184d00048483ac38020389a000028201d41e0100061340016120eb0e0000e26800008080ba83c00000c2680024242ea160000c0101c1b000018100542c0001c02000c0d80034200a85c00000c010181b000704015070040706c00007840150780400181b000804015070000706c00007840150780000181b0008040100382600004541c0101c07000024100541e01000601c0026100541c0001c07000028100541e00000601c002a100542c00018020380c000058201d42c0001c02000c030005c201d42e0000060080c0300060201d41c0001c02000032100ea0f000003004001a080709480b487e14e85b1cf870a74ed8e7c3853a16c73e1c29d3b639f0e14e85b1cf870a74ed8e7c3853a16c73e1c29d3b639f0e14e85b1cf870a74ed8e7c3853a16c73e1c29d3b639f0e14e85b1cf870a74ed8e7c3893a74ed8e7c3893a74ed8e7c3893a74ed8e7c3853a76c73e1c29d3b639f0e14e9db1cf870a74ed8e7c3813b639f0e14e9db1cf870a74ed8e7c3853a76c73e1c29d3b639f0e24e9d3b639f0e24e9d3b639f0e24e9d3b639f0e14e9db1cf870a74ed8e7c3158f884210c4310c4310c42108421084210842108420f412a03e00300070000010140180c025006000603e050020000000100000200800002004000018020000100100000a0080000600400003802000020010000120080000a02994b79535933582958195833582b58135811581b580b40704000025949010000196524040000a594901000039652404000125949010000596524040001a594901000079652401f4aa2a94c55268aa0b1540e2a83455028aa03141d0ae02a8140a070381c0e070381c0e000e8421084210012201c40000020100000080400000201000000804000002010000008040000020100000080034101002000040100108080100402008000404018000100400420200c01808020001010080000401001080804008020080004040280001004004202014028080200010100c000040100108080600c02008000404038000100400420201c0200802000205010002028004040000500e002028004040000501201e01402c020041028080010140020200002807009014016020038280900100a0020100008140400780a00b01001c140380080a001010000140480080500100800020201c000080400810100e010040200000080500a10100e000040280508080700802014000404030000100a0142020180300805000201014000040500001014014402028000080a00a020280008040500501014000040500008180600100e0000c0580880700810300c01a01c020180b00100e0000b1701406014a2020067300 asn1::cbit_ref bref{pdu}; diff --git a/tests/unittests/asn1/asn1_utils_test.cpp b/tests/unittests/asn1/asn1_utils_test.cpp index cf85ff0285..14a5bef611 100644 --- a/tests/unittests/asn1/asn1_utils_test.cpp +++ b/tests/unittests/asn1/asn1_utils_test.cpp @@ -197,7 +197,7 @@ TEST(asn1_bit_ref, pack_unpack_operators) // test advance bits { - srsran::byte_buffer buf{std::vector(256)}; + srsran::byte_buffer buf = byte_buffer::create(std::vector(256)).value(); cbit_ref bref(buf); ASSERT_EQ(SRSASN_SUCCESS, bref.advance_bits(4)); ASSERT_EQ(4, bref.distance()); diff --git a/tests/unittests/cu_cp/du_processor_test_messages.cpp b/tests/unittests/cu_cp/du_processor_test_messages.cpp index 09410ac03d..5dc3234a80 100644 --- a/tests/unittests/cu_cp/du_processor_test_messages.cpp +++ b/tests/unittests/cu_cp/du_processor_test_messages.cpp @@ -100,7 +100,7 @@ srsran::srs_cu_cp::generate_ue_rrc_context_creation_request(ue_index_t ue_index, "5c00b001117aec701061e0007c20408d07810020a2090480ca8000f800000000008370842000088165000048200002069a06aa49880002" "00204000400d008013b64b1814400e468acf120000096070820f177e060870000000e25038000040bde802000400000000028201950300" "c400"); - req.du_to_cu_rrc_container = {tmp.begin(), tmp.end()}; + req.du_to_cu_rrc_container = byte_buffer::create(tmp.begin(), tmp.end()).value(); return req; } diff --git a/tests/unittests/cu_up/cu_up_test.cpp b/tests/unittests/cu_up/cu_up_test.cpp index 30a4d63ef1..adfa45d602 100644 --- a/tests/unittests/cu_up/cu_up_test.cpp +++ b/tests/unittests/cu_up/cu_up_test.cpp @@ -290,9 +290,9 @@ TEST_F(cu_up_test, ul_data_flow) 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}; span t_pdu_span1 = {t_pdu_arr1}; - byte_buffer t_pdu_buf1 = {t_pdu_span1}; + byte_buffer t_pdu_buf1 = byte_buffer::create(t_pdu_span1).value(); nru_ul_message nru_msg1 = {}; - nru_msg1.t_pdu = byte_buffer_chain{std::move(t_pdu_buf1)}; + nru_msg1.t_pdu = byte_buffer_chain::create(std::move(t_pdu_buf1)).value(); f1u_bearer.handle_pdu(std::move(nru_msg1)); // send message 2 @@ -303,9 +303,9 @@ TEST_F(cu_up_test, ul_data_flow) 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}; span t_pdu_span2 = {t_pdu_arr2}; - byte_buffer t_pdu_buf2 = {t_pdu_span2}; + byte_buffer t_pdu_buf2 = byte_buffer::create(t_pdu_span2).value(); nru_ul_message nru_msg2 = {}; - nru_msg2.t_pdu = byte_buffer_chain{std::move(t_pdu_buf2)}; + nru_msg2.t_pdu = byte_buffer_chain::create(std::move(t_pdu_buf2)).value(); f1u_bearer.handle_pdu(std::move(nru_msg2)); std::array rx_buf; diff --git a/tests/unittests/cu_up/cu_up_test_helpers.h b/tests/unittests/cu_up/cu_up_test_helpers.h index 09f513baa9..1090d7dfb5 100644 --- a/tests/unittests/cu_up/cu_up_test_helpers.h +++ b/tests/unittests/cu_up/cu_up_test_helpers.h @@ -41,49 +41,37 @@ constexpr auto default_wait_timeout = std::chrono::seconds(3); namespace srsran { /// Dummy CU-UP executor pool used for testing -class dummy_cu_up_executor_pool final : public cu_up_executor_pool +class dummy_cu_up_executor_pool final : public srs_cu_up::cu_up_executor_pool { -public: - dummy_cu_up_executor_pool(task_executor* test_executor_) : test_executor(test_executor_) {} - using ptr = std::unique_ptr>; - - ptr create_ul_pdu_executor() override + class dummy_pdu_session_executor_mapper_impl : public srs_cu_up::ue_executor_mapper { - return {test_executor, [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } + public: + dummy_pdu_session_executor_mapper_impl(task_executor& exec_) : exec(&exec_) {} + + task_executor& ctrl_executor() override { return *exec; } + task_executor& ul_pdu_executor() override { return *exec; } + task_executor& dl_pdu_executor() override { return *exec; } + + async_task stop() override + { + return launch_async([](coro_context>& ctx) { + CORO_BEGIN(ctx); + CORO_RETURN(); + }); + } - ptr create_dl_pdu_executor() override - { - return {test_executor, [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } + task_executor* exec; + }; - ptr create_ctrl_executor() override - { - return {test_executor, [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } +public: + dummy_cu_up_executor_pool(task_executor* test_executor_) : test_executor(test_executor_) {} -private: - void dealloc_pdu_executor(task_executor* exec) + std::unique_ptr create_ue_executor_mapper() override { - // do nothing. - } - void dealloc_ctrl_executor(task_executor* exec) - { - // do nothing. + return std::make_unique(*test_executor); } +private: task_executor* test_executor; }; @@ -170,7 +158,7 @@ class dummy_inner_f1u_bearer final : public srs_cu_up::f1u_bearer, { // Forward T-PDU to PDCP srsran_assert(rx_sdu_notifier != nullptr, "The rx_sdu_notifier must not be a nullptr!"); - rx_sdu_notifier->on_new_sdu(std::move(msg.t_pdu)); + rx_sdu_notifier->on_new_sdu(std::move(msg.t_pdu.value())); } void discard_sdu(uint32_t pdcp_sn) final { tx_discard_sdu_list.push_back(pdcp_sn); }; diff --git a/tests/unittests/du_manager/du_manager_test_helpers.h b/tests/unittests/du_manager/du_manager_test_helpers.h index cd0def86ad..718dd2dd27 100644 --- a/tests/unittests/du_manager/du_manager_test_helpers.h +++ b/tests/unittests/du_manager/du_manager_test_helpers.h @@ -78,7 +78,7 @@ class dummy_f1c_bearer : public f1c_bearer { public: byte_buffer last_rx_pdu; - byte_buffer_chain last_tx_sdu; + byte_buffer_chain last_tx_sdu = byte_buffer_chain::create().value(); void handle_pdu(byte_buffer pdu) override { last_rx_pdu = std::move(pdu); } void handle_sdu(byte_buffer_chain sdu) override { last_tx_sdu = std::move(sdu); } @@ -192,7 +192,7 @@ class f1u_bearer_dummy : public f1u_bearer, optional last_pdu; optional last_highest_transmitted_pdcp_sn; optional last_highest_delivered_pdcp_sn; - byte_buffer_chain last_sdu; + byte_buffer_chain last_sdu = byte_buffer_chain::create().value(); f1u_bearer_dummy(srs_du::f1u_rx_sdu_notifier& du_rx_) : du_rx(du_rx_) {} diff --git a/tests/unittests/du_manager/du_ue/du_bearer_test.cpp b/tests/unittests/du_manager/du_ue/du_bearer_test.cpp index fce79d82bd..1361ae0abe 100644 --- a/tests/unittests/du_manager/du_ue/du_bearer_test.cpp +++ b/tests/unittests/du_manager/du_ue/du_bearer_test.cpp @@ -62,7 +62,9 @@ std::unique_ptr create_dummy_drb(drb_id_t drb_id, lcid_t lcid) ul_tnls, teid_pool, du_mng->params, - rlf_notifier); + rlf_notifier, + qos_characteristics{}, + nullopt); } TEST(du_ue_bearer_manager_test, when_no_drbs_allocated_lcid_is_min) diff --git a/tests/unittests/du_manager/du_ue/ue_manager_test.cpp b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp index d22966bfc8..7b14162073 100644 --- a/tests/unittests/du_manager/du_ue/ue_manager_test.cpp +++ b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp @@ -54,7 +54,7 @@ class du_ue_manager_tester : public ::testing::Test ul_ccch_indication_message ccch_ind{}; ccch_ind.cell_index = to_du_cell_index(0); ccch_ind.tc_rnti = rnti; - ccch_ind.subpdu = {0, 1, 2, 3, 4, 5}; + ccch_ind.subpdu = byte_buffer::create({0, 1, 2, 3, 4, 5}).value(); return ccch_ind; } diff --git a/tests/unittests/du_manager/procedures/du_manager_procedure_test_helpers.cpp b/tests/unittests/du_manager/procedures/du_manager_procedure_test_helpers.cpp index 290c40c219..e1d49f37e9 100644 --- a/tests/unittests/du_manager/procedures/du_manager_procedure_test_helpers.cpp +++ b/tests/unittests/du_manager/procedures/du_manager_procedure_test_helpers.cpp @@ -35,7 +35,7 @@ ul_ccch_indication_message srsran::srs_du::create_test_ul_ccch_message(rnti_t rn ul_ccch_msg.cell_index = to_du_cell_index(0); ul_ccch_msg.tc_rnti = rnti; ul_ccch_msg.slot_rx = {0, test_rgen::uniform_int(0, 10239)}; - ul_ccch_msg.subpdu = test_rgen::random_vector(6); + ul_ccch_msg.subpdu = byte_buffer::create(test_rgen::random_vector(6)).value(); return ul_ccch_msg; } diff --git a/tests/unittests/du_manager/procedures/ue_configuration_test.cpp b/tests/unittests/du_manager/procedures/ue_configuration_test.cpp index d9733f54d7..3d674d0327 100644 --- a/tests/unittests/du_manager/procedures/ue_configuration_test.cpp +++ b/tests/unittests/du_manager/procedures/ue_configuration_test.cpp @@ -200,14 +200,15 @@ TEST_F(ue_config_tester, when_du_manager_completes_ue_configuration_procedure_th TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_then_mac_rlc_f1c_bearers_are_connected) { const static std::array dummy_rlc_header = {0x80, 0x0}; - byte_buffer test_payload{test_rgen::random_vector(test_rgen::uniform_int(1, 100))}; + byte_buffer test_payload = + byte_buffer::create({test_rgen::random_vector(test_rgen::uniform_int(1, 100))}).value(); // Run UE Configuration Procedure to completion. configure_ue(create_f1ap_ue_context_update_request(test_ue->ue_index, {srb_id_t::srb2}, {})); // Forward MAC Rx SDU through SRB2 (UL). // > Add dummy RLC data header. - byte_buffer mac_rx_sdu(dummy_rlc_header); + byte_buffer mac_rx_sdu = byte_buffer::create(dummy_rlc_header).value(); // > Append data buffer. ASSERT_TRUE(mac_rx_sdu.append(test_payload.copy())); // > Push MAC Rx SDU through MAC logical channel. @@ -223,7 +224,8 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t // > Check arrival of MAC Tx SDU to MAC logical channel. std::vector mac_tx_sdu(test_payload.length() + dummy_rlc_header.size()); size_t nwritten = mac.last_ue_reconf_msg->bearers_to_addmod[0].dl_bearer->on_new_tx_sdu(mac_tx_sdu); - byte_buffer extracted_payload(mac_tx_sdu.begin() + dummy_rlc_header.size(), mac_tx_sdu.begin() + nwritten); + byte_buffer extracted_payload = + byte_buffer::create(mac_tx_sdu.begin() + dummy_rlc_header.size(), mac_tx_sdu.begin() + nwritten).value(); ASSERT_EQ(test_payload, extracted_payload) << fmt::format("Byte buffers do not match:\n{}\n{}\n", test_payload, extracted_payload); } @@ -231,7 +233,8 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_then_mac_rlc_f1u_bearers_are_connected) { const static std::array dummy_rlc_header = {0x80, 0x0}; - byte_buffer test_payload{test_rgen::random_vector(test_rgen::uniform_int(1, 100))}; + byte_buffer test_payload = + byte_buffer::create(test_rgen::random_vector(test_rgen::uniform_int(1, 100))).value(); // Run UE Configuration Procedure to completion. configure_ue(create_f1ap_ue_context_update_request(test_ue->ue_index, {}, {drb_id_t::drb1})); @@ -239,7 +242,7 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t // Forward MAC Rx SDU through DRB1 (UL). // > Add dummy RLC data header. - byte_buffer mac_sdu(dummy_rlc_header); + byte_buffer mac_sdu = byte_buffer::create(dummy_rlc_header).value(); // > Append data buffer. ASSERT_TRUE(mac_sdu.append(test_payload.copy())); // > Push MAC Rx SDU through MAC logical channel. @@ -257,7 +260,8 @@ TEST_F(ue_config_tester, when_du_manager_finishes_processing_ue_config_request_t // > Check arrival of MAC Tx SDU to MAC logical channel. std::vector mac_tx_sdu(test_payload.length() + dummy_rlc_header.size()); unsigned nwritten = mac.last_ue_reconf_msg->bearers_to_addmod[0].dl_bearer->on_new_tx_sdu(mac_tx_sdu); - byte_buffer extracted_payload(mac_tx_sdu.begin() + dummy_rlc_header.size(), mac_tx_sdu.begin() + nwritten); + byte_buffer extracted_payload = + byte_buffer::create(mac_tx_sdu.begin() + dummy_rlc_header.size(), mac_tx_sdu.begin() + nwritten).value(); ASSERT_EQ(test_payload, extracted_payload); } diff --git a/tests/unittests/e2/e2_setup_procedure_test.cpp b/tests/unittests/e2/e2_setup_procedure_test.cpp index 5f105c5b4b..458fcb4740 100644 --- a/tests/unittests/e2/e2_setup_procedure_test.cpp +++ b/tests/unittests/e2/e2_setup_procedure_test.cpp @@ -243,10 +243,10 @@ TEST_F(e2_external_test, correctly_unpack_e2_response) ASSERT_EQ(msg_notifier->last_e2_msg.pdu.init_msg().value.type().value, asn1::e2ap::e2_ap_elem_procs_o::init_msg_c::types_opts::e2setup_request); - uint8_t e2_resp[] = {0x20, 0x01, 0x00, 0x38, 0x00, 0x00, 0x04, 0x00, 0x31, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x07, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x90, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, - 0x06, 0x40, 0x05, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x34, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x35, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x6e, 0x67, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x00}; - byte_buffer e2_resp_buf(e2_resp, e2_resp + sizeof(e2_resp)); + uint8_t e2_resp[] = {0x20, 0x01, 0x00, 0x38, 0x00, 0x00, 0x04, 0x00, 0x31, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x07, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x90, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, + 0x06, 0x40, 0x05, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x34, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x35, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x6e, 0x67, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x00}; + byte_buffer e2_resp_buf = byte_buffer::create(e2_resp, e2_resp + sizeof(e2_resp)).value(); packer->handle_packed_pdu(std::move(e2_resp_buf)); -} \ No newline at end of file +} diff --git a/tests/unittests/e2/e2_subscription_setup_test.cpp b/tests/unittests/e2/e2_subscription_setup_test.cpp index 912e922eb5..d719f0f5c0 100644 --- a/tests/unittests/e2/e2_subscription_setup_test.cpp +++ b/tests/unittests/e2/e2_subscription_setup_test.cpp @@ -41,7 +41,7 @@ TEST_F(e2_test_subscriber, when_e2_subscription_request_correct_sent_subscriptio 0x00, 0x15, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x60, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x02, 0x00}; - byte_buffer e2ap_sub_req_buf(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)); + byte_buffer e2ap_sub_req_buf = byte_buffer::create(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)).value(); packer->handle_packed_pdu(std::move(e2ap_sub_req_buf)); asn1::cbit_ref bref(gw->last_pdu); @@ -60,7 +60,7 @@ TEST_F(e2_test_subscriber, when_e2_subscription_request_received_start_indicatio 0x00, 0x15, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x60, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x02, 0x00}; - byte_buffer e2ap_sub_req_buf(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)); + byte_buffer e2ap_sub_req_buf = byte_buffer::create(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)).value(); packer->handle_packed_pdu(std::move(e2ap_sub_req_buf)); asn1::cbit_ref bref(gw->last_pdu); e2_message msg = {}; @@ -94,7 +94,7 @@ TEST_F(e2_test_subscriber, start_indication_procedure_check_contents) std::unique_ptr report_service = e2sm_mngr->get_e2sm_interface("1.3.6.1.4.1.53148.1.2.2.2")->get_e2sm_report_service(action_def); sub_info.action_list.push_back( - {action_def.deep_copy(), 1, asn1::e2ap::ri_caction_type_e::report, std::move(report_service)}); + {action_def.deep_copy().value(), 1, asn1::e2ap::ri_caction_type_e::report, std::move(report_service)}); std::unique_ptr ev_mng = std::make_unique(factory); ev_mng->add_sub_del_req(sub_info.request_id, factory); auto task = launch_async(*msg_notifier, *ev_mng, sub_info, test_logger); @@ -130,7 +130,7 @@ TEST_F(e2_test_subscriber, start_subscription_then_delete_subscription) 0x00, 0x15, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x13, 0x40, 0x0a, 0x60, 0x01, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x02, 0x00}; - byte_buffer e2ap_sub_req_buf(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)); + byte_buffer e2ap_sub_req_buf = byte_buffer::create(e2ap_sub_req, e2ap_sub_req + sizeof(e2ap_sub_req)).value(); packer->handle_packed_pdu(std::move(e2ap_sub_req_buf)); asn1::cbit_ref bref(gw->last_pdu); @@ -142,9 +142,9 @@ TEST_F(e2_test_subscriber, start_subscription_then_delete_subscription) ASSERT_EQ(msg.pdu.successful_outcome().value.type(), e2_ap_elem_procs_o::successful_outcome_c::types_opts::ricsubscription_resp); - uint8_t sub_del_req[] = {0x00, 0x09, 0x00, 0x12, 0x00, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x05, - 0x00, 0x00, 0x7b, 0x00, 0x15, 0x00, 0x05, 0x00, 0x02, 0x00, 0x93}; - byte_buffer sub_del_req_buf(sub_del_req, sub_del_req + sizeof(sub_del_req)); + uint8_t sub_del_req[] = {0x00, 0x09, 0x00, 0x12, 0x00, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x05, + 0x00, 0x00, 0x7b, 0x00, 0x15, 0x00, 0x05, 0x00, 0x02, 0x00, 0x93}; + byte_buffer sub_del_req_buf = byte_buffer::create(sub_del_req, sub_del_req + sizeof(sub_del_req)).value(); packer->handle_packed_pdu(std::move(sub_del_req_buf)); @@ -156,4 +156,4 @@ TEST_F(e2_test_subscriber, start_subscription_then_delete_subscription) ASSERT_EQ(msg1.pdu.type().value, asn1::e2ap::e2_ap_pdu_c::types_opts::successful_outcome); ASSERT_EQ(msg1.pdu.successful_outcome().value.type(), e2_ap_elem_procs_o::successful_outcome_c::types_opts::ricsubscription_delete_resp); -} \ No newline at end of file +} diff --git a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h index 565775c847..dad1c93d5b 100644 --- a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h +++ b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h @@ -51,8 +51,8 @@ f1ap_message generate_init_ul_rrc_message_transfer(gnb_du_ue_f1ap_id_t du_ue_id, /// \brief Generates dummy F1AP UL RRC TRANSFER message. f1ap_message generate_ul_rrc_message_transfer(gnb_cu_ue_f1ap_id_t cu_ue_id, gnb_du_ue_f1ap_id_t du_ue_id, - srb_id_t srb_id = srb_id_t::srb1, - byte_buffer rrc_container = {0x1, 0x2, 0x3}); + srb_id_t srb_id = srb_id_t::srb1, + byte_buffer rrc_container = byte_buffer::create({0x1, 0x2, 0x3}).value()); /// \brief Generates dummy F1AP UE CONTEXT RELEASE COMPLETE message. f1ap_message generate_ue_context_release_complete(gnb_cu_ue_f1ap_id_t cu_ue_id, gnb_du_ue_f1ap_id_t du_ue_id); diff --git a/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp b/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp index b4f78b4bc6..a09a7c5200 100644 --- a/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp +++ b/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp @@ -77,7 +77,7 @@ f1ap_message srsran::generate_f1ap_dl_rrc_message_transfer(srb_id_t srb_id, cons dl_msg->gnb_cu_ue_f1ap_id = 0; dl_msg->gnb_du_ue_f1ap_id = 0; dl_msg->srb_id = srb_id_to_uint(srb_id); - dl_msg->rrc_container = rrc_container.deep_copy(); + dl_msg->rrc_container = rrc_container.deep_copy().value(); return msg; } diff --git a/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp b/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp index 373ef33ee8..7b60188a5d 100644 --- a/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp +++ b/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp @@ -55,7 +55,8 @@ f1ap_cu_test::~f1ap_cu_test() f1ap_cu_test::test_ue& f1ap_cu_test::create_ue(gnb_du_ue_f1ap_id_t du_ue_id) { - f1ap_message msg = generate_init_ul_rrc_message_transfer(du_ue_id, to_rnti(0x4601), {0x1, 0x2, 0x3, 0x4}); + f1ap_message msg = generate_init_ul_rrc_message_transfer( + du_ue_id, to_rnti(0x4601), byte_buffer::create({0x1, 0x2, 0x3, 0x4}).value()); f1ap->handle_message(msg); ue_index_t ue_index = *du_processor_notifier.last_created_ue_index; test_ues.emplace(ue_index, test_ue{ue_index}); diff --git a/tests/unittests/f1ap/du/f1ap_du_dl_rrc_message_transfer_test.cpp b/tests/unittests/f1ap/du/f1ap_du_dl_rrc_message_transfer_test.cpp index 935f8234a8..6341baab7e 100644 --- a/tests/unittests/f1ap/du/f1ap_du_dl_rrc_message_transfer_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_dl_rrc_message_transfer_test.cpp @@ -35,7 +35,7 @@ TEST_F(f1ap_du_test, when_dl_rrc_message_transfer_is_received_lower_layer_srb_no ASSERT_TRUE(ue->f1c_bearers[1].rx_sdu_notifier.last_pdu.empty()); // Test section - byte_buffer test_rrc_msg = {0x1, 0x2, 0x3}; + byte_buffer test_rrc_msg = byte_buffer::create({0x1, 0x2, 0x3}).value(); f1ap_message msg = generate_f1ap_dl_rrc_message_transfer(srb_id_t::srb1, test_rrc_msg); f1ap->handle_message(msg); ASSERT_FALSE(ue->f1c_bearers[1].rx_sdu_notifier.last_pdu.empty()); @@ -50,12 +50,12 @@ TEST_F(f1ap_du_test, when_dl_rrc_message_transfer_is_received_gnb_cu_ue_f1ap_id_ ASSERT_TRUE(ue->f1c_bearers[1].rx_sdu_notifier.last_pdu.empty()); // Test Section. - byte_buffer test_rrc_msg = {0x1, 0x2, 0x3}; + byte_buffer test_rrc_msg = byte_buffer::create({0x1, 0x2, 0x3}).value(); f1ap_message msg = generate_f1ap_dl_rrc_message_transfer(srb_id_t::srb1, test_rrc_msg); msg.pdu.init_msg().value.dl_rrc_msg_transfer()->gnb_cu_ue_f1ap_id = 5; // The DL RRC Message Transfer should update the gNB-CU UE F1AP ID. f1ap->handle_message(msg); - test_ues[0].f1c_bearers[1].bearer->handle_sdu(byte_buffer_chain{test_rrc_msg.copy()}); + test_ues[0].f1c_bearers[1].bearer->handle_sdu(byte_buffer_chain::create(test_rrc_msg.copy()).value()); ASSERT_EQ(f1c_gw.last_tx_f1ap_pdu.pdu.init_msg().value.ul_rrc_msg_transfer()->gnb_cu_ue_f1ap_id, msg.pdu.init_msg().value.dl_rrc_msg_transfer()->gnb_cu_ue_f1ap_id) << "Invalid gNB-CU UE F1AP ID"; diff --git a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp index efe7c85a5c..56366dd466 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp @@ -177,7 +177,25 @@ f1ap_message srsran::srs_du::generate_ue_context_release_command() dl_msg->srb_id_present = true; dl_msg->srb_id = 1; dl_msg->rrc_container_present = true; - dl_msg->rrc_container = byte_buffer{0x1, 0x2, 0x3, 0x4}; + dl_msg->rrc_container = byte_buffer::create({0x1, 0x2, 0x3, 0x4}).value(); + + return msg; +} + +f1ap_message srsran::srs_du::generate_dl_rrc_message_transfer(gnb_du_ue_f1ap_id_t du_ue_id, + gnb_cu_ue_f1ap_id_t cu_ue_id, + srb_id_t srb_id, + byte_buffer rrc_container) +{ + using namespace asn1::f1ap; + f1ap_message msg; + + msg.pdu.set_init_msg().load_info_obj(ASN1_F1AP_ID_DL_RRC_MSG_TRANSFER); + dl_rrc_msg_transfer_s& dl_msg = msg.pdu.init_msg().value.dl_rrc_msg_transfer(); + dl_msg->gnb_du_ue_f1ap_id = gnb_du_ue_f1ap_id_to_uint(du_ue_id); + dl_msg->gnb_cu_ue_f1ap_id = gnb_cu_ue_f1ap_id_to_uint(cu_ue_id); + dl_msg->srb_id = srb_id_to_uint(srb_id); + dl_msg->rrc_container = std::move(rrc_container); return msg; } @@ -307,8 +325,9 @@ void f1ap_du_test::run_ue_context_setup_procedure(du_ue_index_t ue_index, const } // Generate DU manager response to UE context update. - f1ap_du_cfg_handler.next_ue_context_update_response.result = true; - f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = {0x1, 0x2, 0x3}; + f1ap_du_cfg_handler.next_ue_context_update_response.result = true; + f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = + byte_buffer::create({0x1, 0x2, 0x3}).value(); // Send UE CONTEXT SETUP REQUEST message to F1AP. f1ap->handle_message(msg); diff --git a/tests/unittests/f1ap/du/f1ap_du_test_helpers.h b/tests/unittests/f1ap/du/f1ap_du_test_helpers.h index c20f687607..14de662859 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.h +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.h @@ -154,6 +154,12 @@ f1ap_message generate_ue_context_modification_request(const std::initializer_lis /// \brief Generate an F1AP UE Context Release Command message. f1ap_message generate_ue_context_release_command(); +/// \brief Generate an F1AP DL RRC Message Transfer message. +f1ap_message generate_dl_rrc_message_transfer(gnb_du_ue_f1ap_id_t du_ue_id, + gnb_cu_ue_f1ap_id_t cu_ue_id, + srb_id_t srb_id, + byte_buffer rrc_container); + class dummy_f1c_connection_client : public srs_du::f1c_connection_client { public: diff --git a/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp b/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp index 8dca297dba..fe4404cfa5 100644 --- a/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp @@ -71,14 +71,16 @@ TEST_F(f1ap_du_ue_management_tester, f1ap_created_bearers_forward_messages_to_no f1ap_ue_configuration_response resp = f1ap->handle_ue_configuration_request(req); // Send DL data through created F1-C bearer. - byte_buffer dl_srb_buf{test_rgen::random_vector(test_rgen::uniform_int(3, 100))}; + byte_buffer dl_srb_buf = + byte_buffer::create(test_rgen::random_vector(test_rgen::uniform_int(3, 100))).value(); ASSERT_TRUE(this->srb2_rx_sdu_notifier.last_pdu.empty()); f1ap->handle_message(generate_f1ap_dl_rrc_message_transfer(srb_id_t::srb2, dl_srb_buf)); ASSERT_EQ(dl_srb_buf, this->srb2_rx_sdu_notifier.last_pdu); // Send UL data through created F1-C bearer. - byte_buffer ul_srb_buf{test_rgen::random_vector(test_rgen::uniform_int(3, 100))}; - resp.f1c_bearers_added[0].bearer->handle_sdu(byte_buffer_chain{ul_srb_buf.copy()}); + byte_buffer ul_srb_buf = + byte_buffer::create(test_rgen::random_vector(test_rgen::uniform_int(3, 100))).value(); + resp.f1c_bearers_added[0].bearer->handle_sdu(byte_buffer_chain::create(ul_srb_buf.copy()).value()); const auto& ul_f1ap_msg = this->f1c_gw.last_tx_f1ap_pdu.pdu.init_msg().value.ul_rrc_msg_transfer(); ASSERT_EQ(ul_f1ap_msg->rrc_container, ul_srb_buf); ASSERT_EQ((srb_id_t)ul_f1ap_msg->srb_id, srb_id_t::srb2); @@ -96,7 +98,8 @@ TEST_F(f1ap_du_ue_management_tester, f1ap_created_bearers_do_not_forward_invalid f1ap_ue_configuration_response resp = f1ap->handle_ue_configuration_request(req); // Send DL data through created F1-C bearer. - byte_buffer dl_srb_buf{test_rgen::random_vector(test_rgen::uniform_int(1, 2))}; + byte_buffer dl_srb_buf = + byte_buffer::create(test_rgen::random_vector(test_rgen::uniform_int(1, 2))).value(); ASSERT_TRUE(this->srb2_rx_sdu_notifier.last_pdu.empty()); f1ap->handle_message(generate_f1ap_dl_rrc_message_transfer(srb_id_t::srb2, dl_srb_buf)); ASSERT_TRUE(this->srb2_rx_sdu_notifier.last_pdu.empty()); diff --git a/tests/unittests/f1ap/du/f1ap_du_ue_context_modification_test.cpp b/tests/unittests/f1ap/du/f1ap_du_ue_context_modification_test.cpp index b5a39943fb..1c3e6a481b 100644 --- a/tests/unittests/f1ap/du/f1ap_du_ue_context_modification_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_ue_context_modification_test.cpp @@ -51,7 +51,8 @@ class f1ap_du_ue_context_modification_test : public f1ap_du_test drb.dluptnl_info_list[0].gtp_teid = int_to_gtpu_teid(test_rgen::uniform_int()); drb.dluptnl_info_list[0].tp_address = transport_layer_address::create_from_string("127.0.0.1"); } - this->f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = {0x1, 0x2, 0x3}; + this->f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = + byte_buffer::create({0x1, 0x2, 0x3}).value(); // Initiate procedure in F1AP. f1ap_message msg = generate_ue_context_modification_request(drbs); @@ -119,7 +120,8 @@ TEST_F(f1ap_du_ue_context_modification_test, // Prepare DU manager response to F1AP with failed DRB. this->f1ap_du_cfg_handler.next_ue_context_update_response.result = true; this->f1ap_du_cfg_handler.next_ue_context_update_response.drbs_failed_to_setup.push_back(drb_id_t::drb1); - this->f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = {0x1, 0x2, 0x3}; + this->f1ap_du_cfg_handler.next_ue_context_update_response.du_to_cu_rrc_container = + byte_buffer::create({0x1, 0x2, 0x3}).value(); // Initiate procedure in F1AP. f1ap_message msg = generate_ue_context_modification_request({drb_id_t::drb1}); diff --git a/tests/unittests/f1ap/du/f1ap_du_ue_context_setup_procedure_test.cpp b/tests/unittests/f1ap/du/f1ap_du_ue_context_setup_procedure_test.cpp index 9438f81bf0..55c25a75ee 100644 --- a/tests/unittests/f1ap/du/f1ap_du_ue_context_setup_procedure_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_ue_context_setup_procedure_test.cpp @@ -76,7 +76,7 @@ class f1ap_du_ue_context_setup_test : public f1ap_du_test auto& du_to_f1_resp = this->f1ap_du_cfg_handler.next_ue_context_update_response; du_to_f1_resp.result = true; - du_to_f1_resp.du_to_cu_rrc_container = {0x1, 0x2, 0x3}; + du_to_f1_resp.du_to_cu_rrc_container = byte_buffer::create({0x1, 0x2, 0x3}).value(); if (ue_ctx_setup.drbs_to_be_setup_list_present) { du_to_f1_resp.drbs_setup.resize(ue_ctx_setup.drbs_to_be_setup_list.size()); for (size_t i = 0; i < ue_ctx_setup.drbs_to_be_setup_list.size(); ++i) { @@ -160,8 +160,9 @@ TEST_F(f1ap_du_ue_context_setup_test, when_f1ap_receives_request_then_new_srbs_b // UL data through created SRB2 reaches F1-C. ASSERT_EQ(this->f1ap_du_cfg_handler.last_ue_cfg_response->f1c_bearers_added.size(), 1); f1c_bearer* srb2 = this->f1ap_du_cfg_handler.last_ue_cfg_response->f1c_bearers_added[0].bearer; - byte_buffer ul_rrc_msg{test_rgen::random_vector(test_rgen::uniform_int(1, 100))}; - srb2->handle_sdu(byte_buffer_chain{ul_rrc_msg.copy()}); + byte_buffer ul_rrc_msg = + byte_buffer::create(test_rgen::random_vector(test_rgen::uniform_int(1, 100))).value(); + srb2->handle_sdu(byte_buffer_chain::create(ul_rrc_msg.copy()).value()); ASSERT_EQ(this->f1c_gw.last_tx_f1ap_pdu.pdu.type().value, f1ap_pdu_c::types_opts::init_msg); ASSERT_EQ(this->f1c_gw.last_tx_f1ap_pdu.pdu.init_msg().value.type().value, f1ap_elem_procs_o::init_msg_c::types_opts::ul_rrc_msg_transfer); @@ -234,7 +235,7 @@ TEST_F(f1ap_du_test, f1ap_handles_precanned_ue_context_setup_request_correctly) 0x20, 0x08, 0x08, 0x95, 0x75, 0x5b, 0x0c, 0x00, 0xb8, 0x40, 0x01, 0x00}; // 000500440000080028000200160029400340a127003f00090002f899000bc614e0006b0001000009000100004a00060000490001080032400a09000320080895755b0c00b8400100 - byte_buffer buf(msg); + byte_buffer buf = byte_buffer::create(msg).value(); asn1::cbit_ref bref(buf); ASSERT_EQ(ue_ctxt_setup_req.pdu.unpack(bref), asn1::SRSASN_SUCCESS); } diff --git a/tests/unittests/f1ap/du/f1ap_du_ul_rrc_message_transfer_test.cpp b/tests/unittests/f1ap/du/f1ap_du_ul_rrc_message_transfer_test.cpp index 6414e73730..a41d6c8f1a 100644 --- a/tests/unittests/f1ap/du/f1ap_du_ul_rrc_message_transfer_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_ul_rrc_message_transfer_test.cpp @@ -39,8 +39,8 @@ TEST_F(f1ap_du_test, when_sdu_is_received_then_sdu_is_forwarded_to_tx_pdu_notifi this->f1c_gw.last_tx_f1ap_pdu.pdu = {}; std::vector bytes = test_rgen::random_vector(test_rgen::uniform_int(1, 4000)); - byte_buffer sdu{bytes}; - ue->f1c_bearers[1].bearer->handle_sdu(byte_buffer_chain{sdu.copy()}); + byte_buffer sdu = byte_buffer::create(bytes).value(); + ue->f1c_bearers[1].bearer->handle_sdu(byte_buffer_chain::create(sdu.copy()).value()); ASSERT_EQ(this->f1c_gw.last_tx_f1ap_pdu.pdu.type().value, asn1::f1ap::f1ap_pdu_c::types_opts::init_msg); ASSERT_EQ(this->f1c_gw.last_tx_f1ap_pdu.pdu.init_msg().proc_code, ASN1_F1AP_ID_UL_RRC_MSG_TRANSFER); diff --git a/tests/unittests/f1u/common/f1u_connector_test.cpp b/tests/unittests/f1u/common/f1u_connector_test.cpp index 8808ae8f68..5ad46e4996 100644 --- a/tests/unittests/f1u/common/f1u_connector_test.cpp +++ b/tests/unittests/f1u/common/f1u_connector_test.cpp @@ -27,6 +27,8 @@ using namespace srsran; +namespace { + // dummy CU-UP RX bearer interface struct dummy_f1u_cu_up_rx_sdu_notifier final : public srs_cu_up::f1u_rx_sdu_notifier { void on_new_sdu(byte_buffer_chain sdu) override @@ -34,8 +36,8 @@ struct dummy_f1u_cu_up_rx_sdu_notifier final : public srs_cu_up::f1u_rx_sdu_noti logger.info(sdu.begin(), sdu.end(), "CU-UP received SDU"); last_sdu = std::move(sdu); } - byte_buffer_chain last_sdu; - srslog::basic_logger& logger = srslog::fetch_basic_logger("CU-F1-U", false); + byte_buffer_chain last_sdu = byte_buffer_chain::create().value(); + srslog::basic_logger& logger = srslog::fetch_basic_logger("CU-F1-U", false); }; struct dummy_f1u_cu_up_rx_delivery_notifier final : public srs_cu_up::f1u_rx_delivery_notifier { @@ -112,6 +114,8 @@ class f1u_connector_test : public ::testing::Test srslog::basic_logger& f1u_logger_du = srslog::fetch_basic_logger("DU-F1-U", false); }; +} // namespace + /// Test the instantiation of a new entity TEST_F(f1u_connector_test, create_new_connector) { @@ -144,17 +148,21 @@ TEST_F(f1u_connector_test, attach_detach_cu_up_f1u_to_du_f1u) cu_gw->attach_dl_teid(ul_tnl, dl_tnl); // Check CU-UP -> DU path - byte_buffer cu_buf = make_byte_buffer("ABCD"); - byte_buffer_chain du_exp{cu_buf.deep_copy()}; + byte_buffer cu_buf = make_byte_buffer("ABCD"); + auto du_exp_buf = byte_buffer_chain::create(cu_buf.deep_copy().value()); + ASSERT_FALSE(du_exp_buf.is_error()); + byte_buffer_chain du_exp = std::move(du_exp_buf.value()); pdcp_tx_pdu sdu; sdu.buf = std::move(cu_buf); sdu.pdcp_sn = 0; cu_bearer->get_tx_sdu_handler().handle_sdu(std::move(sdu)); // Check DU-> CU-UP path - byte_buffer du_buf = make_byte_buffer("DCBA"); - byte_buffer cu_exp = du_buf.deep_copy(); - byte_buffer_chain du_slice{du_buf.deep_copy()}; + byte_buffer du_buf = make_byte_buffer("DCBA"); + byte_buffer cu_exp = du_buf.deep_copy().value(); + auto du_slice_buf = byte_buffer_chain::create(du_buf.deep_copy().value()); + ASSERT_FALSE(du_slice_buf.is_error()); + byte_buffer_chain du_slice = std::move(du_slice_buf.value()); du_bearer->get_tx_sdu_handler().handle_sdu(std::move(du_slice)); ASSERT_EQ(du_rx.last_sdu, du_exp); @@ -164,9 +172,11 @@ TEST_F(f1u_connector_test, attach_detach_cu_up_f1u_to_du_f1u) cu_bearer.reset(); // Check DU-> CU-UP path is properly detached - byte_buffer du_buf2 = make_byte_buffer("LMNO"); - byte_buffer cu_exp2 = du_buf2.deep_copy(); - byte_buffer_chain du_slice2{du_buf2.deep_copy()}; + byte_buffer du_buf2 = make_byte_buffer("LMNO"); + byte_buffer cu_exp2 = du_buf2.deep_copy().value(); + auto du_slice2_buf = byte_buffer_chain::create(du_buf2.deep_copy().value()); + ASSERT_FALSE(du_slice2_buf.is_error()); + byte_buffer_chain du_slice2 = std::move(du_slice2_buf.value()); du_bearer->get_tx_sdu_handler().handle_sdu(std::move(du_slice2)); ASSERT_EQ(cu_rx.last_sdu, cu_exp); // Last SDU should not have changed } @@ -195,17 +205,21 @@ TEST_F(f1u_connector_test, detach_du_f1u_first) cu_gw->attach_dl_teid(ul_tnl, dl_tnl); // Check CU-UP -> DU path - byte_buffer cu_buf = make_byte_buffer("ABCD"); - byte_buffer_chain du_exp{cu_buf.deep_copy()}; + byte_buffer cu_buf = make_byte_buffer("ABCD"); + auto du_exp_buf = byte_buffer_chain::create(cu_buf.deep_copy().value()); + ASSERT_FALSE(du_exp_buf.is_error()); + byte_buffer_chain du_exp = std::move(du_exp_buf.value()); pdcp_tx_pdu sdu; sdu.buf = std::move(cu_buf); sdu.pdcp_sn = 0; cu_bearer->get_tx_sdu_handler().handle_sdu(std::move(sdu)); // Check DU-> CU-UP path - byte_buffer du_buf = make_byte_buffer("DCBA"); - byte_buffer cu_exp = du_buf.deep_copy(); - byte_buffer_chain du_slice{du_buf.deep_copy()}; + byte_buffer du_buf = make_byte_buffer("DCBA"); + byte_buffer cu_exp = du_buf.deep_copy().value(); + auto du_slice_buf = byte_buffer_chain::create(du_buf.deep_copy().value()); + ASSERT_FALSE(du_slice_buf.is_error()); + byte_buffer_chain du_slice = std::move(du_slice_buf.value()); du_bearer->get_tx_sdu_handler().handle_sdu(std::move(du_slice)); ASSERT_EQ(du_rx.last_sdu, du_exp); @@ -248,17 +262,21 @@ TEST_F(f1u_connector_test, update_du_f1u) { // Check CU-UP -> DU path - byte_buffer cu_buf = make_byte_buffer("ABCD"); - byte_buffer_chain du_exp{cu_buf.deep_copy()}; + byte_buffer cu_buf = make_byte_buffer("ABCD"); + auto du_exp_buf = byte_buffer_chain::create(cu_buf.deep_copy().value()); + ASSERT_FALSE(du_exp_buf.is_error()); + byte_buffer_chain du_exp = std::move(du_exp_buf.value()); pdcp_tx_pdu sdu; sdu.buf = std::move(cu_buf); sdu.pdcp_sn = 0; cu_bearer->get_tx_sdu_handler().handle_sdu(std::move(sdu)); // Check DU-> CU-UP path - byte_buffer du_buf = make_byte_buffer("DCBA"); - byte_buffer cu_exp = du_buf.deep_copy(); - byte_buffer_chain du_slice{du_buf.deep_copy()}; + byte_buffer du_buf = make_byte_buffer("DCBA"); + byte_buffer cu_exp = du_buf.deep_copy().value(); + auto du_slice_buf = byte_buffer_chain::create(du_buf.deep_copy().value()); + ASSERT_FALSE(du_slice_buf.is_error()); + byte_buffer_chain du_slice = std::move(du_slice_buf.value()); du_bearer1->get_tx_sdu_handler().handle_sdu(std::move(du_slice)); ASSERT_EQ(du_rx1.last_sdu, du_exp); @@ -280,17 +298,21 @@ TEST_F(f1u_connector_test, update_du_f1u) { // Check CU-UP -> DU path - byte_buffer cu_buf = make_byte_buffer("ABCD"); - byte_buffer_chain du_exp{cu_buf.deep_copy()}; + byte_buffer cu_buf = make_byte_buffer("ABCD"); + auto du_exp_buf = byte_buffer_chain::create(cu_buf.deep_copy().value()); + ASSERT_FALSE(du_exp_buf.is_error()); + byte_buffer_chain du_exp = std::move(du_exp_buf.value()); pdcp_tx_pdu sdu; sdu.buf = std::move(cu_buf); sdu.pdcp_sn = 0; cu_bearer->get_tx_sdu_handler().handle_sdu(std::move(sdu)); // Check DU-> CU-UP path - byte_buffer du_buf = make_byte_buffer("DCBA"); - byte_buffer cu_exp = du_buf.deep_copy(); - byte_buffer_chain du_slice{du_buf.deep_copy()}; + byte_buffer du_buf = make_byte_buffer("DCBA"); + byte_buffer cu_exp = du_buf.deep_copy().value(); + auto du_slice_buf = byte_buffer_chain::create(du_buf.deep_copy().value()); + ASSERT_FALSE(du_slice_buf.is_error()); + byte_buffer_chain du_slice = std::move(du_slice_buf.value()); du_bearer2->get_tx_sdu_handler().handle_sdu(std::move(du_slice)); } } diff --git a/tests/unittests/f1u/cu_up/f1u_cu_up_bearer_test.cpp b/tests/unittests/f1u/cu_up/f1u_cu_up_bearer_test.cpp index 7392689ae3..bfdd2d592a 100644 --- a/tests/unittests/f1u/cu_up/f1u_cu_up_bearer_test.cpp +++ b/tests/unittests/f1u/cu_up/f1u_cu_up_bearer_test.cpp @@ -181,7 +181,7 @@ TEST_F(f1u_cu_up_test, tx_discard) byte_buffer tx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, 0xcc); pdcp_tx_pdu sdu1; - sdu1.buf = tx_pdcp_pdu1.deep_copy(); + sdu1.buf = tx_pdcp_pdu1.deep_copy().value(); sdu1.pdcp_sn = pdcp_sn + 22; // transmit a PDU to piggy-back previous discard @@ -241,13 +241,13 @@ TEST_F(f1u_cu_up_test, tx_pdcp_pdus) byte_buffer tx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); pdcp_tx_pdu sdu1; - sdu1.buf = tx_pdcp_pdu1.deep_copy(); + sdu1.buf = tx_pdcp_pdu1.deep_copy().value(); sdu1.pdcp_sn = pdcp_sn; f1u->handle_sdu(std::move(sdu1)); byte_buffer tx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); pdcp_tx_pdu sdu2; - sdu2.buf = tx_pdcp_pdu2.deep_copy(); + sdu2.buf = tx_pdcp_pdu2.deep_copy().value(); sdu2.pdcp_sn = pdcp_sn + 1; f1u->handle_sdu(std::move(sdu2)); @@ -286,7 +286,9 @@ TEST_F(f1u_cu_up_test, rx_pdcp_pdus) byte_buffer rx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); nru_ul_message msg1; - msg1.t_pdu = byte_buffer_chain{rx_pdcp_pdu1.deep_copy()}; + auto chain1 = byte_buffer_chain::create(rx_pdcp_pdu1.deep_copy().value()); + EXPECT_FALSE(chain1.is_error()); + msg1.t_pdu = std::move(chain1.value()); f1u->handle_pdu(std::move(msg1)); // UL PDUs restart inactivity timer, hence further ticks shall not expire the timer @@ -295,7 +297,9 @@ TEST_F(f1u_cu_up_test, rx_pdcp_pdus) byte_buffer rx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); nru_ul_message msg2; - msg2.t_pdu = byte_buffer_chain{rx_pdcp_pdu2.deep_copy()}; + auto chain2 = byte_buffer_chain::create(rx_pdcp_pdu2.deep_copy().value()); + EXPECT_FALSE(chain2.is_error()); + msg2.t_pdu = std::move(chain2.value()); f1u->handle_pdu(std::move(msg2)); // UL PDUs restart inactivity timer, hence further ticks shall not expire the timer diff --git a/tests/unittests/f1u/du/f1u_du_bearer_test.cpp b/tests/unittests/f1u/du/f1u_du_bearer_test.cpp index 64827e8a38..e6fe1a05d8 100644 --- a/tests/unittests/f1u/du/f1u_du_bearer_test.cpp +++ b/tests/unittests/f1u/du/f1u_du_bearer_test.cpp @@ -29,6 +29,8 @@ using namespace srsran; using namespace srs_du; +namespace { + /// Mocking class of the surrounding layers invoked by the F1-U bearer class f1u_du_test_frame : public f1u_rx_sdu_notifier, public f1u_tx_pdu_notifier { @@ -115,6 +117,8 @@ class f1u_du_test : public ::testing::Test, public f1u_trx_test const uint32_t f1u_ul_notif_time_ms = 10; }; +} // namespace + TEST_F(f1u_du_test, create_new_entity) { EXPECT_TRUE(tester->rx_sdu_list.empty()); @@ -131,11 +135,11 @@ TEST_F(f1u_du_test, rx_discard) nru_pdcp_sn_discard_block block1a = {}; block1a.pdcp_sn_start = pdcp_sn; block1a.block_size = 1; - msg1.dl_user_data.discard_blocks.value().push_back(std::move(block1a)); + msg1.dl_user_data.discard_blocks.value().push_back(block1a); nru_pdcp_sn_discard_block block1b = {}; block1b.pdcp_sn_start = pdcp_sn + 3; block1b.block_size = 2; - msg1.dl_user_data.discard_blocks.value().push_back(std::move(block1b)); + msg1.dl_user_data.discard_blocks.value().push_back(block1b); f1u->handle_pdu(std::move(msg1)); nru_dl_message msg2 = {}; @@ -143,7 +147,7 @@ TEST_F(f1u_du_test, rx_discard) nru_pdcp_sn_discard_block block2 = {}; block2.pdcp_sn_start = pdcp_sn + 9; block2.block_size = 1; - msg2.dl_user_data.discard_blocks.value().push_back(std::move(block2)); + msg2.dl_user_data.discard_blocks.value().push_back(block2); f1u->handle_pdu(std::move(msg2)); EXPECT_TRUE(tester->rx_sdu_list.empty()); @@ -178,13 +182,13 @@ TEST_F(f1u_du_test, rx_pdcp_pdus) byte_buffer rx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); nru_dl_message msg1 = {}; - msg1.t_pdu = rx_pdcp_pdu1.deep_copy(); + msg1.t_pdu = rx_pdcp_pdu1.deep_copy().value(); msg1.pdcp_sn = pdcp_sn; f1u->handle_pdu(std::move(msg1)); byte_buffer rx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); nru_dl_message msg2 = {}; - msg2.t_pdu = rx_pdcp_pdu2.deep_copy(); + msg2.t_pdu = rx_pdcp_pdu2.deep_copy().value(); msg2.pdcp_sn = pdcp_sn + 1; f1u->handle_pdu(std::move(msg2)); @@ -212,23 +216,27 @@ TEST_F(f1u_du_test, tx_pdcp_pdus) constexpr uint32_t pdcp_sn = 123; byte_buffer tx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu1.deep_copy()}); + auto chain1 = byte_buffer_chain::create(tx_pdcp_pdu1.deep_copy().value()); + ASSERT_FALSE(chain1.is_error()); + f1u->handle_sdu(std::move(chain1.value())); byte_buffer tx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu2.deep_copy()}); + auto chain2 = byte_buffer_chain::create(tx_pdcp_pdu2.deep_copy().value()); + ASSERT_FALSE(chain2.is_error()); + f1u->handle_sdu(std::move(chain2.value())); EXPECT_TRUE(tester->rx_discard_sdu_list.empty()); EXPECT_TRUE(tester->rx_sdu_list.empty()); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu1); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu1); EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); tester->tx_msg_list.pop_front(); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu2); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu2); EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); @@ -247,16 +255,20 @@ TEST_F(f1u_du_test, tx_pdcp_pdus_with_transmit_notification) f1u->handle_transmit_notification(highest_pdcp_sn + 1); byte_buffer tx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu1.deep_copy()}); + auto chain1 = byte_buffer_chain::create(tx_pdcp_pdu1.deep_copy().value()); + ASSERT_FALSE(chain1.is_error()); + f1u->handle_sdu(std::move(chain1.value())); byte_buffer tx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu2.deep_copy()}); + auto chain2 = byte_buffer_chain::create(tx_pdcp_pdu2.deep_copy().value()); + ASSERT_FALSE(chain2.is_error()); + f1u->handle_sdu(std::move(chain2.value())); EXPECT_TRUE(tester->rx_discard_sdu_list.empty()); EXPECT_TRUE(tester->rx_sdu_list.empty()); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu1); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu1); ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value()); { nru_dl_data_delivery_status& status = tester->tx_msg_list.front().data_delivery_status.value(); @@ -274,7 +286,7 @@ TEST_F(f1u_du_test, tx_pdcp_pdus_with_transmit_notification) tester->tx_msg_list.pop_front(); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu2); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu2); EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); @@ -300,16 +312,20 @@ TEST_F(f1u_du_test, tx_pdcp_pdus_with_delivery_notification) EXPECT_TRUE(tester->tx_msg_list.empty()); byte_buffer tx_pdcp_pdu1 = create_sdu_byte_buffer(pdu_size, pdcp_sn); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu1.deep_copy()}); + auto chain1 = byte_buffer_chain::create(tx_pdcp_pdu1.deep_copy().value()); + ASSERT_FALSE(chain1.is_error()); + f1u->handle_sdu(std::move(chain1.value())); byte_buffer tx_pdcp_pdu2 = create_sdu_byte_buffer(pdu_size, pdcp_sn + 1); - f1u->handle_sdu(byte_buffer_chain{tx_pdcp_pdu2.deep_copy()}); + auto chain2 = byte_buffer_chain::create(tx_pdcp_pdu2.deep_copy().value()); + ASSERT_FALSE(chain2.is_error()); + f1u->handle_sdu(std::move(chain2.value())); EXPECT_TRUE(tester->rx_discard_sdu_list.empty()); EXPECT_TRUE(tester->rx_sdu_list.empty()); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu1); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu1); ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value()); { nru_dl_data_delivery_status& status = tester->tx_msg_list.front().data_delivery_status.value(); @@ -327,7 +343,7 @@ TEST_F(f1u_du_test, tx_pdcp_pdus_with_delivery_notification) tester->tx_msg_list.pop_front(); ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_EQ(tester->tx_msg_list.front().t_pdu, tx_pdcp_pdu2); + EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu2); EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); @@ -347,7 +363,7 @@ TEST_F(f1u_du_test, tx_pdcp_pdus_with_delivery_notification) } ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_TRUE(tester->tx_msg_list.front().t_pdu.empty()); + EXPECT_FALSE(tester->tx_msg_list.front().t_pdu.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value()); { @@ -382,7 +398,7 @@ TEST_F(f1u_du_test, tx_transmit_notification) } ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_TRUE(tester->tx_msg_list.front().t_pdu.empty()); + EXPECT_FALSE(tester->tx_msg_list.front().t_pdu.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value()); { @@ -417,7 +433,7 @@ TEST_F(f1u_du_test, tx_delivery_notification) } ASSERT_FALSE(tester->tx_msg_list.empty()); - EXPECT_TRUE(tester->tx_msg_list.front().t_pdu.empty()); + EXPECT_FALSE(tester->tx_msg_list.front().t_pdu.has_value()); EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value()); ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value()); { diff --git a/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp index 00b4e80803..156c259695 100644 --- a/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp @@ -76,33 +76,11 @@ TEST(dl_csi_pdu_builder, valid_tx_power_info_parameters_passes) dl_csi_rs_pdu pdu; dl_csi_rs_pdu_builder builder(pdu); - nzp_csi_rs_epre_to_ssb ss = nzp_csi_rs_epre_to_ssb::dB3; - optional profile_nr; - if (power) { - profile_nr.emplace(power); - } + power_control_offset_ss ss = power_control_offset_ss::dB3; - builder.set_tx_power_info_parameters(profile_nr, ss); + builder.set_tx_power_info_parameters(power, ss); ASSERT_EQ(ss, pdu.power_control_offset_ss_profile_nr); - ASSERT_EQ(profile_nr ? static_cast(profile_nr.value() + 8) : 255, pdu.power_control_offset_profile_nr); - } -} - -TEST(dl_csi_pdu_builder, valid_maintenance_v3_tx_power_parameters_passes) -{ - for (auto power : {0, -8}) { - dl_csi_rs_pdu pdu; - dl_csi_rs_pdu_builder builder(pdu); - - optional profile_sss; - if (power) { - profile_sss.emplace(power); - } - - builder.set_maintenance_v3_tx_power_info_parameters(profile_sss); - - ASSERT_EQ(profile_sss ? static_cast(profile_sss.value() * 1000.F) : -32768, - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss); + ASSERT_EQ(power, pdu.power_control_offset_profile_nr); } } diff --git a/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp b/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp index 7d3b413cd2..a20296a365 100644 --- a/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp @@ -124,48 +124,9 @@ TEST(dl_pdcch_pdu_builder, valid_dci_tx_power_parameters_passes) dl_pdcch_pdu_builder builder(pdu); dl_dci_pdu_builder builder_dci = builder.add_dl_dci(); - // Leave the optional power unset for -8 to test it is being set internally to -127. - optional power; - if (i != -8) { - power = i; - } + builder_dci.set_tx_power_info_parameter(i); - builder_dci.set_tx_power_info_parameter(power); - - ASSERT_EQ(power ? static_cast(power.value()) : -127, pdu.dl_dci[0].power_control_offset_ss_profile_nr); - } -} - -TEST(dl_pdcch_pdu_builder, valid_maintenance_v3_dci_parameters_passes) -{ - bool collocated = true; - - for (int dmrs_power = -4; dmrs_power != 4; ++dmrs_power) { - for (int data_power = -4; data_power != 4; ++data_power) { - dl_pdcch_pdu pdu; - dl_pdcch_pdu_builder builder(pdu); - dl_dci_pdu_builder builder_dci = builder.add_dl_dci(); - - // Leave the optional power unset for 0 to test it is being set internally to -32768. - optional dmrs; - if (dmrs_power != 0) { - dmrs = dmrs_power; - } - - // Leave the optional power unset for 0 to test it is being set internally to -32768. - optional data; - if (data_power != 0) { - data = data_power; - } - - builder_dci.set_maintenance_v3_dci_parameters(collocated, dmrs, data); - - ASSERT_EQ(collocated, pdu.maintenance_v3.info[0].collocated_AL16_candidate); - ASSERT_EQ(dmrs ? static_cast(dmrs.value() * 1000) : -32768, - pdu.maintenance_v3.info[0].pdcch_dmrs_power_offset_profile_sss); - ASSERT_EQ(data ? static_cast(data.value() * 1000) : -32768, - pdu.maintenance_v3.info[0].pdcch_data_power_offset_profile_sss); - } + ASSERT_EQ(i, pdu.dl_dci[0].power_control_offset_ss_profile_nr); } } diff --git a/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp index ee4d39f7e5..0b30b72f07 100644 --- a/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp @@ -191,15 +191,11 @@ TEST(dl_pdsch_pdu_builder, valid_tx_power_info_parameters_passes) dl_pdsch_pdu pdu; dl_pdsch_pdu_builder builder(pdu); - nzp_csi_rs_epre_to_ssb ss_profile = nzp_csi_rs_epre_to_ssb::dB0; - optional p; - if (power != 16) { - p.emplace(power); - } + power_control_offset_ss ss_profile = power_control_offset_ss::dB0; - builder.set_tx_power_info_parameters(p, ss_profile); + builder.set_tx_power_info_parameters(power, ss_profile); - ASSERT_EQ(p ? static_cast(p.value() + 8) : 255, pdu.power_control_offset_profile_nr); + ASSERT_EQ(power, pdu.power_control_offset_profile_nr); ASSERT_EQ(ss_profile, pdu.power_control_offset_ss_profile_nr); } } @@ -293,30 +289,6 @@ TEST(dl_pdsch_pdu_builder, valid_maintenance_v3_csi_rm_parameters_passes) ASSERT_EQ(csi, pdu.pdsch_maintenance_v3.csi_for_rm); } -TEST(dl_pdsch_pdu_builder, valid_maintenance_v3_tx_power_info_parameters_passes) -{ - for (int power : {-33, -10, 0}) { - dl_pdsch_pdu pdu; - dl_pdsch_pdu_builder builder(pdu); - - optional dmrs; - if (power != -33) { - dmrs.emplace(power); - } - optional data; - if (power + 33 != 33) { - data.emplace(power + 33); - } - - builder.set_maintenance_v3_tx_power_info_parameters(dmrs, data); - - ASSERT_EQ(dmrs ? static_cast(dmrs.value() * 1000) : -32768, - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss); - ASSERT_EQ(data ? static_cast(data.value() * 1000) : -32768, - pdu.pdsch_maintenance_v3.pdsch_data_power_offset_profile_sss); - } -} - TEST(dl_pdsch_pdu_builder, valid_maintenance_v3_cbg_tx_crtl_parameters_passes) { for (auto cbg_per_tb : {2U, 4U, 6U, 8U}) { @@ -348,24 +320,6 @@ TEST(dl_pdsch_pdu_builder, valid_maintenance_v3_codeword_parameters_passes) ASSERT_EQ(1, pdu.pdsch_maintenance_v3.cbg_tx_information.size()); } -TEST(dl_pdsch_pdu_builder, valid_ptrs_maintenance_v3_tx_power_parameters_passes) -{ - for (int power : {-33, 0}) { - dl_pdsch_pdu pdu; - dl_pdsch_pdu_builder builder(pdu); - - optional ptrs; - if (power != -33) { - ptrs.emplace(power); - } - - builder.set_ptrs_maintenance_v3_tx_power_info_parameters(ptrs); - - ASSERT_EQ(ptrs ? static_cast(ptrs.value() * 1000) : -32768, - pdu.ptrs_maintenance_v3.pdsch_ptrs_power_offset_profile_sss); - } -} - TEST(dl_pdsch_pdu_builder, valid_maintenance_v4_basica_parameters_passes) { dl_pdsch_pdu pdu; diff --git a/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp b/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp index 973b319272..f9024c37de 100644 --- a/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp @@ -63,28 +63,6 @@ TEST(dl_ssb_pdu_builder, valid_maintenance_v3_parameters_passes) ASSERT_EQ(Lmax, v3.L_max); } -TEST(dl_ssb_pdu_builder, valid_maintenance_v3_tx_power_parameters_passes) -{ - for (bool enable : {true, false}) { - dl_ssb_pdu pdu; - dl_ssb_pdu_builder builder(pdu); - - optional pss_profile_sss; - optional ss_power_block; - if (enable) { - pss_profile_sss.emplace(18.307); - ss_power_block.emplace(-8.607); - } - - builder.set_maintenance_v3_tx_power_info(ss_power_block, pss_profile_sss); - - const dl_ssb_maintenance_v3& v3 = pdu.ssb_maintenance_v3; - - ASSERT_EQ(enable ? 18307 : -32768, v3.beta_pss_profile_sss); - ASSERT_EQ(enable ? -860 : -32768, v3.ss_pbch_block_power_scaling); - } -} - TEST(dl_ssb_pdu_builder, valid_bch_payload_passes) { dl_ssb_pdu pdu; diff --git a/tests/unittests/fapi/message_builder_helpers.cpp b/tests/unittests/fapi/message_builder_helpers.cpp index 1e48083831..08001dccf2 100644 --- a/tests/unittests/fapi/message_builder_helpers.cpp +++ b/tests/unittests/fapi/message_builder_helpers.cpp @@ -157,23 +157,21 @@ dl_ssb_pdu unittest::build_valid_dl_ssb_pdu() { dl_ssb_pdu pdu; - pdu.phys_cell_id = generate_pci(); - pdu.beta_pss_profile_nr = beta_pss_profile_type::dB_0; - pdu.ssb_block_index = generate_block_index(); - pdu.ssb_subcarrier_offset = generate_subcarrier_offset(); - pdu.ssb_offset_pointA = generate_offset_point_A(); - pdu.bch_payload_flag = bch_payload_type::phy_full; - pdu.bch_payload.phy_mib_pdu.cell_barred = generate_bool(); - pdu.bch_payload.phy_mib_pdu.intrafreq_reselection = generate_bool(); - pdu.bch_payload.phy_mib_pdu.dmrs_typeA_position = static_cast(generate_bool()); - pdu.bch_payload.phy_mib_pdu.pdcch_config_sib1 = 43; - pdu.ssb_maintenance_v3.ssb_pdu_index = 0; - pdu.ssb_maintenance_v3.case_type = generate_case_pattern(); - pdu.ssb_maintenance_v3.scs = subcarrier_spacing::kHz240; - pdu.ssb_maintenance_v3.L_max = 4; - pdu.ssb_maintenance_v3.beta_pss_profile_sss = std::numeric_limits::min(); - pdu.ssb_maintenance_v3.ss_pbch_block_power_scaling = std::numeric_limits::min(); - pdu.precoding_and_beamforming = build_valid_tx_precoding_and_beamforming_pdu(); + pdu.phys_cell_id = generate_pci(); + pdu.beta_pss_profile_nr = beta_pss_profile_type::dB_0; + pdu.ssb_block_index = generate_block_index(); + pdu.ssb_subcarrier_offset = generate_subcarrier_offset(); + pdu.ssb_offset_pointA = generate_offset_point_A(); + pdu.bch_payload_flag = bch_payload_type::phy_full; + pdu.bch_payload.phy_mib_pdu.cell_barred = generate_bool(); + pdu.bch_payload.phy_mib_pdu.intrafreq_reselection = generate_bool(); + pdu.bch_payload.phy_mib_pdu.dmrs_typeA_position = static_cast(generate_bool()); + pdu.bch_payload.phy_mib_pdu.pdcch_config_sib1 = 43; + pdu.ssb_maintenance_v3.ssb_pdu_index = 0; + pdu.ssb_maintenance_v3.case_type = generate_case_pattern(); + pdu.ssb_maintenance_v3.scs = subcarrier_spacing::kHz240; + pdu.ssb_maintenance_v3.L_max = 4; + pdu.precoding_and_beamforming = build_valid_tx_precoding_and_beamforming_pdu(); return pdu; } @@ -215,8 +213,6 @@ dl_pdcch_pdu unittest::build_valid_dl_pdcch_pdu() dl_pdcch_pdu_maintenance_v3::maintenance_info& dci_v3 = pdu.maintenance_v3.info.back(); dci_v3.dci_index = 2; dci_v3.collocated_AL16_candidate = generate_bool(); - dci_v3.pdcch_data_power_offset_profile_sss = -32768; - dci_v3.pdcch_dmrs_power_offset_profile_sss = -32768; pdu.parameters_v4.params.emplace_back(); pdu.parameters_v4.params.back().nid_pdcch_dmrs = generate_uint16(); @@ -252,7 +248,7 @@ dl_pdsch_pdu unittest::build_valid_dl_pdsch_pdu() pdu.start_symbol_index = 3; pdu.nr_of_symbols = 5; pdu.power_control_offset_profile_nr = 6; - pdu.power_control_offset_ss_profile_nr = fapi::nzp_csi_rs_epre_to_ssb::dB3; + pdu.power_control_offset_ss_profile_nr = fapi::power_control_offset_ss::dB3; pdu.is_inline_tb_crc = fapi::inline_tb_crc_type::control_message; pdu.dl_dmrs_symb_pos = 0; pdu.precoding_and_beamforming = build_valid_tx_precoding_and_beamforming_pdu(); @@ -268,8 +264,6 @@ dl_pdsch_pdu unittest::build_valid_dl_pdsch_pdu() pdu.pdsch_maintenance_v3.num_coreset_rm_patterns = 0; pdu.pdsch_maintenance_v3.pdcch_pdu_index = 4; pdu.pdsch_maintenance_v3.dci_index = 3; - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = -32768; - pdu.pdsch_maintenance_v3.pdsch_data_power_offset_profile_sss = -32768; pdu.pdsch_maintenance_v3.max_num_cbg_per_tb = 4; // Maintenance v4 @@ -282,23 +276,22 @@ dl_csi_rs_pdu unittest::build_valid_dl_csi_pdu() { dl_csi_rs_pdu pdu; - pdu.scs = subcarrier_spacing::kHz15; - pdu.cp = cyclic_prefix::NORMAL; - pdu.start_rb = 23; - pdu.num_rbs = 28; - pdu.type = csi_rs_type::CSI_RS_NZP; - pdu.row = 1; - pdu.freq_domain = {1, 0, 0, 0, 0, 0}; - pdu.symb_L0 = 8; - pdu.symb_L1 = 7; - pdu.cdm_type = csi_rs_cdm_type::no_CDM; - pdu.freq_density = csi_rs_freq_density_type::three; - pdu.scramb_id = 123; - pdu.power_control_offset_profile_nr = 0; - pdu.power_control_offset_ss_profile_nr = nzp_csi_rs_epre_to_ssb::dB0; - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss = -32768; - pdu.csi_rs_maintenance_v3.csi_rs_pdu_index = 0; - pdu.precoding_and_beamforming = build_valid_tx_precoding_and_beamforming_pdu(); + pdu.scs = subcarrier_spacing::kHz15; + pdu.cp = cyclic_prefix::NORMAL; + pdu.start_rb = 23; + pdu.num_rbs = 28; + pdu.type = csi_rs_type::CSI_RS_NZP; + pdu.row = 1; + pdu.freq_domain = {1, 0, 0, 0, 0, 0}; + pdu.symb_L0 = 8; + pdu.symb_L1 = 7; + pdu.cdm_type = csi_rs_cdm_type::no_CDM; + pdu.freq_density = csi_rs_freq_density_type::three; + pdu.scramb_id = 123; + pdu.power_control_offset_profile_nr = 0; + pdu.power_control_offset_ss_profile_nr = power_control_offset_ss::dB0; + pdu.csi_rs_maintenance_v3.csi_rs_pdu_index = 0; + pdu.precoding_and_beamforming = build_valid_tx_precoding_and_beamforming_pdu(); return pdu; } diff --git a/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp b/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp index 55b90b8ba2..c9eee16e0b 100644 --- a/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp @@ -171,27 +171,13 @@ INSTANTIATE_TEST_SUITE_P(Power_control_offset, testing::Combine(testing::Values(pdu_field_data{ "Power control offset", [](dl_csi_rs_pdu& pdu, int value) { - pdu.power_control_offset_profile_nr = value; - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss = -32768; + pdu.power_control_offset_profile_nr = value; }}), - testing::Values(test_case_data{0, true}, - test_case_data{12, true}, - test_case_data{23, true}, - test_case_data{24, false}))); - -INSTANTIATE_TEST_SUITE_P(Power_control_offset_v3, - validate_csi_pdu_field, - testing::Combine(testing::Values(pdu_field_data{ - "Power control offset", - [](dl_csi_rs_pdu& pdu, int value) { - pdu.power_control_offset_profile_nr = 255; - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss = value; - }}), - testing::Values(test_case_data{static_cast(int16_t(-32767)), true}, + testing::Values(test_case_data{unsigned(-9), false}, + test_case_data{unsigned(-8), true}, test_case_data{0, true}, - test_case_data{32767, true}, - test_case_data{static_cast(int16_t(-32768)), - false}))); + test_case_data{15, true}, + test_case_data{16, false}))); INSTANTIATE_TEST_SUITE_P(Power_control_offset_SS_profile_NR, validate_csi_pdu_field, @@ -199,15 +185,14 @@ INSTANTIATE_TEST_SUITE_P(Power_control_offset_SS_profile_NR, "Power control offset SS profile NR", [](dl_csi_rs_pdu& pdu, int value) { pdu.power_control_offset_ss_profile_nr = - static_cast(value); - pdu.csi_rs_maintenance_v3.csi_rs_power_offset_profile_sss = -32768; + static_cast(value); }}), testing::Values(test_case_data{0, true}, test_case_data{1, true}, test_case_data{3, true}, test_case_data{4, false}, test_case_data{254, false}, - test_case_data{255, true}))); + test_case_data{255, false}))); /// Valid PDU should pass. TEST(validate_csi_pdu, valid_pdu_passes) diff --git a/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp b/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp index 088f8f2cd3..171c8acfb9 100644 --- a/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp @@ -309,33 +309,17 @@ INSTANTIATE_TEST_SUITE_P(aggregation_level, INSTANTIATE_TEST_SUITE_P(dmrs_power, validate_pdcch_pdu_field, testing::Combine(testing::Values(pdu_field_data{ - "DMRS Power offset", + "Power control offset SS", [](dl_pdcch_pdu& pdu, int value) { pdu.dl_dci.back().power_control_offset_ss_profile_nr = value; - pdu.maintenance_v3.info.back().pdcch_dmrs_power_offset_profile_sss = - -32768; }}), - testing::Values(test_case_data{static_cast(int16_t(-126)), false}, + testing::Values(test_case_data{static_cast(int16_t(-127)), false}, test_case_data{static_cast(int16_t(-9)), false}, test_case_data{static_cast(int16_t(-8)), true}, test_case_data{0, true}, test_case_data{8, true}, test_case_data{9, false}))); -INSTANTIATE_TEST_SUITE_P(dmrs_power_1, - validate_pdcch_pdu_field, - testing::Combine(testing::Values(pdu_field_data{ - "DMRS Power offset", - [](dl_pdcch_pdu& pdu, int value) { - pdu.dl_dci.back().power_control_offset_ss_profile_nr = -127; - pdu.maintenance_v3.info.back().pdcch_dmrs_power_offset_profile_sss = - value; - }}), - testing::Values(test_case_data{static_cast(int16_t(-32768)), false}, - test_case_data{static_cast(int16_t(-32767)), true}, - test_case_data{0, true}, - test_case_data{32767, true}))); - INSTANTIATE_TEST_SUITE_P( collocated_al16_candidate, validate_pdcch_pdu_field, diff --git a/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp index 9257fb974d..4a1a2e3b8c 100644 --- a/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp @@ -291,31 +291,15 @@ INSTANTIATE_TEST_SUITE_P(nof_symbols, INSTANTIATE_TEST_SUITE_P(profile_nr, validate_pdsch_pdu_field, testing::Combine(testing::Values(pdu_field_data{ - "Ratio PDSCH EPRE to NZP CSI-RSEPRE", + "Ratio PDSCH EPRE to NZP CSI-RS EPRE", [](dl_pdsch_pdu& pdu, int value) { - pdu.power_control_offset_profile_nr = value; - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = -32768; + pdu.power_control_offset_profile_nr = value; }}), - testing::Values(test_case_data{0, true}, - test_case_data{12, true}, - test_case_data{23, true}, - test_case_data{24, false}))); - -INSTANTIATE_TEST_SUITE_P(profile_nr_2, - validate_pdsch_pdu_field, - testing::Combine(testing::Values(pdu_field_data{ - "Ratio PDSCH EPRE to NZP CSI-RSEPRE", - [](dl_pdsch_pdu& pdu, int value) { - pdu.power_control_offset_profile_nr = 255; - pdu.power_control_offset_ss_profile_nr = - (value == -32768) ? srsran::fapi::nzp_csi_rs_epre_to_ssb::dB3 - : nzp_csi_rs_epre_to_ssb::L1_use_profile_sss; - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = value; - }}), - testing::Values(test_case_data{static_cast(int16_t(-32768)), false}, - test_case_data{static_cast(int16_t(-32767)), true}, + testing::Values(test_case_data{unsigned(-9), false}, + test_case_data{unsigned(-8), true}, test_case_data{0, true}, - test_case_data{32767, true}))); + test_case_data{15, true}, + test_case_data{16, false}))); INSTANTIATE_TEST_SUITE_P(offset_ss_profile_nr, validate_pdsch_pdu_field, @@ -323,28 +307,13 @@ INSTANTIATE_TEST_SUITE_P(offset_ss_profile_nr, "Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE", [](dl_pdsch_pdu& pdu, int value) { pdu.power_control_offset_ss_profile_nr = - static_cast(value); - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = -32768; + static_cast(value); }}), testing::Values(test_case_data{0, true}, test_case_data{2, true}, test_case_data{3, true}, - test_case_data{4, false}))); - -INSTANTIATE_TEST_SUITE_P(offset_ss_profile_nr_2, - validate_pdsch_pdu_field, - testing::Combine(testing::Values(pdu_field_data{ - "Ratio of NZP CSI-RS EPRE to SSB/PBCH block EPRE", - [](dl_pdsch_pdu& pdu, int value) { - pdu.power_control_offset_profile_nr = (value == -32768) ? 3 : 255; - pdu.power_control_offset_ss_profile_nr = - nzp_csi_rs_epre_to_ssb::L1_use_profile_sss; - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = value; - }}), - testing::Values(test_case_data{static_cast(int16_t(-32768)), false}, - test_case_data{static_cast(int16_t(-32767)), true}, - test_case_data{0, true}, - test_case_data{32767, true}))); + test_case_data{4, false}, + test_case_data{255, false}))); INSTANTIATE_TEST_SUITE_P( is_inline_tb_crc, @@ -580,10 +549,9 @@ TEST(validate_pdsch_pdu, invalid_pdu_fails) dl_pdsch_pdu pdu = build_valid_dl_pdsch_pdu(); // Force 3 errors. - pdu.bwp_size = 2690; - pdu.power_control_offset_profile_nr = 255; - pdu.pdsch_maintenance_v3.pdsch_dmrs_power_offset_profile_sss = -32768; - pdu.cws[0].qam_mod_order = 1; + pdu.bwp_size = 2690; + pdu.power_control_offset_profile_nr = 255; + pdu.cws[0].qam_mod_order = 1; validator_report report(0, 0); EXPECT_FALSE(validate_dl_pdsch_pdu(pdu, report)); // Assert 3 reports were generated. diff --git a/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp b/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp index b47c846cc7..caf6bb22ad 100644 --- a/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp @@ -61,14 +61,12 @@ INSTANTIATE_TEST_SUITE_P(pss, "Beta PSS profile NR", [](dl_ssb_pdu& pdu, int value) { pdu.beta_pss_profile_nr = static_cast(value); - pdu.ssb_maintenance_v3.beta_pss_profile_sss = - (value == 255) ? 0 : std::numeric_limits::min(); }}), testing::Values(test_case_data{0, true}, test_case_data{1, true}, test_case_data{2, false}, test_case_data{254, false}, - test_case_data{255, true}))); + test_case_data{255, false}))); INSTANTIATE_TEST_SUITE_P(pbch_block_index, validate_ssb_pdu_field, @@ -139,21 +137,6 @@ INSTANTIATE_TEST_SUITE_P(L_max, test_case_data{64, true}, test_case_data{65, false}))); -INSTANTIATE_TEST_SUITE_P(scaling_power, - validate_ssb_pdu_field, - testing::Combine(testing::Values(pdu_field_data{ - "Baseband power scaling applied to SS-PBCH", - [](dl_ssb_pdu& pdu, int value) { - pdu.ssb_maintenance_v3.ss_pbch_block_power_scaling = value; - }}), - testing::Values(test_case_data{static_cast(int16_t(-32768)), true}, - test_case_data{static_cast(int16_t(-32767)), false}, - test_case_data{static_cast(int16_t(-11001)), false}, - test_case_data{static_cast(int16_t(-11000)), true}, - test_case_data{0, true}, - test_case_data{12000, true}, - test_case_data{12001, false}))); - /// Valid PDU should pass. TEST(validate_ssb_pdu, valid_pdu_passes) { @@ -171,14 +154,13 @@ TEST(validate_ssb_pdu, invalid_pdu_fails) dl_ssb_pdu pdu = build_valid_dl_ssb_pdu(); // Force 3 errors. - pdu.phys_cell_id = 2000; - pdu.ssb_block_index = 100; - pdu.ssb_maintenance_v3.ss_pbch_block_power_scaling = -12000; + pdu.phys_cell_id = 2000; + pdu.ssb_block_index = 100; validator_report report(0, 0); EXPECT_FALSE(validate_dl_ssb_pdu(pdu, report)); // Assert 3 reports were generated. - EXPECT_EQ(report.reports.size(), 3u); + EXPECT_EQ(report.reports.size(), 2u); } /// Only build and run this test when asserts are available, as the death is caused by an assert. diff --git a/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp b/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp index f151758e68..20f75a6938 100644 --- a/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp +++ b/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp @@ -153,18 +153,12 @@ static void pdcch_conversion_benchmark() builder_dci.set_basic_parameters( to_rnti(0), nid_data_dist(gen), n_rnti_dist(gen), cce_dist(gen), aggregation_dist(gen)); - optional profile_nr; - profile_nr.emplace(power_dist(gen)); - builder_dci.set_tx_power_info_parameter(profile_nr); + builder_dci.set_tx_power_info_parameter(power_dist(gen)); builder_dci.get_tx_precoding_and_beamforming_pdu_builder().set_basic_parameters(275, 0).add_prg(0, {}); // Payload. dci_payload payload; builder_dci.set_payload(payload); - - optional profile_data; - optional profile_dmrs; - builder_dci.set_maintenance_v3_dci_parameters(true, profile_dmrs, profile_data); builder_dci.set_parameters_v4_dci(nid_dmrs_dist(gen)); pdcch_processor::pdu_t proc_pdu; diff --git a/tests/unittests/fapi_adaptor/mac/messages/dl_ssb_pdu_test.cpp b/tests/unittests/fapi_adaptor/mac/messages/dl_ssb_pdu_test.cpp index 2e9f1f851c..c836082a5b 100644 --- a/tests/unittests/fapi_adaptor/mac/messages/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/mac/messages/dl_ssb_pdu_test.cpp @@ -46,8 +46,6 @@ TEST(mac_fapi_ssb_pdu_conversor_test, valid_pdu_should_pass) ASSERT_EQ(static_cast(pdu.ssb_case), static_cast(fapi_pdu.ssb_maintenance_v3.case_type)); ASSERT_EQ(pdu.L_max, fapi_pdu.ssb_maintenance_v3.L_max); ASSERT_EQ(static_cast(pdu.scs), static_cast(fapi_pdu.ssb_maintenance_v3.scs)); - ASSERT_EQ(std::numeric_limits::min(), fapi_pdu.ssb_maintenance_v3.beta_pss_profile_sss); - ASSERT_EQ(std::numeric_limits::min(), fapi_pdu.ssb_maintenance_v3.ss_pbch_block_power_scaling); // MIB. ASSERT_EQ(fapi::bch_payload_type::phy_full, fapi_pdu.bch_payload_flag); diff --git a/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt b/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt index 07ad886de9..487a56c762 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt +++ b/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt @@ -21,16 +21,16 @@ set_directory_properties(PROPERTIES LABELS "fapi_adaptor") add_executable(fapi_phy_ssb_adaptor_test dl_ssb_pdu_test.cpp) -target_link_libraries(fapi_phy_ssb_adaptor_test srsran_fapi_phy_message_adaptors srslog) -add_test(fapi_phy_ssb_adaptor_test fapi_phy_ssb_adaptor_test) +target_link_libraries(fapi_phy_ssb_adaptor_test srsran_fapi_phy_message_adaptors srslog gtest gtest_main) +gtest_discover_tests(fapi_phy_ssb_adaptor_test) add_executable(fapi_phy_pdcch_adaptor_test dl_pdcch_pdu_test.cpp) -target_link_libraries(fapi_phy_pdcch_adaptor_test srsran_fapi_phy_message_adaptors srsran_fapi_precoding_matrix_tools srsran_ran srslog) -add_test(fapi_phy_pdcch_adaptor_test fapi_phy_pdcch_adaptor_test) +target_link_libraries(fapi_phy_pdcch_adaptor_test srsran_fapi_phy_message_adaptors srsran_fapi_precoding_matrix_tools srsran_ran srslog gtest gtest_main) +gtest_discover_tests(fapi_phy_pdcch_adaptor_test) add_executable(fapi_phy_pdsch_adaptor_test dl_pdsch_pdu_test.cpp) -target_link_libraries(fapi_phy_pdsch_adaptor_test srsran_fapi_phy_message_adaptors srsran_upper_phy_support srslog) -add_test(fapi_phy_pdsch_adaptor_test fapi_phy_pdsch_adaptor_test) +target_link_libraries(fapi_phy_pdsch_adaptor_test srsran_fapi_phy_message_adaptors srsran_upper_phy_support srslog gtest gtest_main) +gtest_discover_tests(fapi_phy_pdsch_adaptor_test) add_executable(fapi_phy_prach_adaptor_test ul_prach_pdu_test.cpp) target_link_libraries(fapi_phy_prach_adaptor_test srsran_fapi_phy_message_adaptors gtest gtest_main srsran_fapi_message_builder_test_helpers srslog) diff --git a/tests/unittests/fapi_adaptor/phy/messages/dl_pdcch_pdu_test.cpp b/tests/unittests/fapi_adaptor/phy/messages/dl_pdcch_pdu_test.cpp index b950e8019e..7d1affa98f 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/dl_pdcch_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/messages/dl_pdcch_pdu_test.cpp @@ -25,7 +25,7 @@ #include "srsran/fapi_adaptor/precoding_matrix_table_generator.h" #include "srsran/srsvec/bit.h" #include "srsran/support/math_utils.h" -#include "srsran/support/test_utils.h" +#include #include using namespace srsran; @@ -33,7 +33,7 @@ using namespace fapi_adaptor; static std::mt19937 gen(0); -static void pdcch_conversion_test() +TEST(fapi_to_phy_pdcch_conversion_test, valid_pdu_conversion_success) { // Random generators. std::uniform_int_distribution sfn_dist(0, 1023); @@ -48,7 +48,6 @@ static void pdcch_conversion_test() std::uniform_int_distribution aggregation_dist(0, 4); std::uniform_int_distribution nid_dmrs_dist(0, 65535); std::uniform_int_distribution nid_data_dist(0, 65535); - std::uniform_real_distribution power_dmrs_dist(-32.767, 32.767); auto pm_tools = generate_precoding_matrix_tables(1); const precoding_matrix_repository& pm_repo = *std::get>(pm_tools); @@ -61,7 +60,7 @@ static void pdcch_conversion_test() for (auto type : {fapi::pdcch_coreset_type::pbch_or_coreset0, fapi::pdcch_coreset_type::other}) { for (auto precoder : {coreset_configuration::precoder_granularity_type::same_as_reg_bundle, coreset_configuration::precoder_granularity_type::all_contiguous_rbs}) { - for (int power_nr = -9; power_nr != -7; ++power_nr) { + for (int power_nr = -8; power_nr != -7; ++power_nr) { for (int power = -33; power != 3; power += 3) { unsigned sfn = sfn_dist(gen); unsigned slot = slot_dist(gen); @@ -75,7 +74,6 @@ static void pdcch_conversion_test() unsigned aggregation = pow2(aggregation_dist(gen)); unsigned nid_dmrs = nid_dmrs_dist(gen); unsigned nid_data = nid_data_dist(gen); - float power_dmrs = power_dmrs_dist(gen); fapi::dl_pdcch_pdu pdu; fapi::dl_pdcch_pdu_builder builder(pdu); @@ -100,28 +98,14 @@ static void pdcch_conversion_test() auto builder_dci = builder.add_dl_dci(); builder_dci.set_basic_parameters(to_rnti(0), nid_data, n_rnti, cce, aggregation); - optional profile_nr; - optional profile_dmrs; - if (power_nr != -9) { - profile_nr.emplace(power_nr); - } else { - profile_dmrs.emplace(power_dmrs); - } - builder_dci.set_tx_power_info_parameter(profile_nr); + builder_dci.set_tx_power_info_parameter(power_nr); builder_dci.get_tx_precoding_and_beamforming_pdu_builder().set_basic_parameters(275, 0).add_prg(0, {}); // Payload. dci_payload payload = {1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; builder_dci.set_payload(payload); - - optional profile_data; - if (power != -33) { - profile_data.emplace(power); - } - - builder_dci.set_maintenance_v3_dci_parameters(true, profile_dmrs, profile_data); builder_dci.set_parameters_v4_dci(nid_dmrs); pdcch_processor::pdu_t proc_pdu; @@ -129,61 +113,57 @@ static void pdcch_conversion_test() convert_pdcch_fapi_to_phy(proc_pdu, pdu, sfn, slot, 0, pm_repo); // Test basic parameters. - TESTASSERT_EQ(sfn, proc_pdu.slot.sfn()); - TESTASSERT_EQ(slot, proc_pdu.slot.slot_index()); - TESTASSERT_EQ(cp, proc_pdu.cp.value); + ASSERT_EQ(sfn, proc_pdu.slot.sfn()); + ASSERT_EQ(slot, proc_pdu.slot.slot_index()); + ASSERT_EQ(cp, proc_pdu.cp.value); // Test coreset parameters. - TESTASSERT_EQ(bwp_size, proc_pdu.coreset.bwp_size_rb); - TESTASSERT_EQ(bwp_start, proc_pdu.coreset.bwp_start_rb); - TESTASSERT_EQ(start_symbol_index, proc_pdu.coreset.start_symbol_index); - TESTASSERT_EQ(duration_symbol, proc_pdu.coreset.duration); + ASSERT_EQ(bwp_size, proc_pdu.coreset.bwp_size_rb); + ASSERT_EQ(bwp_start, proc_pdu.coreset.bwp_start_rb); + ASSERT_EQ(start_symbol_index, proc_pdu.coreset.start_symbol_index); + ASSERT_EQ(duration_symbol, proc_pdu.coreset.duration); if (type == fapi::pdcch_coreset_type::pbch_or_coreset0) { - TESTASSERT(proc_pdu.coreset.cce_to_reg_mapping == - pdcch_processor::cce_to_reg_mapping_type::CORESET0); - TESTASSERT_EQ(0, proc_pdu.coreset.reg_bundle_size); - TESTASSERT_EQ(0, proc_pdu.coreset.interleaver_size); - TESTASSERT_EQ(shift_index, proc_pdu.coreset.shift_index); + ASSERT_TRUE(proc_pdu.coreset.cce_to_reg_mapping == + pdcch_processor::cce_to_reg_mapping_type::CORESET0); + ASSERT_EQ(0, proc_pdu.coreset.reg_bundle_size); + ASSERT_EQ(0, proc_pdu.coreset.interleaver_size); + ASSERT_EQ(shift_index, proc_pdu.coreset.shift_index); } else { if (cce_reg_mapping == fapi::cce_to_reg_mapping_type::non_interleaved) { - TESTASSERT(proc_pdu.coreset.cce_to_reg_mapping == - pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED); - TESTASSERT_EQ(0, proc_pdu.coreset.reg_bundle_size); - TESTASSERT_EQ(0, proc_pdu.coreset.interleaver_size); - TESTASSERT_EQ(0, proc_pdu.coreset.shift_index); + ASSERT_TRUE(proc_pdu.coreset.cce_to_reg_mapping == + pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED); + ASSERT_EQ(0, proc_pdu.coreset.reg_bundle_size); + ASSERT_EQ(0, proc_pdu.coreset.interleaver_size); + ASSERT_EQ(0, proc_pdu.coreset.shift_index); } else { - TESTASSERT(proc_pdu.coreset.cce_to_reg_mapping == - pdcch_processor::cce_to_reg_mapping_type::INTERLEAVED); - TESTASSERT_EQ(reg_bundle, proc_pdu.coreset.reg_bundle_size); - TESTASSERT_EQ(interleaver_size, proc_pdu.coreset.interleaver_size); - TESTASSERT_EQ(shift_index, proc_pdu.coreset.shift_index); + ASSERT_TRUE(proc_pdu.coreset.cce_to_reg_mapping == + pdcch_processor::cce_to_reg_mapping_type::INTERLEAVED); + ASSERT_EQ(reg_bundle, proc_pdu.coreset.reg_bundle_size); + ASSERT_EQ(interleaver_size, proc_pdu.coreset.interleaver_size); + ASSERT_EQ(shift_index, proc_pdu.coreset.shift_index); } } // Test DCI. - TESTASSERT_EQ(n_rnti, proc_pdu.dci.n_rnti); - TESTASSERT_EQ(cce, proc_pdu.dci.cce_index); - TESTASSERT_EQ(aggregation, proc_pdu.dci.aggregation_level); - TESTASSERT_EQ(nid_data, proc_pdu.dci.n_id_pdcch_data); - TESTASSERT_EQ(nid_dmrs, proc_pdu.dci.n_id_pdcch_dmrs); + ASSERT_EQ(n_rnti, proc_pdu.dci.n_rnti); + ASSERT_EQ(cce, proc_pdu.dci.cce_index); + ASSERT_EQ(aggregation, proc_pdu.dci.aggregation_level); + ASSERT_EQ(nid_data, proc_pdu.dci.n_id_pdcch_data); + ASSERT_EQ(nid_dmrs, proc_pdu.dci.n_id_pdcch_dmrs); // Test powers. - TESTASSERT(std::fabs((profile_nr ? profile_nr.value() : profile_dmrs.value()) - - proc_pdu.dci.dmrs_power_offset_dB) < 0.001F); - TESTASSERT(std::fabs((profile_data ? profile_data.value() - : profile_nr ? profile_nr.value() - : profile_dmrs.value()) - - proc_pdu.dci.data_power_offset_dB) < 0.001F); + ASSERT_TRUE(std::fabs((power_nr - proc_pdu.dci.dmrs_power_offset_dB)) < 0.001F); + ASSERT_TRUE(std::fabs((power_nr - proc_pdu.dci.data_power_offset_dB)) < 0.001F); // Test vectors. for (unsigned i = 0, e = payload.size(); i != e; ++i) { - TESTASSERT_EQ(payload.test(i), bool(proc_pdu.dci.payload[i])); + ASSERT_EQ(payload.test(i), bool(proc_pdu.dci.payload[i])); } // Test frequency domain resources. for (unsigned i = 0, e = 45; i != e; ++i) { - TESTASSERT_EQ(freq_domain.test(i), bool(proc_pdu.coreset.frequency_resources.test(i))); + ASSERT_EQ(freq_domain.test(i), bool(proc_pdu.coreset.frequency_resources.test(i))); } } } @@ -194,9 +174,3 @@ static void pdcch_conversion_test() } } } - -int main() -{ - pdcch_conversion_test(); - fmt::print("PDCCH FAPI to PHY message conversion OK\n"); -} diff --git a/tests/unittests/fapi_adaptor/phy/messages/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi_adaptor/phy/messages/dl_pdsch_pdu_test.cpp index 1dadc8c6c2..1d63fffc3a 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/messages/dl_pdsch_pdu_test.cpp @@ -23,7 +23,7 @@ #include "srsran/fapi/message_builders.h" #include "srsran/fapi_adaptor/phy/messages/pdsch.h" #include "srsran/fapi_adaptor/precoding_matrix_table_generator.h" -#include "srsran/support/test_utils.h" +#include #include using namespace srsran; @@ -31,45 +31,33 @@ using namespace fapi_adaptor; static std::mt19937 gen(0); -static float calculate_ratio_pdsch_data_to_sss_dB(int profile_nr, - fapi::nzp_csi_rs_epre_to_ssb profile_ss_nr, - float power_data_profile_sss) +static float calculate_ratio_pdsch_data_to_sss_dB(int profile_nr, fapi::power_control_offset_ss profile_ss_nr) { - if (profile_ss_nr != fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss) { - float power_control_offset_ss_dB = 0.0F; - switch (profile_ss_nr) { - case fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3: - power_control_offset_ss_dB = -3.F; - break; - case fapi::nzp_csi_rs_epre_to_ssb::dB0: - power_control_offset_ss_dB = .0F; - break; - case fapi::nzp_csi_rs_epre_to_ssb::dB3: - power_control_offset_ss_dB = 3.F; - break; - case fapi::nzp_csi_rs_epre_to_ssb::dB6: - default: - power_control_offset_ss_dB = 6.F; - break; - } - - return static_cast(profile_nr) + power_control_offset_ss_dB; + float power_control_offset_ss_dB = 0.0F; + switch (profile_ss_nr) { + case fapi::power_control_offset_ss::dB_minus_3: + power_control_offset_ss_dB = -3.F; + break; + case fapi::power_control_offset_ss::dB0: + power_control_offset_ss_dB = .0F; + break; + case fapi::power_control_offset_ss::dB3: + power_control_offset_ss_dB = 3.F; + break; + case fapi::power_control_offset_ss::dB6: + default: + power_control_offset_ss_dB = 6.F; + break; } - return power_data_profile_sss; + return static_cast(profile_nr) + power_control_offset_ss_dB; } -static float calculate_ratio_pdsch_dmrs_to_sss_dB(int dmrs_power_profile_sss, - float ratio_pdsch_data_to_sss_dB, - unsigned num_dmrs_cdm_grps_no_data) +static float calculate_ratio_pdsch_dmrs_to_sss_dB(float ratio_pdsch_data_to_sss_dB, unsigned num_dmrs_cdm_grps_no_data) { - if (dmrs_power_profile_sss == -33) { - static const std::array beta_dmrs_values = {NAN, 0, -3, -4.77}; + static const std::array beta_dmrs_values = {NAN, 0, -3, -4.77}; - return ratio_pdsch_data_to_sss_dB + beta_dmrs_values[num_dmrs_cdm_grps_no_data]; - } - - return static_cast(dmrs_power_profile_sss); + return ratio_pdsch_data_to_sss_dB + beta_dmrs_values[num_dmrs_cdm_grps_no_data]; } static rb_allocation make_freq_allocation(fapi::pdsch_trans_type trasn_type, @@ -127,7 +115,7 @@ static rb_allocation make_freq_allocation(fapi::pdsch_trans_type trasn_t return result; } -static void pdsch_conversion_test() +TEST(fapi_to_phy_pdsch_conversion_test, valid_pdu_conversion_success) { // Random generators. std::uniform_int_distribution sfn_dist(0, 1023); @@ -158,169 +146,142 @@ static void pdsch_conversion_test() for (auto vrb_prb_mapping : {fapi::vrb_to_prb_mapping_type::interleaved_rb_size4, fapi::vrb_to_prb_mapping_type::interleaved_rb_size2}) { // Iterate all possible NZP-CSI-RS to SSS ratios. L1_use_profile_sss means SSS profile mode. - for (auto power_ss_profile_nr : {fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3, - fapi::nzp_csi_rs_epre_to_ssb::dB0, - fapi::nzp_csi_rs_epre_to_ssb::dB3, - fapi::nzp_csi_rs_epre_to_ssb::dB6, - fapi::nzp_csi_rs_epre_to_ssb::dB6, - fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss}) { + for (auto power_ss_profile_nr : {fapi::power_control_offset_ss::dB_minus_3, + fapi::power_control_offset_ss::dB0, + fapi::power_control_offset_ss::dB3, + fapi::power_control_offset_ss::dB6}) { // Iterate possible PDSCH data to NZP-CSI-RS ratios for Profile NR. It is ignored when // power_ss_profile_nr is L1_use_profile_sss. for (int power_profile_nr = -8; power_profile_nr != -7; ++power_profile_nr) { - // Iterate possible PDSCH DMRS to SSS ratios. -33 for Profile NR. - for (int dmrs_power_profile_sss = -33; dmrs_power_profile_sss != -30; ++dmrs_power_profile_sss) { - for (auto trasn_type : {fapi::pdsch_trans_type::non_interleaved_other, - fapi::pdsch_trans_type::non_interleaved_common_ss, - fapi::pdsch_trans_type::interleaved_other, - fapi::pdsch_trans_type::interleaved_common_type0_coreset0, - fapi::pdsch_trans_type::interleaved_common_any_coreset0_present, - fapi::pdsch_trans_type::interleaved_common_any_coreset0_not_present}) { - for (auto ldpc_graph : {ldpc_base_graph_type::BG1, ldpc_base_graph_type::BG2}) { - unsigned sfn = sfn_dist(gen); - unsigned slot = slot_dist(gen); - rnti_t rnti = to_rnti(rnti_dist(gen)); - unsigned bwp_size = bwp_size_dist(gen); - unsigned bwp_start = bwp_start_dist(gen); - unsigned nid_pdsch = nid_pdsch_dist(gen); - unsigned scrambling_id = dmrs_scrambling_dist(gen); - unsigned scrambling_id_complement = dmrs_scrambling_dist(gen); - bool n_scid = binary_dist(gen); - unsigned dmrs_cdm_grps_no_data = dmrs_cdm_grps_no_data_dist(gen); - unsigned start_symbol_index = start_symbol_index_dist(gen); - unsigned nr_of_symbols = nr_of_symbols_dist(gen); - unsigned coreset_start = bwp_size_dist(gen); - unsigned initial_bwp_size = bwp_size_dist(gen); - units::bytes tb_size_lbrm_bytes{50}; - unsigned dl_dmrs_symbol = rnti_dist(gen); - unsigned rb_size = nr_of_symbols_dist(gen); - unsigned rb_start = start_symbol_index_dist(gen); - float power_data_profile_sss = 1000.0F * std::round(power_dist(gen) / 1000.0F); - - std::array rb_bitmap = {}; - - fapi::dl_pdsch_pdu pdu; - fapi::dl_pdsch_pdu_builder builder(pdu); - - builder.set_basic_parameters(rnti); - - // Always work with the biggest numerology. - builder.set_bwp_parameters(bwp_size, bwp_start, subcarrier_spacing::kHz240, cyclic_p); - builder.set_codeword_information_parameters(nid_pdsch, 0, 0, ref_point); - builder.set_dmrs_parameters(dl_dmrs_symbol, - config_type, - scrambling_id, - scrambling_id_complement, - low_papr, - n_scid, - dmrs_cdm_grps_no_data, - 0); - - auto builder_cw = builder.add_codeword(); - - unsigned target_code = 2; - unsigned qam_mod = 2; - unsigned mcs = 20; - unsigned mcs_table = 1; - unsigned rv_index = 0; - units::bytes tb_size{42}; - - builder_cw.set_basic_parameters(target_code, qam_mod, mcs, mcs_table, rv_index, tb_size); - - if (resource_alloc == fapi::resource_allocation_type::type_0) { - builder.set_pdsch_allocation_in_frequency_type_0({rb_bitmap}, vrb_prb_mapping); - } else { - builder.set_pdsch_allocation_in_frequency_type_1(rb_start, rb_size, vrb_prb_mapping); - } - - builder.set_pdsch_allocation_in_time_parameters(start_symbol_index, nr_of_symbols); - - optional profile_nr; - optional data_profile_sss; - optional dmrs_profile_sss; - if (power_ss_profile_nr != fapi::nzp_csi_rs_epre_to_ssb::L1_use_profile_sss) { - profile_nr.emplace(power_profile_nr); - } else { - data_profile_sss.emplace(power_data_profile_sss); - } - if (dmrs_power_profile_sss != -33) { - dmrs_profile_sss.emplace(dmrs_power_profile_sss); - } - - builder.set_tx_power_info_parameters(profile_nr, power_ss_profile_nr); - - // :TODO: not filling CBG to retx control parameters. - - builder.set_maintenance_v3_bwp_parameters(trasn_type, coreset_start, initial_bwp_size); - builder.set_maintenance_v3_codeword_parameters(ldpc_graph, tb_size_lbrm_bytes, 0, 0); - builder.set_maintenance_v3_tx_power_info_parameters(dmrs_profile_sss, data_profile_sss); - builder.get_tx_precoding_and_beamforming_pdu_builder().add_prg(0, {}).set_basic_parameters(51, - 0); - - pdsch_processor::pdu_t proc_pdu; - convert_pdsch_fapi_to_phy(proc_pdu, pdu, sfn, slot, {}, pm_repo); - - // Test basic parameters. - TESTASSERT_EQ(sfn, proc_pdu.slot.sfn()); - TESTASSERT_EQ(slot, proc_pdu.slot.slot_index()); - TESTASSERT_EQ(static_cast(cyclic_p), static_cast(proc_pdu.cp.value)); - - TESTASSERT_EQ(to_value(rnti), proc_pdu.rnti); - TESTASSERT_EQ(bwp_size, proc_pdu.bwp_size_rb); - TESTASSERT_EQ(bwp_start, proc_pdu.bwp_start_rb); - - // Codeword. - TESTASSERT_EQ(static_cast(qam_mod), proc_pdu.codewords[0].modulation); - TESTASSERT_EQ(rv_index, proc_pdu.codewords[0].rv); - - TESTASSERT_EQ(nid_pdsch, proc_pdu.n_id); - - for (unsigned i = 0; i != 14; ++i) { - TESTASSERT_EQ(((dl_dmrs_symbol >> i) & 1U) == 1U, proc_pdu.dmrs_symbol_mask.test(i)); - } - - TESTASSERT_EQ(static_cast(ref_point), static_cast(proc_pdu.ref_point)); - TESTASSERT(dmrs_type((config_type == dmrs_config_type::type1) - ? dmrs_type::options::TYPE1 - : dmrs_type::options::TYPE2) == proc_pdu.dmrs); - TESTASSERT_EQ(scrambling_id, proc_pdu.scrambling_id); - TESTASSERT_EQ(n_scid, proc_pdu.n_scid); - TESTASSERT_EQ(dmrs_cdm_grps_no_data, proc_pdu.nof_cdm_groups_without_data); - TESTASSERT_EQ(start_symbol_index, proc_pdu.start_symbol_index); - TESTASSERT_EQ(nr_of_symbols, proc_pdu.nof_symbols); - - // Powers. - float ratio_pdsch_data_to_sss_dB = calculate_ratio_pdsch_data_to_sss_dB( - power_profile_nr, power_ss_profile_nr, power_data_profile_sss); - float ratio_pdsch_dmrs_to_sss_dB = calculate_ratio_pdsch_dmrs_to_sss_dB( - dmrs_power_profile_sss, ratio_pdsch_data_to_sss_dB, dmrs_cdm_grps_no_data); - - TESTASSERT(std::fabs(ratio_pdsch_dmrs_to_sss_dB - proc_pdu.ratio_pdsch_dmrs_to_sss_dB) < 0.001F, - "PDSCH DMRS to SSS power ratio {} is too far from expected {}.", - proc_pdu.ratio_pdsch_dmrs_to_sss_dB, - ratio_pdsch_dmrs_to_sss_dB); - TESTASSERT(std::fabs(ratio_pdsch_data_to_sss_dB - proc_pdu.ratio_pdsch_data_to_sss_dB) < 0.001F, - "PDSCH Data to SSS power ratio {} is too far from expected {}.", - proc_pdu.ratio_pdsch_data_to_sss_dB, - ratio_pdsch_data_to_sss_dB); - - // Frequency domain allocation. - rb_allocation freq_allocation = make_freq_allocation(trasn_type, - bwp_start, - bwp_size, - coreset_start, - initial_bwp_size, - vrb_prb_mapping, - resource_alloc, - rb_bitmap, - rb_start, - rb_size); - TESTASSERT(freq_allocation == proc_pdu.freq_alloc); - - TESTASSERT_EQ(ldpc_graph, proc_pdu.ldpc_base_graph); - TESTASSERT_EQ(tb_size_lbrm_bytes.value(), proc_pdu.tbs_lbrm_bytes); - - // :TODO: re_pattern. + for (auto trasn_type : {fapi::pdsch_trans_type::non_interleaved_other, + fapi::pdsch_trans_type::non_interleaved_common_ss, + fapi::pdsch_trans_type::interleaved_other, + fapi::pdsch_trans_type::interleaved_common_type0_coreset0, + fapi::pdsch_trans_type::interleaved_common_any_coreset0_present, + fapi::pdsch_trans_type::interleaved_common_any_coreset0_not_present}) { + for (auto ldpc_graph : {ldpc_base_graph_type::BG1, ldpc_base_graph_type::BG2}) { + unsigned sfn = sfn_dist(gen); + unsigned slot = slot_dist(gen); + rnti_t rnti = to_rnti(rnti_dist(gen)); + unsigned bwp_size = bwp_size_dist(gen); + unsigned bwp_start = bwp_start_dist(gen); + unsigned nid_pdsch = nid_pdsch_dist(gen); + unsigned scrambling_id = dmrs_scrambling_dist(gen); + unsigned scrambling_id_complement = dmrs_scrambling_dist(gen); + bool n_scid = binary_dist(gen); + unsigned dmrs_cdm_grps_no_data = dmrs_cdm_grps_no_data_dist(gen); + unsigned start_symbol_index = start_symbol_index_dist(gen); + unsigned nr_of_symbols = nr_of_symbols_dist(gen); + unsigned coreset_start = bwp_size_dist(gen); + unsigned initial_bwp_size = bwp_size_dist(gen); + units::bytes tb_size_lbrm_bytes{50}; + unsigned dl_dmrs_symbol = rnti_dist(gen); + unsigned rb_size = nr_of_symbols_dist(gen); + unsigned rb_start = start_symbol_index_dist(gen); + + std::array rb_bitmap = {}; + + fapi::dl_pdsch_pdu pdu; + fapi::dl_pdsch_pdu_builder builder(pdu); + + builder.set_basic_parameters(rnti); + + // Always work with the biggest numerology. + builder.set_bwp_parameters(bwp_size, bwp_start, subcarrier_spacing::kHz240, cyclic_p); + builder.set_codeword_information_parameters(nid_pdsch, 0, 0, ref_point); + builder.set_dmrs_parameters(dl_dmrs_symbol, + config_type, + scrambling_id, + scrambling_id_complement, + low_papr, + n_scid, + dmrs_cdm_grps_no_data, + 0); + + auto builder_cw = builder.add_codeword(); + + unsigned target_code = 2; + unsigned qam_mod = 2; + unsigned mcs = 20; + unsigned mcs_table = 1; + unsigned rv_index = 0; + units::bytes tb_size{42}; + + builder_cw.set_basic_parameters(target_code, qam_mod, mcs, mcs_table, rv_index, tb_size); + + if (resource_alloc == fapi::resource_allocation_type::type_0) { + builder.set_pdsch_allocation_in_frequency_type_0({rb_bitmap}, vrb_prb_mapping); + } else { + builder.set_pdsch_allocation_in_frequency_type_1(rb_start, rb_size, vrb_prb_mapping); + } + + builder.set_pdsch_allocation_in_time_parameters(start_symbol_index, nr_of_symbols); + builder.set_tx_power_info_parameters(power_profile_nr, power_ss_profile_nr); + + // :TODO: not filling CBG to retx control parameters. + + builder.set_maintenance_v3_bwp_parameters(trasn_type, coreset_start, initial_bwp_size); + builder.set_maintenance_v3_codeword_parameters(ldpc_graph, tb_size_lbrm_bytes, 0, 0); + builder.get_tx_precoding_and_beamforming_pdu_builder().add_prg(0, {}).set_basic_parameters(51, 0); + + pdsch_processor::pdu_t proc_pdu; + convert_pdsch_fapi_to_phy(proc_pdu, pdu, sfn, slot, {}, pm_repo); + + // Test basic parameters. + ASSERT_EQ(sfn, proc_pdu.slot.sfn()); + ASSERT_EQ(slot, proc_pdu.slot.slot_index()); + ASSERT_EQ(static_cast(cyclic_p), static_cast(proc_pdu.cp.value)); + + ASSERT_EQ(to_value(rnti), proc_pdu.rnti); + ASSERT_EQ(bwp_size, proc_pdu.bwp_size_rb); + ASSERT_EQ(bwp_start, proc_pdu.bwp_start_rb); + + // Codeword. + ASSERT_EQ(static_cast(qam_mod), proc_pdu.codewords[0].modulation); + ASSERT_EQ(rv_index, proc_pdu.codewords[0].rv); + + ASSERT_EQ(nid_pdsch, proc_pdu.n_id); + + for (unsigned i = 0; i != 14; ++i) { + ASSERT_EQ(((dl_dmrs_symbol >> i) & 1U) == 1U, proc_pdu.dmrs_symbol_mask.test(i)); } + + ASSERT_EQ(static_cast(ref_point), static_cast(proc_pdu.ref_point)); + ASSERT_TRUE(dmrs_type((config_type == dmrs_config_type::type1) + ? dmrs_type::options::TYPE1 + : dmrs_type::options::TYPE2) == proc_pdu.dmrs); + ASSERT_EQ(scrambling_id, proc_pdu.scrambling_id); + ASSERT_EQ(n_scid, proc_pdu.n_scid); + ASSERT_EQ(dmrs_cdm_grps_no_data, proc_pdu.nof_cdm_groups_without_data); + ASSERT_EQ(start_symbol_index, proc_pdu.start_symbol_index); + ASSERT_EQ(nr_of_symbols, proc_pdu.nof_symbols); + + // Powers. + float ratio_pdsch_data_to_sss_dB = + calculate_ratio_pdsch_data_to_sss_dB(power_profile_nr, power_ss_profile_nr); + float ratio_pdsch_dmrs_to_sss_dB = + calculate_ratio_pdsch_dmrs_to_sss_dB(ratio_pdsch_data_to_sss_dB, dmrs_cdm_grps_no_data); + + ASSERT_FLOAT_EQ(ratio_pdsch_dmrs_to_sss_dB, proc_pdu.ratio_pdsch_dmrs_to_sss_dB); + ASSERT_FLOAT_EQ(ratio_pdsch_data_to_sss_dB, proc_pdu.ratio_pdsch_data_to_sss_dB); + + // Frequency domain allocation. + rb_allocation freq_allocation = make_freq_allocation(trasn_type, + bwp_start, + bwp_size, + coreset_start, + initial_bwp_size, + vrb_prb_mapping, + resource_alloc, + rb_bitmap, + rb_start, + rb_size); + ASSERT_TRUE(freq_allocation == proc_pdu.freq_alloc); + + ASSERT_EQ(ldpc_graph, proc_pdu.ldpc_base_graph); + ASSERT_EQ(tb_size_lbrm_bytes.value(), proc_pdu.tbs_lbrm_bytes); + + // :TODO: re_pattern. } } } @@ -332,9 +293,3 @@ static void pdsch_conversion_test() } } } - -int main() -{ - pdsch_conversion_test(); - fmt::print("PDCCH FAPI to PHY message conversion OK\n"); -} diff --git a/tests/unittests/fapi_adaptor/phy/messages/dl_ssb_pdu_test.cpp b/tests/unittests/fapi_adaptor/phy/messages/dl_ssb_pdu_test.cpp index 6ae23cf118..0d9382a77b 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi_adaptor/phy/messages/dl_ssb_pdu_test.cpp @@ -23,8 +23,8 @@ #include "srsran/fapi/message_builders.h" #include "srsran/fapi_adaptor/phy/messages/ssb.h" #include "srsran/srsvec/compare.h" -#include "srsran/support/test_utils.h" #include +#include #include using namespace srsran; @@ -33,7 +33,7 @@ using namespace fapi_adaptor; static std::mt19937 gen(0); /// Benchmark that measures the performance converting SSB data structures from MAC -> FAPI -> PHY. -static void ssb_conversion_test() +TEST(fapi_to_phy_ssb_conversion_test, valid_pdu_conversion_success) { // Random generators. std::uniform_int_distribution sfn_dist(0, 1023); @@ -59,9 +59,8 @@ static void ssb_conversion_test() subcarrier_spacing::kHz30, subcarrier_spacing::kHz60, subcarrier_spacing::kHz120}) { - for (fapi::beta_pss_profile_type beta_pss : {fapi::beta_pss_profile_type::dB_0, - fapi::beta_pss_profile_type::dB_3, - fapi::beta_pss_profile_type::beta_pss_profile_sss}) { + for (fapi::beta_pss_profile_type beta_pss : + {fapi::beta_pss_profile_type::dB_0, fapi::beta_pss_profile_type::dB_3}) { for (ssb_pattern_case pattern_case : {ssb_pattern_case::A, ssb_pattern_case::B, ssb_pattern_case::C, @@ -89,10 +88,6 @@ static void ssb_conversion_test() dmrs_type_a_position, pdcch_config_sib1, cell_barred, intra_freq_reselection); ssb_builder.set_maintenance_v3_basic_parameters(pattern_case, scs, lmax); - float power_scaling_ss_pbch_dB = power_scaling_ss_pbch_dist(gen); - float pss_to_sss_ratio_dB = pss_to_sss_ratio_dist(gen); - ssb_builder.set_maintenance_v3_tx_power_info(power_scaling_ss_pbch_dB, pss_to_sss_ratio_dB); - // PHY processor PDU. ssb_processor::pdu_t pdu; @@ -100,94 +95,89 @@ static void ssb_conversion_test() convert_ssb_fapi_to_phy(pdu, msg.pdus[0].ssb_pdu, msg.sfn, msg.slot, common_scs); // Assert contents. - TESTASSERT_EQ(pdu.slot.sfn(), sfn); - TESTASSERT_EQ(pdu.slot.slot_index(), slot.slot_index()); - TESTASSERT_EQ(pdu.phys_cell_id, pci); + ASSERT_EQ(pdu.slot.sfn(), sfn); + ASSERT_EQ(pdu.slot.slot_index(), slot.slot_index()); + ASSERT_EQ(pdu.phys_cell_id, pci); switch (beta_pss) { case fapi::beta_pss_profile_type::dB_0: - TESTASSERT_EQ(pdu.beta_pss, 0.0); + ASSERT_EQ(pdu.beta_pss, 0.0); break; case fapi::beta_pss_profile_type::dB_3: - TESTASSERT_EQ(pdu.beta_pss, 3.0); + ASSERT_EQ(pdu.beta_pss, 3.0); break; case fapi::beta_pss_profile_type::beta_pss_profile_sss: - TESTASSERT(std::abs(pdu.beta_pss - pss_to_sss_ratio_dB) < 0.01, - "Beta PSS is {} but expected {}.", - pdu.beta_pss, - pss_to_sss_ratio_dB); break; } - TESTASSERT_EQ(pdu.ssb_idx, ssb_idx); - TESTASSERT_EQ(pdu.L_max, lmax); - TESTASSERT_EQ(pdu.subcarrier_offset.to_uint(), ssb_subcarrier_offset); - TESTASSERT_EQ(pdu.offset_to_pointA.to_uint(), offset_pointA); - TESTASSERT_EQ(pdu.pattern_case, pattern_case); - TESTASSERT(srsvec::equal(pdu.ports, std::vector{0})); + ASSERT_EQ(pdu.ssb_idx, ssb_idx); + ASSERT_EQ(pdu.L_max, lmax); + ASSERT_EQ(pdu.subcarrier_offset.to_uint(), ssb_subcarrier_offset); + ASSERT_EQ(pdu.offset_to_pointA.to_uint(), offset_pointA); + ASSERT_EQ(pdu.pattern_case, pattern_case); + ASSERT_TRUE(srsvec::equal(pdu.ports, std::vector{0})); // MIB - 1 bit - TESTASSERT_EQ(pdu.bch_payload[0], 0); + ASSERT_EQ(pdu.bch_payload[0], 0); // systemFrameNumber - 6 bits MSB - TESTASSERT_EQ(pdu.bch_payload[1], (sfn >> 9U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[2], (sfn >> 8U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[3], (sfn >> 7U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[4], (sfn >> 6U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[5], (sfn >> 5U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[6], (sfn >> 4U) & 1U); + ASSERT_EQ(pdu.bch_payload[1], (sfn >> 9U) & 1U); + ASSERT_EQ(pdu.bch_payload[2], (sfn >> 8U) & 1U); + ASSERT_EQ(pdu.bch_payload[3], (sfn >> 7U) & 1U); + ASSERT_EQ(pdu.bch_payload[4], (sfn >> 6U) & 1U); + ASSERT_EQ(pdu.bch_payload[5], (sfn >> 5U) & 1U); + ASSERT_EQ(pdu.bch_payload[6], (sfn >> 4U) & 1U); // subCarrierSpacingCommon - 1 bit - TESTASSERT_EQ(pdu.bch_payload[7], - (common_scs == subcarrier_spacing::kHz15 || common_scs == subcarrier_spacing::kHz60) ? 0 - : 1); + ASSERT_EQ(pdu.bch_payload[7], + (common_scs == subcarrier_spacing::kHz15 || common_scs == subcarrier_spacing::kHz60) ? 0 : 1); // ssb-SubcarrierOffset - 4 bits - TESTASSERT_EQ(pdu.bch_payload[8], (ssb_subcarrier_offset >> 3U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[9], (ssb_subcarrier_offset >> 2U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[10], (ssb_subcarrier_offset >> 1U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[11], (ssb_subcarrier_offset >> 0U) & 1U); + ASSERT_EQ(pdu.bch_payload[8], (ssb_subcarrier_offset >> 3U) & 1U); + ASSERT_EQ(pdu.bch_payload[9], (ssb_subcarrier_offset >> 2U) & 1U); + ASSERT_EQ(pdu.bch_payload[10], (ssb_subcarrier_offset >> 1U) & 1U); + ASSERT_EQ(pdu.bch_payload[11], (ssb_subcarrier_offset >> 0U) & 1U); // dmrs-TypeA-Position - 1 bit - TESTASSERT_EQ(pdu.bch_payload[12], - static_cast(dmrs_type_a_position == dmrs_typeA_position::pos2) ? 0 : 1); + ASSERT_EQ(pdu.bch_payload[12], + static_cast(dmrs_type_a_position == dmrs_typeA_position::pos2) ? 0 : 1); // pdcch-ConfigSIB1 // controlResourceSetZero - 4 bits - TESTASSERT_EQ(pdu.bch_payload[13], (pdcch_config_sib1 >> 7U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[14], (pdcch_config_sib1 >> 6U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[15], (pdcch_config_sib1 >> 5U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[16], (pdcch_config_sib1 >> 4U) & 1U); + ASSERT_EQ(pdu.bch_payload[13], (pdcch_config_sib1 >> 7U) & 1U); + ASSERT_EQ(pdu.bch_payload[14], (pdcch_config_sib1 >> 6U) & 1U); + ASSERT_EQ(pdu.bch_payload[15], (pdcch_config_sib1 >> 5U) & 1U); + ASSERT_EQ(pdu.bch_payload[16], (pdcch_config_sib1 >> 4U) & 1U); // searchSpaceZero - 4 bits - TESTASSERT_EQ(pdu.bch_payload[17], (pdcch_config_sib1 >> 3U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[18], (pdcch_config_sib1 >> 2U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[19], (pdcch_config_sib1 >> 1U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[20], (pdcch_config_sib1 >> 0U) & 1U); + ASSERT_EQ(pdu.bch_payload[17], (pdcch_config_sib1 >> 3U) & 1U); + ASSERT_EQ(pdu.bch_payload[18], (pdcch_config_sib1 >> 2U) & 1U); + ASSERT_EQ(pdu.bch_payload[19], (pdcch_config_sib1 >> 1U) & 1U); + ASSERT_EQ(pdu.bch_payload[20], (pdcch_config_sib1 >> 0U) & 1U); // Barred - 1 bit - TESTASSERT_EQ(pdu.bch_payload[21], cell_barred ? 0U : 1U); + ASSERT_EQ(pdu.bch_payload[21], cell_barred ? 0U : 1U); // intraFreqReselection - 1 bit - TESTASSERT_EQ(pdu.bch_payload[22], intra_freq_reselection ? 0U : 1U); + ASSERT_EQ(pdu.bch_payload[22], intra_freq_reselection ? 0U : 1U); // Spare - 1 bit - TESTASSERT_EQ(pdu.bch_payload[23], 0); + ASSERT_EQ(pdu.bch_payload[23], 0); // systemFrameNumber - 4 bits LSB - TESTASSERT_EQ(pdu.bch_payload[24], (sfn >> 3U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[25], (sfn >> 2U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[26], (sfn >> 1U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[27], (sfn >> 0U) & 1U); + ASSERT_EQ(pdu.bch_payload[24], (sfn >> 3U) & 1U); + ASSERT_EQ(pdu.bch_payload[25], (sfn >> 2U) & 1U); + ASSERT_EQ(pdu.bch_payload[26], (sfn >> 1U) & 1U); + ASSERT_EQ(pdu.bch_payload[27], (sfn >> 0U) & 1U); // Half radio frame - 1 bit - TESTASSERT_EQ(pdu.bch_payload[28], slot.is_odd_hrf()); + ASSERT_EQ(pdu.bch_payload[28], slot.is_odd_hrf()); if (lmax == 64) { // SS/PBCH block index - 3 MSB - TESTASSERT_EQ(pdu.bch_payload[29], (ssb_idx >> 5U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[30], (ssb_idx >> 4U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[31], (ssb_idx >> 3U) & 1U); + ASSERT_EQ(pdu.bch_payload[29], (ssb_idx >> 5U) & 1U); + ASSERT_EQ(pdu.bch_payload[30], (ssb_idx >> 4U) & 1U); + ASSERT_EQ(pdu.bch_payload[31], (ssb_idx >> 3U) & 1U); } else { // 3rd LSB set to MSB of SSB subcarrier offset. 2nd and 1st bits reserved. - TESTASSERT_EQ(pdu.bch_payload[29], (ssb_subcarrier_offset >> 5U) & 1U); - TESTASSERT_EQ(pdu.bch_payload[30], 0); - TESTASSERT_EQ(pdu.bch_payload[31], 0); + ASSERT_EQ(pdu.bch_payload[29], (ssb_subcarrier_offset >> 5U) & 1U); + ASSERT_EQ(pdu.bch_payload[30], 0); + ASSERT_EQ(pdu.bch_payload[31], 0); } } } @@ -196,11 +186,3 @@ static void ssb_conversion_test() } } } - -int main() -{ - ssb_conversion_test(); - - fmt::print("Success\n"); - return 0; -} diff --git a/tests/unittests/gtpu/gtpu_demux_test.cpp b/tests/unittests/gtpu/gtpu_demux_test.cpp index e47e655ed8..4e93b4225c 100644 --- a/tests/unittests/gtpu/gtpu_demux_test.cpp +++ b/tests/unittests/gtpu/gtpu_demux_test.cpp @@ -63,10 +63,7 @@ class gtpu_demux_test : public ::testing::Test std::unique_ptr gtpu_tunnel; manual_task_worker teid_worker{128}; - - task_worker worker{"GTP-U demux#0", 128}; - task_worker_executor exec{worker}; - null_dlt_pcap dummy_pcap; + null_dlt_pcap dummy_pcap; std::unique_ptr dut; srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST", false); @@ -76,10 +73,10 @@ class gtpu_demux_test : public ::testing::Test TEST_F(gtpu_demux_test, when_tunnel_not_registered_pdu_is_dropped) { sockaddr_storage src_addr = {}; - byte_buffer pdu{gtpu_ping_vec_teid_1}; + byte_buffer pdu = byte_buffer::create(gtpu_ping_vec_teid_1).value(); dut->handle_pdu(std::move(pdu), src_addr); - worker.wait_pending_tasks(); + teid_worker.run_pending_tasks(); ASSERT_EQ(gtpu_tunnel->last_rx.length(), 0); } @@ -87,11 +84,11 @@ TEST_F(gtpu_demux_test, when_tunnel_not_registered_pdu_is_dropped) TEST_F(gtpu_demux_test, when_tunnel_registered_pdu_is_forwarded) { sockaddr_storage src_addr = {}; - byte_buffer pdu{gtpu_ping_vec_teid_1}; + byte_buffer pdu = byte_buffer::create(gtpu_ping_vec_teid_1).value(); dut->add_tunnel(gtpu_teid_t{0x1}, teid_worker, gtpu_tunnel.get()); dut->handle_pdu(std::move(pdu), src_addr); - worker.wait_pending_tasks(); + teid_worker.run_pending_tasks(); ASSERT_EQ(gtpu_tunnel->last_rx.length(), sizeof(gtpu_ping_vec_teid_1)); } @@ -99,12 +96,12 @@ TEST_F(gtpu_demux_test, when_tunnel_registered_pdu_is_forwarded) TEST_F(gtpu_demux_test, when_tunnel_is_removed_pdu_is_dropped) { sockaddr_storage src_addr = {}; - byte_buffer pdu{gtpu_ping_vec_teid_1}; + byte_buffer pdu = byte_buffer::create(gtpu_ping_vec_teid_1).value(); dut->add_tunnel(gtpu_teid_t{0x1}, teid_worker, gtpu_tunnel.get()); dut->remove_tunnel(gtpu_teid_t{0x1}); dut->handle_pdu(std::move(pdu), src_addr); - worker.wait_pending_tasks(); + teid_worker.run_pending_tasks(); ASSERT_EQ(gtpu_tunnel->last_rx.length(), 0); } @@ -112,11 +109,17 @@ TEST_F(gtpu_demux_test, when_tunnel_is_removed_pdu_is_dropped) TEST_F(gtpu_demux_test, when_different_tunnel_registered_pdu_is_dropped) { sockaddr_storage src_addr = {}; - byte_buffer pdu{gtpu_ping_vec_teid_2}; + byte_buffer pdu = byte_buffer::create(gtpu_ping_vec_teid_2).value(); dut->add_tunnel(gtpu_teid_t{0x1}, teid_worker, gtpu_tunnel.get()); dut->handle_pdu(std::move(pdu), src_addr); - worker.wait_pending_tasks(); + teid_worker.run_pending_tasks(); ASSERT_EQ(gtpu_tunnel->last_rx.length(), 0); } + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/unittests/gtpu/gtpu_echo_test.cpp b/tests/unittests/gtpu/gtpu_echo_test.cpp index 9966631fd1..359d68dd75 100644 --- a/tests/unittests/gtpu/gtpu_echo_test.cpp +++ b/tests/unittests/gtpu/gtpu_echo_test.cpp @@ -136,16 +136,35 @@ TEST_F(gtpu_echo_test, rx_echo_req_tx_echo_rep) echo = create_gtpu_echo(msg); sockaddr_storage orig_addr = {}; - byte_buffer echo_req = {gtpu_echo_request_sn_65535}; + byte_buffer echo_req = byte_buffer::create(gtpu_echo_request_sn_65535).value(); gtpu_tunnel_rx_upper_layer_interface* rx = echo->get_rx_upper_layer_interface(); rx->handle_pdu(std::move(echo_req), orig_addr); ASSERT_FALSE(gtpu_tx.last_tx.empty()); - byte_buffer echo_rep = {gtpu_echo_response_sn_65535}; + byte_buffer echo_rep = byte_buffer::create(gtpu_echo_response_sn_65535).value(); ASSERT_EQ(gtpu_tx.last_tx, echo_rep); }; +/// \brief Test correct reception of an error indication message +TEST_F(gtpu_echo_test, rx_error_indication) +{ + null_dlt_pcap dummy_pcap; + // init echo entity + gtpu_echo_creation_message msg = {}; + msg.gtpu_pcap = &dummy_pcap; + msg.tx_upper = >pu_tx; + echo = create_gtpu_echo(msg); + + sockaddr_storage orig_addr = {}; + byte_buffer error_indication = byte_buffer::create(gtpu_error_indication).value(); + + gtpu_tunnel_rx_upper_layer_interface* rx = echo->get_rx_upper_layer_interface(); + rx->handle_pdu(std::move(error_indication), orig_addr); + + ASSERT_TRUE(gtpu_tx.last_tx.empty()); +}; + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/tests/unittests/gtpu/gtpu_test.cpp b/tests/unittests/gtpu/gtpu_test.cpp index 46215e5e04..9a21be4842 100644 --- a/tests/unittests/gtpu/gtpu_test.cpp +++ b/tests/unittests/gtpu/gtpu_test.cpp @@ -68,9 +68,9 @@ class gtpu_test : public ::testing::Test TEST_F(gtpu_test, read_teid) { srsran::test_delimit_logger delimiter("GTP-U read TEID test"); - byte_buffer orig_vec{gtpu_ping_vec_teid_1}; - byte_buffer test_vec{gtpu_ping_vec_teid_1}; - uint32_t teid = {}; + byte_buffer orig_vec = byte_buffer::create(gtpu_ping_vec_teid_1).value(); + byte_buffer test_vec = byte_buffer::create(gtpu_ping_vec_teid_1).value(); + uint32_t teid = {}; // Unpack SDU logger.info(orig_vec.begin(), orig_vec.end(), "Original SDU"); @@ -86,14 +86,14 @@ TEST_F(gtpu_test, read_teid) TEST_F(gtpu_test, pack_unpack) { srsran::test_delimit_logger delimiter("GTP-U unpack/pack test"); - byte_buffer orig_vec{gtpu_ping_vec_teid_1}; - byte_buffer tst_vec{gtpu_ping_vec_teid_1}; - byte_buffer tst_vec_no_header{tst_vec.begin() + 8, tst_vec.end()}; + byte_buffer orig_vec = byte_buffer::create(gtpu_ping_vec_teid_1).value(); + byte_buffer tst_vec = byte_buffer::create(gtpu_ping_vec_teid_1).value(); + byte_buffer tst_vec_no_header = byte_buffer::create(tst_vec.begin() + 8, tst_vec.end()).value(); gtpu_dissected_pdu dissected_pdu; // Unpack SDU logger.info(orig_vec.begin(), orig_vec.end(), "Original SDU"); - bool read_ok = gtpu_dissect_pdu(dissected_pdu, tst_vec.deep_copy(), gtpu_rx_logger); + bool read_ok = gtpu_dissect_pdu(dissected_pdu, tst_vec.deep_copy().value(), gtpu_rx_logger); ASSERT_EQ(read_ok, true); // Check flags @@ -116,11 +116,11 @@ TEST_F(gtpu_test, pack_unpack) gtpu_header hdr = dissected_pdu.hdr; // Check SDU after striping header - byte_buffer sdu = gtpu_extract_t_pdu(std::move(dissected_pdu)); + byte_buffer sdu = gtpu_extract_msg(std::move(dissected_pdu)); ASSERT_EQ(sdu.length(), tst_vec_no_header.length()); ASSERT_EQ(sdu, tst_vec_no_header); - byte_buffer repack_buf = tst_vec_no_header.deep_copy(); + byte_buffer repack_buf = tst_vec_no_header.deep_copy().value(); gtpu_write_header(repack_buf, hdr, gtpu_tx_logger); logger.info(repack_buf.begin(), repack_buf.end(), "Repackaged GTP-U packet"); @@ -133,15 +133,16 @@ TEST_F(gtpu_test, pack_unpack) TEST_F(gtpu_test, pack_unpack_ext_hdr) { srsran::test_delimit_logger delimiter("GTP-U header extension unpack/pack test"); - byte_buffer orig_vec{gtpu_ping_two_ext_vec}; - byte_buffer tst_vec{gtpu_ping_two_ext_vec}; + byte_buffer orig_vec = byte_buffer::create(gtpu_ping_two_ext_vec).value(); + byte_buffer tst_vec = byte_buffer::create(gtpu_ping_two_ext_vec).value(); uint16_t ext_size = 4; - byte_buffer tst_vec_no_header{tst_vec.begin() + GTPU_EXTENDED_HEADER_LEN + 2 * ext_size, tst_vec.end()}; + byte_buffer tst_vec_no_header = + byte_buffer::create(tst_vec.begin() + GTPU_EXTENDED_HEADER_LEN + 2 * ext_size, tst_vec.end()).value(); gtpu_dissected_pdu dissected_pdu; // Unpack SDU logger.info(orig_vec.begin(), orig_vec.end(), "Original SDU"); - bool read_ok = gtpu_dissect_pdu(dissected_pdu, tst_vec.deep_copy(), gtpu_rx_logger); + bool read_ok = gtpu_dissect_pdu(dissected_pdu, tst_vec.deep_copy().value(), gtpu_rx_logger); ASSERT_EQ(read_ok, true); // Check flags @@ -181,22 +182,24 @@ TEST_F(gtpu_test, pack_unpack_ext_hdr) gtpu_header hdr = dissected_pdu.hdr; - byte_buffer container0 = {dissected_pdu.hdr.ext_list[0].container.begin(), - dissected_pdu.hdr.ext_list[0].container.end()}; + byte_buffer container0 = byte_buffer::create(dissected_pdu.hdr.ext_list[0].container.begin(), + dissected_pdu.hdr.ext_list[0].container.end()) + .value(); hdr.ext_list[0].container = container0; hdr.ext_list[0].extension_header_type = dissected_pdu.hdr.ext_list[0].extension_header_type; - byte_buffer container1 = {dissected_pdu.hdr.ext_list[1].container.begin(), - dissected_pdu.hdr.ext_list[1].container.end()}; + byte_buffer container1 = byte_buffer::create(dissected_pdu.hdr.ext_list[1].container.begin(), + dissected_pdu.hdr.ext_list[1].container.end()) + .value(); hdr.ext_list[1].container = container1; hdr.ext_list[1].extension_header_type = dissected_pdu.hdr.ext_list[1].extension_header_type; // Check SDU after striping header - byte_buffer sdu = gtpu_extract_t_pdu(std::move(dissected_pdu)); + byte_buffer sdu = gtpu_extract_msg(std::move(dissected_pdu)); ASSERT_EQ(sdu.length(), tst_vec_no_header.length()); ASSERT_EQ(sdu, tst_vec_no_header); - byte_buffer repack_buf = tst_vec_no_header.deep_copy(); + byte_buffer repack_buf = tst_vec_no_header.deep_copy().value(); gtpu_write_header(repack_buf, hdr, gtpu_tx_logger); logger.info(repack_buf.begin(), repack_buf.end(), "Repackaged GTP-U packet"); diff --git a/tests/unittests/gtpu/gtpu_test_shared.h b/tests/unittests/gtpu/gtpu_test_shared.h index cdf7079a9b..566d9843f4 100644 --- a/tests/unittests/gtpu/gtpu_test_shared.h +++ b/tests/unittests/gtpu/gtpu_test_shared.h @@ -85,4 +85,7 @@ const uint8_t gtpu_echo_request_sn_65535[] = {0x32, 0x01, 0x00, 0x04, 0x00, 0x00 const uint8_t gtpu_echo_response_sn_65535[] = {0x32, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0e, 0x00}; +const uint8_t gtpu_error_indication[] = {0x36, 0x1a, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x01, 0x00, 0x01, 0x40, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x12, 0x67, 0x85, 0x00, 0x04, 0x0a, 0x35, 0x01, 0x02}; } // namespace srsran diff --git a/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp index 3d6c27c1b6..329be7a3bf 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp @@ -224,7 +224,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_no_sn) for (unsigned i = 0; i < 3; i++) { byte_buffer sdu; EXPECT_TRUE(sdu.append(0x11)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, {}); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, {}); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -249,7 +249,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_in_order) for (unsigned i = 0; i < 3; i++) { byte_buffer sdu; EXPECT_TRUE(sdu.append(0x11)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, i); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, i); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -274,7 +274,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 0 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x0)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 0); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 0); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -287,7 +287,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 2 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x2)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 2); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 2); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -299,7 +299,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 4 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x4)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 4); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 4); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -310,7 +310,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 1 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x1)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 1); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 1); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -322,7 +322,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order) { // SN = 3 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x3)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 3); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 3); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -350,7 +350,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 0 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x0)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 0); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 0); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -363,7 +363,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 2 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x2)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 2); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 2); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -375,7 +375,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 4 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x4)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 4); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 4); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -386,7 +386,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 3 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x3)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 3); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 3); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -398,7 +398,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_out_of_order_two_holes) { // SN = 1 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x1)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 1); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 1); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -424,7 +424,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 0 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x0)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 0); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 0); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -437,7 +437,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 2 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x2)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 2); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 2); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -448,7 +448,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 4 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x4)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 4); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 4); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -469,7 +469,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_expiration) { // SN = 1 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x1)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 1); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 1); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -496,7 +496,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 0 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x0)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 0); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 0); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -509,7 +509,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 2 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x2)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 2); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 2); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -520,7 +520,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 4 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x4)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 4); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 4); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -531,7 +531,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 3 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x3)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 3); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 3); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); @@ -548,7 +548,7 @@ TEST_F(gtpu_tunnel_ngu_rx_test, rx_t_reordering_two_holes) { // SN = 1 byte_buffer sdu; EXPECT_TRUE(sdu.append(0x1)); - byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy(), rx_cfg.local_teid, qos_flow_id_t::min, 1); + byte_buffer pdu = pdu_generator.create_gtpu_pdu(sdu.deep_copy().value(), rx_cfg.local_teid, qos_flow_id_t::min, 1); gtpu_tunnel_base_rx* rx_base = rx.get(); rx_base->handle_pdu(std::move(pdu), src_addr); diff --git a/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp b/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp index 6a40451a96..a176c032e9 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp @@ -155,12 +155,12 @@ TEST_F(gtpu_tunnel_ngu_test, rx_sdu) byte_buffer orig_vec = make_byte_buffer(gtpu_ping_vec_teid_2_qfi_1_dl); byte_buffer strip_vec = make_byte_buffer(gtpu_ping_vec_teid_2_qfi_1_dl); gtpu_dissected_pdu dissected_pdu; - bool read_ok = gtpu_dissect_pdu(dissected_pdu, strip_vec.deep_copy(), gtpu_rx_logger); + bool read_ok = gtpu_dissect_pdu(dissected_pdu, strip_vec.deep_copy().value(), gtpu_rx_logger); ASSERT_EQ(read_ok, true); gtpu_tunnel_rx_upper_layer_interface* rx = gtpu->get_rx_upper_layer_interface(); rx->handle_pdu(std::move(orig_vec), orig_addr); - ASSERT_EQ(gtpu_extract_t_pdu(std::move(dissected_pdu)), gtpu_rx.last_rx); + ASSERT_EQ(gtpu_extract_msg(std::move(dissected_pdu)), gtpu_rx.last_rx); ASSERT_EQ(uint_to_qos_flow_id(1), gtpu_rx.last_rx_qos_flow_id); }; @@ -179,8 +179,8 @@ TEST_F(gtpu_tunnel_ngu_test, tx_pdu) msg.ue_dl_timer_factory = timers; gtpu = create_gtpu_tunnel_ngu(msg); - byte_buffer sdu{gtpu_ping_sdu}; - byte_buffer pdu{gtpu_ping_vec_teid_2_qfi_1_ul}; + byte_buffer sdu = byte_buffer::create(gtpu_ping_sdu).value(); + byte_buffer pdu = byte_buffer::create(gtpu_ping_vec_teid_2_qfi_1_ul).value(); gtpu_tunnel_tx_lower_layer_interface* tx = gtpu->get_tx_lower_layer_interface(); tx->handle_sdu(std::move(sdu), uint_to_qos_flow_id(1)); diff --git a/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp b/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp index 18a9f84f4b..6f00f48e9f 100644 --- a/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp +++ b/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp @@ -58,7 +58,7 @@ TEST(mac_dl_sch_pdu, mac_ce_con_res_id_pack) pdu.add_ue_con_res_id(conres); span result = pdu.get(); - byte_buffer expected{0b00111110}; + byte_buffer expected = byte_buffer::create({0b00111110}).value(); ASSERT_TRUE(expected.append(conres)); ASSERT_EQ(result, expected); } @@ -82,7 +82,7 @@ TEST(mac_dl_sch_pdu, mac_sdu_8bit_L_pack) ASSERT_TRUE(payload.append(test_rgen::uniform_int())); } lcid_t lcid = (lcid_t)test_rgen::uniform_int(0, MAX_NOF_RB_LCIDS); - pdu.add_sdu(lcid, byte_buffer_chain{payload.copy()}); + pdu.add_sdu(lcid, byte_buffer_chain::create(payload.copy()).value()); span result = pdu.get(); byte_buffer expected; @@ -115,7 +115,7 @@ TEST(mac_dl_sch_pdu, mac_sdu_16bit_L_pack) ASSERT_TRUE(payload.append(test_rgen::uniform_int())); } lcid_t lcid = (lcid_t)test_rgen::uniform_int(0, MAX_NOF_RB_LCIDS); - ASSERT_EQ(pdu.add_sdu(lcid, byte_buffer_chain{payload.copy()}), payload.length() + HEADER_LEN); + ASSERT_EQ(pdu.add_sdu(lcid, byte_buffer_chain::create(payload.copy()).value()), payload.length() + HEADER_LEN); span result = pdu.get(); byte_buffer expected; @@ -144,7 +144,7 @@ class dummy_dl_bearer : public mac_sdu_tx_builder for (unsigned i = 0; i != nof_bytes; ++i) { mac_sdu_buf[i] = test_rgen::uniform_int(); } - last_sdus.emplace_back(mac_sdu_buf.first(nof_bytes)); + last_sdus.emplace_back(byte_buffer::create(mac_sdu_buf.first(nof_bytes)).value()); return nof_bytes; } diff --git a/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp b/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp index d837233a19..918a52729e 100644 --- a/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp +++ b/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp @@ -88,7 +88,7 @@ static bool is_rapid_subpdu(span rar_pdu) /// Decode RAR UL PDU as per TS 38.321, Section 6.2.2 and 6.2.3. rar_ul_grant decode_ul_grant(span rar_subpdu) { - byte_buffer buf = rar_subpdu; + byte_buffer buf = byte_buffer::create(rar_subpdu).value(); bit_decoder dec(buf); rar_ul_grant ret{}; diff --git a/tests/unittests/mac/mac_test_helpers.h b/tests/unittests/mac/mac_test_helpers.h index 2bc7107e08..e6931bbe50 100644 --- a/tests/unittests/mac/mac_test_helpers.h +++ b/tests/unittests/mac/mac_test_helpers.h @@ -163,7 +163,7 @@ class mac_sdu_tx_builder_test_notifier : public mac_sdu_tx_builder size_t on_new_tx_sdu(span mac_sdu_buf) override { - previous_tx_sdu = test_rgen::random_vector(mac_sdu_buf.size()); + previous_tx_sdu = byte_buffer::create(test_rgen::random_vector(mac_sdu_buf.size())).value(); auto out_it = mac_sdu_buf.begin(); for (span seg : previous_tx_sdu.segments()) { out_it = std::copy(seg.begin(), seg.end(), out_it); diff --git a/tests/unittests/mac/mac_ul_pdu_test.cpp b/tests/unittests/mac/mac_ul_pdu_test.cpp index 88c36f3500..d4e2ec8348 100644 --- a/tests/unittests/mac/mac_ul_pdu_test.cpp +++ b/tests/unittests/mac/mac_ul_pdu_test.cpp @@ -46,7 +46,7 @@ TEST(mac_ul_subpdu, decode_ul_ccch_48) // R/LCID MAC subheader = R|R|LCID = 0x34 -> LCID=52 // MAC SDU (UL CCCH) = {0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06} (Random 6B sequence) - byte_buffer msg({0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}); + byte_buffer msg = byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length @@ -74,7 +74,7 @@ TEST(mac_ul_subpdu, decode_ul_ccch_64) // R/LCID MAC subheader = R|R|LCID = 0x00 -> LCID = 0 // MAC SDU (UL CCCH) = {0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54} (Random 8B sequence) - byte_buffer msg({0x00, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54}); + byte_buffer msg = byte_buffer::create({0x00, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -99,7 +99,7 @@ TEST(mac_ul_subpdu, decode_short_bsr) // R/LCID MAC subheader = R|R|LCID = 0x3d or LCID=61 // MAC CE Short BSR = {0x59} LCG ID = 2, Buffer size = 25 - byte_buffer msg({0x3d, 0x59}); + byte_buffer msg = byte_buffer::create({0x3d, 0x59}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -129,7 +129,7 @@ TEST(mac_ul_subpdu, decode_short_trunc_bsr) // R/LCID MAC subheader = R|R|LCID = 0x3b or LCID=59 // MAC CE Short BSR = {0xae} LCG ID = 2, Buffer size = 14 - byte_buffer msg({0x3b, 0xae}); + byte_buffer msg = byte_buffer::create({0x3b, 0xae}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -164,7 +164,7 @@ TEST(mac_ul_subpdu, decode_long_bsr_with_2_lcgs) // R/F/LCID/L MAC subheader = 0x3b - F=0, LCID=62, L=3 // MAC CE Long BSR = {0x81, 0xd9, 0xab} LCG_ID_7=true, LCG_ID_0= true // Buffer size(LCG_ID_0) = 217 (0xd9), Buffer size(LCG_ID_7) = 171 (0xab) - byte_buffer msg({0x3e, 0x03, 0x81, 0xd9, 0xab}); + byte_buffer msg = byte_buffer::create({0x3e, 0x03, 0x81, 0xd9, 0xab}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -206,7 +206,7 @@ TEST(mac_ul_subpdu, decode_long_bsr_with_4_lcgs) // MAC CE Long BSR = {0x5a, 0x02, 0x04, 0x05, 0x07} // LCG_ID_6=true, LCG_ID_4=true, LCG_ID_3=true, LCG_ID_1=true // Buffer size(LCG_ID_1)=2, Buffer size(LCG_ID_3)=4, Buffer size(LCG_ID_4)=5, Buffer size(LCG_ID_6)=7 - byte_buffer msg({0x3e, 0x05, 0x5a, 0x02, 0x04, 0x05, 0x07}); + byte_buffer msg = byte_buffer::create({0x3e, 0x05, 0x5a, 0x02, 0x04, 0x05, 0x07}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -249,7 +249,7 @@ TEST(mac_ul_subpdu, decode_long_bsr_with_8_lcgs) // MAC CE Long BSR = {0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08} // All LCG_ID set to true (0xff) // Buffer size(LCG_ID_0)=1, ..., Buffer size(LCG_ID_n)=n+1, ... , Buffer size(LCG_ID_7)=8 - byte_buffer msg({0x3e, 0x9, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}); + byte_buffer msg = byte_buffer::create({0x3e, 0x9, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -287,7 +287,7 @@ TEST(mac_ul_subpdu, decode_long_trunc_bsr) // R/F/LCID/L MAC subheader = 0x3c - F=0, LCID=61, L=3 // MAC CE Long Truncated BSR = {0x81, 0xd9, 0xab} LCG_ID_7=true, LCG_ID_0= true // Buffer size_1 = 217 (0xd9), Buffer size_2 = 171 (0xab) - byte_buffer msg({0x3c, 0x3, 0x45, 0xd9, 0xab}); + byte_buffer msg = byte_buffer::create({0x3c, 0x3, 0x45, 0xd9, 0xab}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -324,7 +324,7 @@ TEST(mac_ul_subpdu, decode_crnti_ce) // R/LCID MAC subheader = R|R|LCID = 0x3a or LCID=61 // MAC CE C-RNTI = {0x46, 0x01}, RNTI=0x4601 - byte_buffer msg({0x3a, 0x46, 0x01}); + byte_buffer msg = byte_buffer::create({0x3a, 0x46, 0x01}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -355,7 +355,7 @@ TEST(mac_ul_subpdu, decode_single_entry_phr) // R/LCID MAC subheader = R|R|LCID = 0x39 or LCID=57 // MAC CE SE PHR = {0x27, 0x2f} - byte_buffer msg({0x39, 0x27, 0x2f}); + byte_buffer msg = byte_buffer::create({0x39, 0x27, 0x2f}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -392,7 +392,7 @@ TEST(mac_ul_subpdu, decode_subpdu_padding) // R/LCID MAC subheader = R|R|LCID = 0x3f or LCID=63 // Padding = {0x00, 0x00} - 2B of padding - byte_buffer msg({0x3f, 0x00, 0x00}); + byte_buffer msg = byte_buffer::create({0x3f, 0x00, 0x00}).value(); ASSERT_TRUE(subpdu.unpack(msg)); // Test expected length. @@ -414,7 +414,7 @@ TEST(mac_ul_pdu, decode_crnti_ce_and_sbsr) // subPDU_1 = [ R/LCID MAC subheader (1 byte) | MAC CE C-RNTI ] // R/LCID MAC subheader = R|R|LCID = 0x3a or LCID=58 - byte_buffer msg = {0x3a, 0x46, 0x1}; + byte_buffer msg = byte_buffer::create({0x3a, 0x46, 0x1}).value(); // subPDU_2 = [ R/LCID MAC subheader (1 byte) | MAC CE Short BSR ] // R/LCID MAC subheader = R|R|LCID = 0x3d or LCID=63 @@ -448,7 +448,7 @@ TEST(mac_ul_pdu, decode_ul_ccch_and_padding) // MAC SDU (UL CCCH) = {0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06} (Random 6B sequence) // subPDU_2 = [ R/LCID MAC subheader (1 byte) | padding (3bytes) ] // R/LCID MAC subheader = R|R|LCID = 0x3f or LCID=63 - byte_buffer msg({0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}); + byte_buffer msg = byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}).value(); ASSERT_TRUE(pdu.unpack(msg)); // Test expected PDU. @@ -477,9 +477,9 @@ TEST(mac_ul_pdu, decode_short_sdu) // ... // | PAYLOAD | Octet L + 2 - size_t L = test_rgen::uniform_int(1, 255); - lcid_t lcid = uint_to_lcid(test_rgen::uniform_int(LCID_SRB1, LCID_MAX_DRB)); - byte_buffer payload{test_rgen::random_vector(L)}; + size_t L = test_rgen::uniform_int(1, 255); + lcid_t lcid = uint_to_lcid(test_rgen::uniform_int(LCID_SRB1, LCID_MAX_DRB)); + byte_buffer payload = byte_buffer::create(test_rgen::random_vector(L)).value(); byte_buffer msg; bit_encoder enc(msg); @@ -514,9 +514,9 @@ TEST(mac_ul_pdu, decode_long_sdu) // ... // | PAYLOAD | Octet L + 3 - size_t L = test_rgen::uniform_int(256, 1000); - lcid_t lcid = uint_to_lcid(test_rgen::uniform_int(LCID_SRB1, LCID_MAX_DRB)); - byte_buffer payload{test_rgen::random_vector(L)}; + size_t L = test_rgen::uniform_int(256, 1000); + lcid_t lcid = uint_to_lcid(test_rgen::uniform_int(LCID_SRB1, LCID_MAX_DRB)); + byte_buffer payload = byte_buffer::create(test_rgen::random_vector(L)).value(); byte_buffer msg; bit_encoder enc(msg); @@ -541,7 +541,7 @@ TEST(mac_ul_pdu, decode_bad_mac_pdu) { mac_ul_sch_pdu pdu; - byte_buffer msg(std::vector(11, 0x0)); + byte_buffer msg = byte_buffer::create(std::vector(11, 0x0)).value(); ASSERT_FALSE(pdu.unpack(msg)); ASSERT_EQ(pdu.nof_subpdus(), 0); } @@ -550,9 +550,9 @@ TEST(mac_ul_pdu, handle_the_case_when_a_pdu_has_too_many_subpdus) { constexpr unsigned nof_subpdus_per_pdu = 1000; - size_t L = 1; - lcid_t lcid = srsran::LCID_SRB1; - byte_buffer payload{test_rgen::random_vector(L)}; + size_t L = 1; + lcid_t lcid = srsran::LCID_SRB1; + byte_buffer payload = byte_buffer::create(test_rgen::random_vector(L)).value(); byte_buffer msg; bit_encoder enc(msg); @@ -572,9 +572,9 @@ TEST(mac_ul_pdu, handle_the_case_when_a_pdu_has_too_many_subpdus) TEST(mac_ul_pdu, handle_the_case_when_pdu_length_is_too_short_to_decode_length_prefix) { - size_t L = 1; - lcid_t lcid = srsran::LCID_SRB1; - byte_buffer payload{test_rgen::random_vector(L)}; + size_t L = 1; + lcid_t lcid = srsran::LCID_SRB1; + byte_buffer payload = byte_buffer::create(test_rgen::random_vector(L)).value(); byte_buffer msg; bit_encoder enc(msg); diff --git a/tests/unittests/mac/mac_ul_processor_test.cpp b/tests/unittests/mac/mac_ul_processor_test.cpp index d83639f092..99f8c3a2c7 100644 --- a/tests/unittests/mac/mac_ul_processor_test.cpp +++ b/tests/unittests/mac/mac_ul_processor_test.cpp @@ -246,7 +246,7 @@ TEST(mac_ul_processor, decode_ul_ccch_48bit) // Create PDU content. // R/LCID MAC subheader | MAC SDU (UL CCCH 48 bits) // { 0x34 | 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06} (Random 6B sequence) - byte_buffer payload({0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}); + byte_buffer payload = byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}).value(); // Send RX data indication to MAC UL. t_bench.send_rx_indication_msg(tc_rnti, payload); @@ -274,7 +274,7 @@ TEST(mac_ul_processor, decode_ul_ccch_64bit) // Create PDU content. // R/LCID MAC subheader | MAC SDU (UL CCCH 64 bits) // { 0x00 | 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54} (Random 8B sequence) - byte_buffer payload({0x00, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54}); + byte_buffer payload = byte_buffer::create({0x00, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06, 0x13, 0x54}).value(); // Send RX data indication to MAC UL. t_bench.send_rx_indication_msg(tc_rnti, payload); @@ -303,7 +303,7 @@ TEST(mac_ul_processor, decode_short_bsr) // Create PDU content. // R/LCID MAC subheader | MAC CE Short BSR // { 0x3d | 0x59} - byte_buffer pdu({0x3d, 0x59}); + byte_buffer pdu = byte_buffer::create({0x3d, 0x59}).value(); // Send RX data indication to MAC UL t_bench.send_rx_indication_msg(ue1_rnti, pdu); @@ -332,7 +332,7 @@ TEST(mac_ul_processor, decode_short_trunc_bsr) // Create PDU content. // R/LCID MAC subheader | MAC CE Short Truncated BSR // { 0x3b | 0xae} - byte_buffer pdu({0x3b, 0xae}); + byte_buffer pdu = byte_buffer::create({0x3b, 0xae}).value(); // Send RX data indication to MAC UL t_bench.send_rx_indication_msg(ue1_rnti, pdu); @@ -361,7 +361,7 @@ TEST(mac_ul_processor, decode_long_bsr) // Create PDU content. // R/F/LCID/L MAC subheader | MAC CE Short BSR // { 0x3e, 0x03 | 0x81, 0xd9, 0xab } - byte_buffer pdu({0x3e, 0x03, 0x81, 0xd9, 0xab}); + byte_buffer pdu = byte_buffer::create({0x3e, 0x03, 0x81, 0xd9, 0xab}).value(); // Send RX data indication to MAC UL. t_bench.send_rx_indication_msg(ue1_rnti, pdu); @@ -389,7 +389,7 @@ TEST(mac_ul_processor, decode_invalid_long_bsr) // Create PDU content. // R/F/LCID/L MAC subheader | MAC CE Long BSR // { 0x3e, 0x03 | 0x81, 0xd9, 0xab } - byte_buffer pdu({0x3e, 0x02, 0x1, 0xff}); + byte_buffer pdu = byte_buffer::create({0x3e, 0x02, 0x1, 0xff}).value(); // Send RX data indication to MAC UL. t_bench.send_rx_indication_msg(ue1_rnti, pdu); @@ -418,7 +418,7 @@ TEST(mac_ul_processor, decode_crnti_ce) // Create PDU content. // R/LCID MAC subheader | MAC CE C-RNTI // { 0x3a | 0x46, 0x01 } - byte_buffer pdu({0x3a, 0x46, 0x01}); + byte_buffer pdu = byte_buffer::create({0x3a, 0x46, 0x01}).value(); // Send RX data indication to MAC UL. t_bench.send_rx_indication_msg(tc_rnti, pdu); @@ -445,11 +445,11 @@ TEST(mac_ul_processor, decode_crnti_ce_and_sbsr) // > Create MAC CE C-RNTI subPDU. // R/LCID MAC subheader | MAC CE C-RNTI // { 0x3a | 0x46, 0x01 } - ASSERT_TRUE(payload.append(byte_buffer{0x3a, 0x46, 0x01})); + ASSERT_TRUE(payload.append(byte_buffer::create({0x3a, 0x46, 0x01}).value())); // > Create MAC CE Short BSR subPDU. // R/LCID MAC subheader | MAC CE Short BSR // { 0x3d | 0x59} - ASSERT_TRUE(payload.append(byte_buffer{0x3d, 0x59})); + ASSERT_TRUE(payload.append(byte_buffer::create({0x3d, 0x59}).value())); // Send RX data indication to MAC UL t_bench.send_rx_indication_msg(create_rx_data_indication(cell_idx, tc_rnti, std::move(payload))); @@ -483,12 +483,12 @@ TEST(mac_ul_processor, handle_crnti_ce_with_inexistent_old_crnti) // > Create subPDU content. // R/LCID MAC subheader | MAC CE C-RNTI // { 0x3a | 0x46, 0x01 } - byte_buffer ce_crnti({0x3a, 0x46, 0x01}); + byte_buffer ce_crnti = byte_buffer::create({0x3a, 0x46, 0x01}).value(); ASSERT_TRUE(payload.append(ce_crnti)); // > Create subPDU content. // R/LCID MAC subheader | MAC CE Short BSR // { 0x3d | 0x59} - byte_buffer sbsr({0x3d, 0x59}); + byte_buffer sbsr = byte_buffer::create({0x3d, 0x59}).value(); ASSERT_TRUE(payload.append(sbsr)); // Send RX data indication to MAC UL @@ -521,7 +521,7 @@ TEST(mac_ul_processor, verify_single_entry_phr) // R/LCID MAC subheader = R|R|LCID = 0x39 or LCID=57 // MAC CE SE PHR = {0x27, 0x2f} - byte_buffer pdu({0x39, 0x27, 0x2f}); + byte_buffer pdu = byte_buffer::create({0x39, 0x27, 0x2f}).value(); // Send RX data indication to MAC UL t_bench.send_rx_indication_msg(ue1_rnti, pdu); @@ -553,11 +553,11 @@ TEST(mac_ul_processor, when_ul_ccch_and_phr_are_received_then_phr_is_ignored) // > MAC subPDU with UL-CCCH: // R/LCID MAC subheader | MAC SDU (UL CCCH 48 bits) // { 0x34 | 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06} (Random 6B sequence) - ASSERT_TRUE(payload.append(byte_buffer{0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06})); + ASSERT_TRUE(payload.append(byte_buffer::create({0x34, 0x1e, 0x4f, 0xc0, 0x04, 0xa6, 0x06}).value())); // > MAC subPDU with PHR: // R/LCID MAC subheader = R|R|LCID = 0x39 or LCID=57 // MAC CE SE PHR = {0x27, 0x2f} - ASSERT_TRUE(payload.append(byte_buffer{0x39, 0x27, 0x2f})); + ASSERT_TRUE(payload.append(byte_buffer::create({0x39, 0x27, 0x2f}).value())); // Send RX data indication to MAC UL t_bench.send_rx_indication_msg(create_rx_data_indication(cell_idx, tc_rnti, std::move(payload))); @@ -576,7 +576,7 @@ TEST(mac_ul_processor, when_pdu_is_filled_with_zerosfor_existing_ue_then_the_mac // Create PDU content. The PDU is made of several SDUs with size equal to UL-CCCH CE to be decodeable. byte_buffer pdu; // R/F/LCID MAC subheader | MAC CE UL-CCCH 64 - byte_buffer ul_ccch({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + byte_buffer ul_ccch = byte_buffer::create({0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}).value(); ASSERT_TRUE(pdu.append(ul_ccch)); ASSERT_TRUE(pdu.append(ul_ccch)); ASSERT_TRUE(pdu.append(ul_ccch)); diff --git a/tests/unittests/ngap/ngap_asn1_packer_test.cpp b/tests/unittests/ngap/ngap_asn1_packer_test.cpp index af88faf401..a8b8bffc2b 100644 --- a/tests/unittests/ngap/ngap_asn1_packer_test.cpp +++ b/tests/unittests/ngap/ngap_asn1_packer_test.cpp @@ -86,7 +86,7 @@ TEST_F(ngap_asn1_packer_test, when_packing_successful_then_pdu_matches_tv) packer->handle_message(ngap_msg); // print packed message and TV - byte_buffer tv({ng_setup_request_packed, sizeof(ng_setup_request_packed)}); + byte_buffer tv = byte_buffer::create({ng_setup_request_packed, sizeof(ng_setup_request_packed)}).value(); test_logger.debug(tv.begin(), tv.end(), "Test vector ({} bytes):", tv.length()); test_logger.debug(gw->last_pdu.begin(), gw->last_pdu.end(), "Packed PDU ({} bytes):", gw->last_pdu.length()); diff --git a/tests/unittests/pcap/mac_pcap_test.cpp b/tests/unittests/pcap/mac_pcap_test.cpp index 3d95e88ba0..c1d67e036d 100644 --- a/tests/unittests/pcap/mac_pcap_test.cpp +++ b/tests/unittests/pcap/mac_pcap_test.cpp @@ -236,8 +236,10 @@ void write_pcap_nr_thread_function_spans(srsran::mac_pcap* pcap, uint32_t num_pd // Write #num_pdus DL MAC NR PDUs using PCAP handle (byte_buffer) void write_pcap_nr_thread_function_byte_buffer(srsran::mac_pcap* pcap, uint32_t num_pdus) { - srsran::byte_buffer tv = { - 0x04, 0x0a, 0x0d, 0x72, 0x80, 0xd3, 0x96, 0x02, 0x7b, 0x01, 0xbd, 0x26, 0x3f, 0x00, 0x00, 0x00, 0x00}; + srsran::byte_buffer tv = + byte_buffer::create( + {0x04, 0x0a, 0x0d, 0x72, 0x80, 0xd3, 0x96, 0x02, 0x7b, 0x01, 0xbd, 0x26, 0x3f, 0x00, 0x00, 0x00, 0x00}) + .value(); int crnti = 0x01011; int ue_id = 2; int harqid = 0; @@ -262,7 +264,6 @@ void write_pcap_nr_thread_function_byte_buffer(srsran::mac_pcap* pcap, uint32_t void write_pcap_nr_thread_function_large_byte_buffer(srsran::mac_pcap* pcap, uint32_t num_pdus) { srsran::byte_buffer tv = srsran::make_byte_buffer( - "44057e80042080042045000578b506400040066c1c0a2d0001" "0a2d0003145196440dc78535f4439577801001fd348500000101080a7e069e553740bf250a43116ae9c7fb384dde95580b51f982cee5b1d7" "2ffb703548c3f9a9220c5434ff30c1d04affa45a62c111fa45e4099dfec3dd946df21545009889b77dcda48b80de4903c13b8844a6dcb31e" @@ -1689,9 +1690,7 @@ void write_pcap_nr_thread_function_large_byte_buffer(srsran::mac_pcap* pcap, uin "b620b47ba9fefa47b9cbbc7fc97c17ae9713dffaad490e42f40093106a92df63200253682f2e32f1a7fcb7bbe6ef37abe0fc5275b3d99b9d" "dd97149c9b466d622b7a641f5a8916dc81cf160f8938185057a770ef7b20de955e30fa904ddc828b97f7e4ad111462dd9bb9b724f8b29d42" "c94a12d6ad43edf2697ffa4a62c12ab00378912b106efd2c50e8c46a3a1f8b682c11f8702ce1591e27042413e38c340def44b68a94a4e761" - "beb25106cf2e60c0aa9f8c0f745bdc1ecb8e9bfe71e9b4846bbea0dc5d2d982d17176c3119432b90e3a8f48195d21a06" - - ); + "beb25106cf2e60c0aa9f8c0f745bdc1ecb8e9bfe71e9b4846bbea0dc5d2d982d17176c3119432b90e3a8f48195d21a06"); int crnti = 0x01011; int ue_id = 2; diff --git a/tests/unittests/pcap/ngap_pcap_test.cpp b/tests/unittests/pcap/ngap_pcap_test.cpp index e8493361d1..f6b37f8f0c 100644 --- a/tests/unittests/pcap/ngap_pcap_test.cpp +++ b/tests/unittests/pcap/ngap_pcap_test.cpp @@ -126,10 +126,12 @@ void write_pcap_ngap_thread_function_spans(srsran::dlt_pcap* pcap, uint32_t num_ // Write #num_pdus DL MAC NR PDUs using PCAP handle (byte_buffer) void write_pcap_ngap_thread_function_byte_buffer(srsran::dlt_pcap* pcap, uint32_t num_pdus) { - srsran::byte_buffer tv = {0x00, 0x15, 0x00, 0x33, 0x00, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x08, 0x00, 0x00, 0xf1, - 0x10, 0x00, 0x00, 0x06, 0x6c, 0x00, 0x52, 0x40, 0x0a, 0x03, 0x80, 0x73, 0x72, 0x73, - 0x67, 0x6e, 0x62, 0x30, 0x31, 0x00, 0x66, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x40, 0x01, 0x60}; + srsran::byte_buffer tv = + byte_buffer::create({0x00, 0x15, 0x00, 0x33, 0x00, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x08, 0x00, 0x00, 0xf1, + 0x10, 0x00, 0x00, 0x06, 0x6c, 0x00, 0x52, 0x40, 0x0a, 0x03, 0x80, 0x73, 0x72, 0x73, + 0x67, 0x6e, 0x62, 0x30, 0x31, 0x00, 0x66, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x40, 0x01, 0x60}) + .value(); for (uint32_t i = 0; i < num_pdus; i++) { pcap->push_pdu(tv.copy()); } diff --git a/tests/unittests/pdcp/pdcp_gen_helper.cpp b/tests/unittests/pdcp/pdcp_gen_helper.cpp index bf7b2e9721..b7fe69ba06 100644 --- a/tests/unittests/pdcp/pdcp_gen_helper.cpp +++ b/tests/unittests/pdcp/pdcp_gen_helper.cpp @@ -158,7 +158,7 @@ int main(int argc, char** argv) pdcp_tx->set_ciphering(security::ciphering_enabled::on); // Write SDU - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); logger.info(frame.pdu_queue.front().buf.begin(), frame.pdu_queue.front().buf.end(), diff --git a/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp b/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp index 3028d5cd04..cb6a885e0d 100644 --- a/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp @@ -50,7 +50,7 @@ TEST_P(pdcp_rx_metrics_test, sdu_pdu_metrics) pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu)).value()); auto m = pdcp_rx->get_metrics(); ASSERT_EQ(m.num_pdus, 1); @@ -100,7 +100,7 @@ TEST_P(pdcp_rx_metrics_test, integrity_metrics) pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu)).value()); auto m = pdcp_rx->get_metrics(); ASSERT_EQ(m.num_pdus, 1); @@ -146,7 +146,7 @@ TEST_P(pdcp_rx_metrics_test, rx_reordering_timer) get_test_pdu(count + 1, test_pdu2); pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); tick_all(10); auto m = pdcp_rx->get_metrics(); diff --git a/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp b/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp index 67b31170da..959a1f1a79 100644 --- a/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp @@ -53,9 +53,9 @@ TEST_P(pdcp_rx_reestablish_test, when_srb_reestablish_then_sdus_dropped) // RX PDU 2 and 3, none should arrive. pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu3)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu3)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // Check PDCP state. @@ -100,9 +100,9 @@ TEST_P(pdcp_rx_reestablish_test, when_drb_um_reestablish_then_pdus_forwared) // RX PDU 2 and 3, none should arrive. pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu3)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu3)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // Check PDCP state. @@ -147,9 +147,9 @@ TEST_P(pdcp_rx_reestablish_test, when_drb_am_reestablish_then_state_preserved) // RX PDU 2 and 3, none should arrive. pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu3)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu3)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // Check PDCP state. @@ -173,7 +173,7 @@ TEST_P(pdcp_rx_reestablish_test, when_drb_am_reestablish_then_state_preserved) ASSERT_EQ(true, pdcp_rx->is_reordering_timer_running()); // Deliver first PDU - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(3, test_frame->sdu_queue.size()); } diff --git a/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp b/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp index 3796a9a2ef..a11c0ba6e8 100644 --- a/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp @@ -61,7 +61,7 @@ TEST_P(pdcp_rx_status_report_test, build_status_report) for (uint32_t i = count + 5; i > count; i--) { byte_buffer test_pdu; get_test_pdu(i, test_pdu); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu)).value()); // Check status report while Rx'ing PDUs in reverse order (bitmap present) status_report = pdcp_rx->compile_status_report(); @@ -83,7 +83,7 @@ TEST_P(pdcp_rx_status_report_test, build_status_report) byte_buffer test_pdu; get_test_pdu(count, test_pdu); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu)).value()); // Check status report in the final state (no bitmap present) status_report = pdcp_rx->compile_status_report(); @@ -131,11 +131,11 @@ TEST_P(pdcp_rx_status_report_test, build_truncated_status_report) byte_buffer test_pdu1; get_test_pdu(count + (9000 - 5) * 8, test_pdu1); // Rx PDU with a COUNT value at max capacity of the report - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); byte_buffer test_pdu2; get_test_pdu(count + 1 + (9000 - 5) * 8, test_pdu2); // Rx PDU with a COUNT value beyond max capacity of the report - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); // Check status report in the final state (truncated bitmap present) status_report = pdcp_rx->compile_status_report(); @@ -185,7 +185,7 @@ TEST_P(pdcp_rx_status_report_test, rx_status_report) enc.pack(0xcafe, 16); // Put into PDCP Rx entity - pdcp_rx->handle_pdu(byte_buffer_chain{buf.deep_copy()}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(buf.deep_copy().value()).value()); // Check the status report was forwared to the Tx entity ASSERT_FALSE(test_frame->status_report_queue.empty()); diff --git a/tests/unittests/pdcp/pdcp_rx_test.cpp b/tests/unittests/pdcp/pdcp_rx_test.cpp index 4c13a9cdb6..641bfb3824 100644 --- a/tests/unittests/pdcp/pdcp_rx_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_test.cpp @@ -86,9 +86,9 @@ TEST_P(pdcp_rx_test, rx_in_order) get_test_pdu(count + 1, test_pdu2); pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(1, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(2, test_frame->sdu_queue.size()); while (not test_frame->sdu_queue.empty()) { ASSERT_EQ(test_frame->sdu_queue.front(), sdu1); @@ -131,19 +131,19 @@ TEST_P(pdcp_rx_test, rx_out_of_order) pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // check rx_reord matches rx_next matches count + 2 EXPECT_EQ(pdcp_rx->get_state().rx_reord, count + 2); EXPECT_EQ(pdcp_rx->get_state().rx_reord, pdcp_rx->get_state().rx_next); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu3)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu3)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // check rx_reord still maches count + 2, i.e did not change because t_reord is already running; rx_next moved on EXPECT_EQ(pdcp_rx->get_state().rx_reord, count + 2); EXPECT_EQ(pdcp_rx->get_state().rx_next, count + 3); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(3, test_frame->sdu_queue.size()); while (not test_frame->sdu_queue.empty()) { ASSERT_EQ(test_frame->sdu_queue.front(), sdu1); @@ -183,11 +183,11 @@ TEST_P(pdcp_rx_test, rx_reordering_timer) get_test_pdu(count + 1, test_pdu2); pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); tick_all(10); ASSERT_EQ(1, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(1, test_frame->sdu_queue.size()); while (not test_frame->sdu_queue.empty()) { ASSERT_EQ(test_frame->sdu_queue.front(), sdu1); @@ -226,9 +226,9 @@ TEST_P(pdcp_rx_test, rx_reordering_timer_0ms) get_test_pdu(count + 1, test_pdu2); pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); ASSERT_EQ(1, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(1, test_frame->sdu_queue.size()); while (not test_frame->sdu_queue.empty()) { ASSERT_EQ(test_frame->sdu_queue.front(), sdu1); @@ -268,10 +268,10 @@ TEST_P(pdcp_rx_test, rx_reordering_timer_infinite) get_test_pdu(count + 1, test_pdu2); pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu2)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu2)).value()); tick_all(6000); // max t-Reordering is 3000ms ASSERT_EQ(0, test_frame->sdu_queue.size()); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(2, test_frame->sdu_queue.size()); while (not test_frame->sdu_queue.empty()) { ASSERT_EQ(test_frame->sdu_queue.front(), sdu1); @@ -308,7 +308,7 @@ TEST_P(pdcp_rx_test, rx_integrity_fail) ASSERT_TRUE(test_pdu1.append(0)); // mess up MAC-I pdcp_rx_state init_state = {.rx_next = count, .rx_deliv = count, .rx_reord = 0}; pdcp_rx->set_state(init_state); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(test_pdu1)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(test_pdu1)).value()); ASSERT_EQ(0, test_frame->sdu_queue.size()); // TODO: Re-enable once the RRC supports notifications from the PDCP // ASSERT_EQ(1, test_frame->integrity_fail_counter); @@ -349,7 +349,7 @@ TEST_P(pdcp_rx_test, count_wraparound) for (uint32_t i = 0; i < n_sdus; i++) { byte_buffer pdu; get_test_pdu(count + i, pdu); - pdcp_rx->handle_pdu(byte_buffer_chain{std::move(pdu)}); + pdcp_rx->handle_pdu(byte_buffer_chain::create(std::move(pdu)).value()); } // check nof max_count reached and max protocol failures. diff --git a/tests/unittests/pdcp/pdcp_test_vectors.h b/tests/unittests/pdcp/pdcp_test_vectors.h index 3637fc5106..16fcb7ca70 100644 --- a/tests/unittests/pdcp/pdcp_test_vectors.h +++ b/tests/unittests/pdcp/pdcp_test_vectors.h @@ -258,52 +258,52 @@ inline bool get_pdu_test_vector_algo1(pdcp_sn_size sn_size, uint32_t count, byte if (sn_size == pdcp_sn_size::size12bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo1_count0_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count0_snlen12).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo1_count1_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count1_snlen12).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo1_count2_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count2_snlen12).value(); return true; case 2047: - exp_pdu = byte_buffer{pdu1_algo1_count2047_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count2047_snlen12).value(); return true; case 2048: - exp_pdu = byte_buffer{pdu1_algo1_count2048_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count2048_snlen12).value(); return true; case 2049: - exp_pdu = byte_buffer{pdu1_algo1_count2049_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count2049_snlen12).value(); return true; case 4095: - exp_pdu = byte_buffer{pdu1_algo1_count4095_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count4095_snlen12).value(); return true; case 4096: - exp_pdu = byte_buffer{pdu1_algo1_count4096_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count4096_snlen12).value(); return true; case 4097: - exp_pdu = byte_buffer{pdu1_algo1_count4097_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count4097_snlen12).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo1_count262143_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262143_snlen12).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo1_count262144_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262144_snlen12).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo1_count262145_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262145_snlen12).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo1_count262146_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262146_snlen12).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo1_count262147_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262147_snlen12).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo1_count262148_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262148_snlen12).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo1_count4294967295_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo1_count4294967295_snlen12).value(); return true; default: return false; @@ -311,49 +311,49 @@ inline bool get_pdu_test_vector_algo1(pdcp_sn_size sn_size, uint32_t count, byte } else if (sn_size == pdcp_sn_size::size18bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo1_count0_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count0_snlen18).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo1_count1_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count1_snlen18).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo1_count2_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count2_snlen18).value(); return true; case 131071: - exp_pdu = byte_buffer{pdu1_algo1_count131071_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count131071_snlen18).value(); return true; case 131072: - exp_pdu = byte_buffer{pdu1_algo1_count131072_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count131072_snlen18).value(); return true; case 131073: - exp_pdu = byte_buffer{pdu1_algo1_count131073_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count131073_snlen18).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo1_count262143_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262143_snlen18).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo1_count262144_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262144_snlen18).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo1_count262145_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262145_snlen18).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo1_count262146_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262146_snlen18).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo1_count262147_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262147_snlen18).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo1_count262148_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count262148_snlen18).value(); return true; case 334103: - exp_pdu = byte_buffer{pdu1_algo1_count334103_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count334103_snlen18).value(); return true; case 334104: - exp_pdu = byte_buffer{pdu1_algo1_count334104_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count334104_snlen18).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo1_count4294967295_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo1_count4294967295_snlen18).value(); return true; default: return false; @@ -374,52 +374,52 @@ inline bool get_pdu_test_vector_algo2(pdcp_sn_size sn_size, uint32_t count, byte if (sn_size == pdcp_sn_size::size12bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo2_count0_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count0_snlen12).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo2_count1_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count1_snlen12).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo2_count2_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count2_snlen12).value(); return true; case 2047: - exp_pdu = byte_buffer{pdu1_algo2_count2047_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count2047_snlen12).value(); return true; case 2048: - exp_pdu = byte_buffer{pdu1_algo2_count2048_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count2048_snlen12).value(); return true; case 2049: - exp_pdu = byte_buffer{pdu1_algo2_count2049_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count2049_snlen12).value(); return true; case 4095: - exp_pdu = byte_buffer{pdu1_algo2_count4095_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count4095_snlen12).value(); return true; case 4096: - exp_pdu = byte_buffer{pdu1_algo2_count4096_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count4096_snlen12).value(); return true; case 4097: - exp_pdu = byte_buffer{pdu1_algo2_count4097_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count4097_snlen12).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo2_count262143_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262143_snlen12).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo2_count262144_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262144_snlen12).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo2_count262145_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262145_snlen12).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo2_count262146_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262146_snlen12).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo2_count262147_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262147_snlen12).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo2_count262148_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262148_snlen12).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo2_count4294967295_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo2_count4294967295_snlen12).value(); return true; default: return false; @@ -427,49 +427,49 @@ inline bool get_pdu_test_vector_algo2(pdcp_sn_size sn_size, uint32_t count, byte } else if (sn_size == pdcp_sn_size::size18bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo2_count0_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count0_snlen18).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo2_count1_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count1_snlen18).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo2_count2_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count2_snlen18).value(); return true; case 131071: - exp_pdu = byte_buffer{pdu1_algo2_count131071_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count131071_snlen18).value(); return true; case 131072: - exp_pdu = byte_buffer{pdu1_algo2_count131072_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count131072_snlen18).value(); return true; case 131073: - exp_pdu = byte_buffer{pdu1_algo2_count131073_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count131073_snlen18).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo2_count262143_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262143_snlen18).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo2_count262144_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262144_snlen18).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo2_count262145_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262145_snlen18).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo2_count262146_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262146_snlen18).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo2_count262147_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262147_snlen18).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo2_count262148_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count262148_snlen18).value(); return true; case 334103: - exp_pdu = byte_buffer{pdu1_algo2_count334103_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count334103_snlen18).value(); return true; case 334104: - exp_pdu = byte_buffer{pdu1_algo2_count334104_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count334104_snlen18).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo2_count4294967295_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo2_count4294967295_snlen18).value(); return true; default: return false; @@ -490,52 +490,52 @@ inline bool get_pdu_test_vector_algo3(pdcp_sn_size sn_size, uint32_t count, byte if (sn_size == pdcp_sn_size::size12bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo3_count0_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count0_snlen12).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo3_count1_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count1_snlen12).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo3_count2_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count2_snlen12).value(); return true; case 2047: - exp_pdu = byte_buffer{pdu1_algo3_count2047_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count2047_snlen12).value(); return true; case 2048: - exp_pdu = byte_buffer{pdu1_algo3_count2048_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count2048_snlen12).value(); return true; case 2049: - exp_pdu = byte_buffer{pdu1_algo3_count2049_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count2049_snlen12).value(); return true; case 4095: - exp_pdu = byte_buffer{pdu1_algo3_count4095_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count4095_snlen12).value(); return true; case 4096: - exp_pdu = byte_buffer{pdu1_algo3_count4096_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count4096_snlen12).value(); return true; case 4097: - exp_pdu = byte_buffer{pdu1_algo3_count4097_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count4097_snlen12).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo3_count262143_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262143_snlen12).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo3_count262144_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262144_snlen12).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo3_count262145_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262145_snlen12).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo3_count262146_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262146_snlen12).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo3_count262147_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262147_snlen12).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo3_count262148_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262148_snlen12).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo3_count4294967295_snlen12}; + exp_pdu = byte_buffer::create(pdu1_algo3_count4294967295_snlen12).value(); return true; default: return false; @@ -543,49 +543,49 @@ inline bool get_pdu_test_vector_algo3(pdcp_sn_size sn_size, uint32_t count, byte } else if (sn_size == pdcp_sn_size::size18bits) { switch (count) { case 0: - exp_pdu = byte_buffer{pdu1_algo3_count0_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count0_snlen18).value(); return true; case 1: - exp_pdu = byte_buffer{pdu1_algo3_count1_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count1_snlen18).value(); return true; case 2: - exp_pdu = byte_buffer{pdu1_algo3_count2_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count2_snlen18).value(); return true; case 131071: - exp_pdu = byte_buffer{pdu1_algo3_count131071_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count131071_snlen18).value(); return true; case 131072: - exp_pdu = byte_buffer{pdu1_algo3_count131072_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count131072_snlen18).value(); return true; case 131073: - exp_pdu = byte_buffer{pdu1_algo3_count131073_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count131073_snlen18).value(); return true; case 262143: - exp_pdu = byte_buffer{pdu1_algo3_count262143_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262143_snlen18).value(); return true; case 262144: - exp_pdu = byte_buffer{pdu1_algo3_count262144_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262144_snlen18).value(); return true; case 262145: - exp_pdu = byte_buffer{pdu1_algo3_count262145_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262145_snlen18).value(); return true; case 262146: - exp_pdu = byte_buffer{pdu1_algo3_count262146_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262146_snlen18).value(); return true; case 262147: - exp_pdu = byte_buffer{pdu1_algo3_count262147_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262147_snlen18).value(); return true; case 262148: - exp_pdu = byte_buffer{pdu1_algo3_count262148_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count262148_snlen18).value(); return true; case 334103: - exp_pdu = byte_buffer{pdu1_algo3_count334103_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count334103_snlen18).value(); return true; case 334104: - exp_pdu = byte_buffer{pdu1_algo3_count334104_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count334104_snlen18).value(); return true; case 4294967295: - exp_pdu = byte_buffer{pdu1_algo3_count4294967295_snlen18}; + exp_pdu = byte_buffer::create(pdu1_algo3_count4294967295_snlen18).value(); return true; default: return false; diff --git a/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp b/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp index 4788151d93..546117d815 100644 --- a/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp @@ -68,8 +68,12 @@ TEST_P(pdcp_tx_empty_pool_test, empty_pool) // Write first SDU for (uint32_t i = 0; i < n_sdus; i++) { - byte_buffer sdu = {sdu1}; - pdcp_tx->handle_sdu(std::move(sdu)); + auto sdu_buf = byte_buffer::create(sdu1); + if (sdu_buf.is_error()) { + pdcp_tx->handle_sdu({}); + break; + } + pdcp_tx->handle_sdu(std::move(sdu_buf.value())); } // check nof max_count reached and max protocol failures. ASSERT_NE(test_frame.pdu_queue.size(), n_sdus); diff --git a/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp b/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp index fa76d2bc5b..a13a6008d6 100644 --- a/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp @@ -46,7 +46,7 @@ TEST_P(pdcp_tx_metrics_test, sdu_pdu) pdcp_tx->set_ciphering(security::ciphering_enabled::on); // Write SDU - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(st.tx_next + 1, sn_size)); diff --git a/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp b/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp index 668fda3287..d702d1b8a0 100644 --- a/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp @@ -44,7 +44,7 @@ TEST_P(pdcp_tx_reestablish_test, when_srb_reestablish_then_pdus_dropped) // Write 5 SDU int n_pdus = 5; for (int i = 0; i < n_pdus; i++) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); } @@ -69,7 +69,7 @@ TEST_P(pdcp_tx_reestablish_test, when_drb_um_reestablish_then_pdus_and_discard_t // Write 5 SDU int n_pdus = 5; for (int i = 0; i < n_pdus; i++) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); } ASSERT_EQ(5, pdcp_tx->nof_discard_timers()); @@ -93,7 +93,7 @@ TEST_P(pdcp_tx_reestablish_test, when_drb_am_reestablish_then_pdus_retx) // Write 5 SDU int n_pdus = 5; for (int i = 0; i < n_pdus; i++) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); } tick_all(5); diff --git a/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp b/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp index a448b583d6..5898be1f97 100644 --- a/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp @@ -47,7 +47,7 @@ TEST_P(pdcp_tx_status_report_test, handle_status_report) srsran::test_delimit_logger delimiter("Testing data recovery. SN_SIZE={} COUNT={}", sn_size, tx_next); for (uint32_t count = tx_next; count < tx_next + n_sdus; ++count) { // Write SDU - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(count, sn_size)); @@ -81,7 +81,7 @@ TEST_P(pdcp_tx_status_report_test, handle_status_report) enc.pack(0b10100000, 8); // Handle this status report - pdcp_tx->on_status_report(byte_buffer_chain{std::move(buf)}); + pdcp_tx->on_status_report(byte_buffer_chain::create(std::move(buf)).value()); // Verify discard { @@ -141,7 +141,7 @@ TEST_P(pdcp_tx_status_report_test, data_recovery) srsran::test_delimit_logger delimiter("Testing data recovery. SN_SIZE={} COUNT={}", sn_size, tx_next); for (uint32_t count = tx_next; count < tx_next + n_sdus; ++count) { // Write SDU - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(count, sn_size)); diff --git a/tests/unittests/pdcp/pdcp_tx_test.cpp b/tests/unittests/pdcp/pdcp_tx_test.cpp index 750b3fa7f8..54146f57d1 100644 --- a/tests/unittests/pdcp/pdcp_tx_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_test.cpp @@ -85,7 +85,7 @@ TEST_P(pdcp_tx_test, pdu_gen) pdcp_tx->set_ciphering(security::ciphering_enabled::on); // Write SDU - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Get generated PDU @@ -135,7 +135,7 @@ TEST_P(pdcp_tx_test, pdu_stall) // Write SDU for (uint32_t count = tx_next; count < tx_next + stall; ++count) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is a new PDU @@ -145,7 +145,7 @@ TEST_P(pdcp_tx_test, pdu_stall) } { // Write an SDU that should be dropped - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is no new PDU @@ -156,7 +156,7 @@ TEST_P(pdcp_tx_test, pdu_stall) pdcp_tx->handle_transmit_notification(pdcp_compute_sn(tx_next + stall - 1, sn_size)); // Write an SDU that should be dropped - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is no new PDU @@ -193,14 +193,14 @@ TEST_P(pdcp_tx_test, discard_timer_and_expiry) // Write first SDU { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(tx_next, sn_size)); ASSERT_EQ(1, pdcp_tx->nof_discard_timers()); } // Write second SDU { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(tx_next + 1, sn_size)); ASSERT_EQ(2, pdcp_tx->nof_discard_timers()); @@ -242,7 +242,7 @@ TEST_P(pdcp_tx_test, discard_timer_and_stop) // Write SDUs for (uint32_t i = 0; i < nof_sdus; i++) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(st.tx_next, sn_size)); ASSERT_EQ(i + 1, pdcp_tx->nof_discard_timers()); @@ -324,7 +324,7 @@ TEST_P(pdcp_tx_test, pdu_stall_with_discard) // Write SDU for (uint32_t count = tx_next; count < tx_next + stall; ++count) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is a new PDU @@ -334,7 +334,7 @@ TEST_P(pdcp_tx_test, pdu_stall_with_discard) } { // Write an SDU that should be dropped - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is no new PDU @@ -349,7 +349,7 @@ TEST_P(pdcp_tx_test, pdu_stall_with_discard) // Check that we can write PDUs again for (uint32_t count = tx_next + stall; count < tx_next + 2 * stall; ++count) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is a new PDU @@ -359,7 +359,7 @@ TEST_P(pdcp_tx_test, pdu_stall_with_discard) } { // Write an SDU that should be dropped - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is no new PDU @@ -370,7 +370,7 @@ TEST_P(pdcp_tx_test, pdu_stall_with_discard) pdcp_tx->handle_transmit_notification(pdcp_compute_sn(tx_next + 2 * stall - 1, sn_size)); // Write an SDU that should not be dropped - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); // Check there is a new PDU @@ -415,7 +415,7 @@ TEST_P(pdcp_tx_test, count_wraparound) // Write first SDU for (uint32_t i = 0; i < n_sdus; i++) { - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); pdcp_tx->handle_sdu(std::move(sdu)); pdcp_tx->handle_transmit_notification(pdcp_compute_sn(st.tx_next + i, sn_size)); } @@ -438,27 +438,27 @@ TEST_P(pdcp_tx_test, count_wraparound) TEST_P(pdcp_tx_test_short_rlc_queue, discard_on_full_rlc_sdu_queue) { init(GetParam()); - byte_buffer sdu = {sdu1}; + byte_buffer sdu = byte_buffer::create(sdu1).value(); // Fill the RLC SDU queue for (uint32_t i = 0; i < config.custom.rlc_sdu_queue; i++) { - pdcp_tx->handle_sdu(sdu.deep_copy()); + pdcp_tx->handle_sdu(sdu.deep_copy().value()); ASSERT_EQ(test_frame.pdu_queue.size(), 1); test_frame.pdu_queue.pop(); } // Any further SDUs should be discarded and not forwarded to lower layers - pdcp_tx->handle_sdu(sdu.deep_copy()); + pdcp_tx->handle_sdu(sdu.deep_copy().value()); ASSERT_TRUE(test_frame.pdu_queue.empty()); // Make room for one more SDU and check if one PDU will be passed to lower layers pdcp_tx->handle_transmit_notification(0); - pdcp_tx->handle_sdu(sdu.deep_copy()); + pdcp_tx->handle_sdu(sdu.deep_copy().value()); ASSERT_EQ(test_frame.pdu_queue.size(), 1); test_frame.pdu_queue.pop(); // Any further SDUs should be discarded and not forwarded to lower layers - pdcp_tx->handle_sdu(sdu.deep_copy()); + pdcp_tx->handle_sdu(sdu.deep_copy().value()); ASSERT_TRUE(test_frame.pdu_queue.empty()); } diff --git a/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.h b/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.h index a169aecf08..9c6f1ff175 100644 --- a/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.h +++ b/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 13-12-2023 (seed 0): +// This file was generated using the following MATLAB class on 05-03-2024 (seed 0): // + "srsPDCCHModulatorUnittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -42,22 +42,22 @@ struct test_case_t { static const std::vector pdcch_modulator_test_data = { // clang-format off - {{{0, 0, 0, 0, 0, 0, 0, 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}, 3, 1, 608, 3085, 1, default_precoding}, {"test_data/pdcch_modulator_test_input0.dat"}, {"test_data/pdcch_modulator_test_output0.dat"}}, + {{{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}, 3, 1, 608, 3084, 1, default_precoding}, {"test_data/pdcch_modulator_test_input0.dat"}, {"test_data/pdcch_modulator_test_output0.dat"}}, {{{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}, 10, 1, 451, 1983, 1, default_precoding}, {"test_data/pdcch_modulator_test_input1.dat"}, {"test_data/pdcch_modulator_test_output1.dat"}}, - {{{1, 1, 1, 1, 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}, 11, 1, 122, 33801, 1, default_precoding}, {"test_data/pdcch_modulator_test_input2.dat"}, {"test_data/pdcch_modulator_test_output2.dat"}}, - {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 2, 1, 447, 2747, 1, default_precoding}, {"test_data/pdcch_modulator_test_input3.dat"}, {"test_data/pdcch_modulator_test_output3.dat"}}, - {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 12, 1, 871, 26161, 1, default_precoding}, {"test_data/pdcch_modulator_test_input4.dat"}, {"test_data/pdcch_modulator_test_output4.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 5, 2, 771, 3978, 1, default_precoding}, {"test_data/pdcch_modulator_test_input5.dat"}, {"test_data/pdcch_modulator_test_output5.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 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}, 8, 2, 98, 10335, 1, default_precoding}, {"test_data/pdcch_modulator_test_input6.dat"}, {"test_data/pdcch_modulator_test_output6.dat"}}, + {{{1, 1, 1, 1, 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}, 11, 1, 122, 33792, 1, default_precoding}, {"test_data/pdcch_modulator_test_input2.dat"}, {"test_data/pdcch_modulator_test_output2.dat"}}, + {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 2, 1, 447, 2746, 1, default_precoding}, {"test_data/pdcch_modulator_test_input3.dat"}, {"test_data/pdcch_modulator_test_output3.dat"}}, + {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 12, 1, 871, 26155, 1, default_precoding}, {"test_data/pdcch_modulator_test_input4.dat"}, {"test_data/pdcch_modulator_test_output4.dat"}}, + {{{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}, 5, 2, 771, 3977, 1, default_precoding}, {"test_data/pdcch_modulator_test_input5.dat"}, {"test_data/pdcch_modulator_test_output5.dat"}}, + {{{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}, 8, 2, 98, 10332, 1, default_precoding}, {"test_data/pdcch_modulator_test_input6.dat"}, {"test_data/pdcch_modulator_test_output6.dat"}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 11, 2, 745, 66, 1, default_precoding}, {"test_data/pdcch_modulator_test_input7.dat"}, {"test_data/pdcch_modulator_test_output7.dat"}}, - {{{0, 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, 1, 1, 1, 1, 0, 0, 0, 0}, 12, 2, 173, 37852, 1, default_precoding}, {"test_data/pdcch_modulator_test_input8.dat"}, {"test_data/pdcch_modulator_test_output8.dat"}}, - {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 1, 2, 332, 32278, 1, default_precoding}, {"test_data/pdcch_modulator_test_input9.dat"}, {"test_data/pdcch_modulator_test_output9.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0}, 11, 3, 634, 44988, 1, default_precoding}, {"test_data/pdcch_modulator_test_input10.dat"}, {"test_data/pdcch_modulator_test_output10.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 11, 3, 555, 56472, 1, default_precoding}, {"test_data/pdcch_modulator_test_input11.dat"}, {"test_data/pdcch_modulator_test_output11.dat"}}, + {{{1, 1, 1, 1, 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}, 12, 2, 173, 37843, 1, default_precoding}, {"test_data/pdcch_modulator_test_input8.dat"}, {"test_data/pdcch_modulator_test_output8.dat"}}, + {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, 1, 2, 332, 32270, 1, default_precoding}, {"test_data/pdcch_modulator_test_input9.dat"}, {"test_data/pdcch_modulator_test_output9.dat"}}, + {{{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, 0, 0, 0, 0, 0, 0}, 11, 3, 634, 44977, 1, default_precoding}, {"test_data/pdcch_modulator_test_input10.dat"}, {"test_data/pdcch_modulator_test_output10.dat"}}, + {{{0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 3, 555, 56458, 1, default_precoding}, {"test_data/pdcch_modulator_test_input11.dat"}, {"test_data/pdcch_modulator_test_output11.dat"}}, {{{0, 0, 0, 0, 0, 0, 0, 0, 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}, 7, 3, 970, 1588, 1, default_precoding}, {"test_data/pdcch_modulator_test_input12.dat"}, {"test_data/pdcch_modulator_test_output12.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 9, 3, 395, 22542, 1, default_precoding}, {"test_data/pdcch_modulator_test_input13.dat"}, {"test_data/pdcch_modulator_test_output13.dat"}}, - {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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}, 4, 3, 931, 11535, 1, default_precoding}, {"test_data/pdcch_modulator_test_input14.dat"}, {"test_data/pdcch_modulator_test_output14.dat"}}, - {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0}, 3, 3, 698, 13475, 1, default_precoding}, {"test_data/pdcch_modulator_test_input15.dat"}, {"test_data/pdcch_modulator_test_output15.dat"}}, + {{{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}, 9, 3, 395, 22536, 1, default_precoding}, {"test_data/pdcch_modulator_test_input13.dat"}, {"test_data/pdcch_modulator_test_output13.dat"}}, + {{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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}, 4, 3, 931, 11532, 1, default_precoding}, {"test_data/pdcch_modulator_test_input14.dat"}, {"test_data/pdcch_modulator_test_output14.dat"}}, + {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0}, 3, 3, 698, 13471, 1, default_precoding}, {"test_data/pdcch_modulator_test_input15.dat"}, {"test_data/pdcch_modulator_test_output15.dat"}}, // clang-format on }; diff --git a/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.h b/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.h index 5a0c8d2d3e..65f8b0cc92 100644 --- a/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.h +++ b/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 14-09-2023 (seed 0): +// This file was generated using the following MATLAB class on 05-03-2024 (seed 0): // + "srsPDCCHProcessorUnittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -40,122 +40,122 @@ struct test_case_t { }; static const std::vector pdcch_processor_test_data = { - // clang-format off - {{nullopt, {0, 999}, cyclic_prefix::NORMAL, {25, 0, 12, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8322, 821, 821, 8322, 0, 1, 0, 0, {1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output0.dat"}}, - {{nullopt, {0, 3481}, cyclic_prefix::NORMAL, {25, 0, 7, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7798, 660, 660, 7798, 2, 2, 0, 0, {1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output1.dat"}}, - {{nullopt, {0, 777}, cyclic_prefix::NORMAL, {25, 0, 5, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {49396, 288, 288, 49396, 0, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output2.dat"}}, - {{nullopt, {0, 9672}, cyclic_prefix::NORMAL, {25, 0, 1, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {27346, 185, 185, 27346, 7, 1, 0, 0, {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output3.dat"}}, - {{nullopt, {0, 3875}, cyclic_prefix::NORMAL, {25, 0, 10, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {53584, 512, 512, 53584, 2, 2, 0, 0, {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output4.dat"}}, - {{nullopt, {0, 5332}, cyclic_prefix::NORMAL, {25, 0, 12, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {30071, 583, 583, 30071, 0, 4, 0, 0, {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output5.dat"}}, - {{nullopt, {0, 619}, cyclic_prefix::NORMAL, {25, 0, 7, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46707, 169, 169, 46707, 0, 8, 0, 0, {0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output6.dat"}}, - {{nullopt, {0, 6720}, cyclic_prefix::NORMAL, {25, 0, 6, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26165, 809, 809, 26165, 1, 1, 0, 0, {0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output7.dat"}}, - {{nullopt, {0, 3775}, cyclic_prefix::NORMAL, {25, 0, 8, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {57794, 32, 32, 57794, 10, 2, 0, 0, {0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output8.dat"}}, - {{nullopt, {0, 6836}, cyclic_prefix::NORMAL, {25, 0, 3, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4455, 677, 677, 4455, 0, 4, 0, 0, {1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output9.dat"}}, - {{nullopt, {0, 6514}, cyclic_prefix::NORMAL, {25, 0, 8, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {42234, 550, 550, 42234, 0, 8, 0, 0, {1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output10.dat"}}, - {{nullopt, {0, 4142}, cyclic_prefix::NORMAL, {52, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {6933, 1001, 1001, 6933, 5, 1, 0, 0, {1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output11.dat"}}, - {{nullopt, {0, 4404}, cyclic_prefix::NORMAL, {52, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17712, 333, 333, 17712, 4, 2, 0, 0, {1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output12.dat"}}, - {{nullopt, {0, 5968}, cyclic_prefix::NORMAL, {52, 0, 13, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {36736, 55, 55, 36736, 0, 4, 0, 0, {1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output13.dat"}}, - {{nullopt, {0, 6350}, cyclic_prefix::NORMAL, {52, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {6927, 955, 955, 6927, 0, 8, 0, 0, {1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output14.dat"}}, - {{nullopt, {0, 555}, cyclic_prefix::NORMAL, {52, 0, 5, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55974, 848, 848, 55974, 13, 1, 0, 0, {0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output15.dat"}}, - {{nullopt, {0, 7957}, cyclic_prefix::NORMAL, {52, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41357, 509, 509, 41357, 4, 2, 0, 0, {0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output16.dat"}}, - {{nullopt, {0, 8877}, cyclic_prefix::NORMAL, {52, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15389, 587, 587, 15389, 0, 4, 0, 0, {0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output17.dat"}}, - {{nullopt, {0, 4999}, cyclic_prefix::NORMAL, {52, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {12285, 110, 110, 12285, 0, 8, 0, 0, {0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output18.dat"}}, - {{nullopt, {0, 1709}, cyclic_prefix::NORMAL, {52, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46315, 77, 77, 46315, 0, 16, 0, 0, {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output19.dat"}}, - {{nullopt, {0, 8136}, cyclic_prefix::NORMAL, {52, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61119, 931, 931, 61119, 8, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output20.dat"}}, - {{nullopt, {0, 3829}, cyclic_prefix::NORMAL, {52, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17388, 178, 178, 17388, 12, 2, 0, 0, {0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output21.dat"}}, - {{nullopt, {0, 6963}, cyclic_prefix::NORMAL, {52, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43409, 772, 772, 43409, 4, 4, 0, 0, {1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output22.dat"}}, - {{nullopt, {0, 1017}, cyclic_prefix::NORMAL, {52, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61241, 836, 836, 61241, 8, 8, 0, 0, {1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output23.dat"}}, - {{nullopt, {0, 9589}, cyclic_prefix::NORMAL, {52, 0, 7, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46764, 934, 934, 46764, 0, 16, 0, 0, {1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output24.dat"}}, - {{nullopt, {0, 853}, cyclic_prefix::NORMAL, {79, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40650, 680, 680, 40650, 1, 1, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output25.dat"}}, - {{nullopt, {0, 10040}, cyclic_prefix::NORMAL, {79, 0, 4, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {36689, 134, 134, 36689, 2, 2, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output26.dat"}}, - {{nullopt, {0, 3336}, cyclic_prefix::NORMAL, {79, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54681, 501, 501, 54681, 8, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output27.dat"}}, - {{nullopt, {0, 5445}, cyclic_prefix::NORMAL, {79, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {33019, 905, 905, 33019, 0, 8, 0, 0, {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output28.dat"}}, - {{nullopt, {0, 8844}, cyclic_prefix::NORMAL, {79, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54540, 19, 19, 54540, 9, 1, 0, 0, {0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output29.dat"}}, - {{nullopt, {0, 5369}, cyclic_prefix::NORMAL, {79, 0, 6, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {14495, 908, 908, 14495, 0, 2, 0, 0, {0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output30.dat"}}, - {{nullopt, {0, 9328}, cyclic_prefix::NORMAL, {79, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26373, 898, 898, 26373, 4, 4, 0, 0, {0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output31.dat"}}, - {{nullopt, {0, 2866}, cyclic_prefix::NORMAL, {79, 0, 1, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {16828, 434, 434, 16828, 8, 8, 0, 0, {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output32.dat"}}, - {{nullopt, {0, 5693}, cyclic_prefix::NORMAL, {79, 0, 1, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {33515, 90, 90, 33515, 0, 16, 0, 0, {1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output33.dat"}}, - {{nullopt, {0, 4347}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {12831, 188, 188, 12831, 15, 1, 0, 0, {1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output34.dat"}}, - {{nullopt, {0, 3778}, cyclic_prefix::NORMAL, {79, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {9339, 16, 16, 9339, 32, 2, 0, 0, {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output35.dat"}}, - {{nullopt, {0, 5533}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {48166, 707, 707, 48166, 16, 4, 0, 0, {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output36.dat"}}, - {{nullopt, {0, 2460}, cyclic_prefix::NORMAL, {79, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {3252, 440, 440, 3252, 24, 8, 0, 0, {1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output37.dat"}}, - {{nullopt, {0, 9164}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40507, 157, 157, 40507, 0, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output38.dat"}}, - {{nullopt, {0, 5539}, cyclic_prefix::NORMAL, {106, 0, 6, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {60914, 864, 864, 60914, 16, 1, 0, 0, {0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output39.dat"}}, - {{nullopt, {0, 2932}, cyclic_prefix::NORMAL, {106, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8493, 899, 899, 8493, 8, 2, 0, 0, {1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output40.dat"}}, +// clang-format off + {{nullopt, {0, 999}, cyclic_prefix::NORMAL, {25, 0, 12, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8320, 821, 821, 8320, 0, 1, 0, 0, {1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output0.dat"}}, + {{nullopt, {0, 3481}, cyclic_prefix::NORMAL, {25, 0, 7, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7796, 660, 660, 7796, 0, 2, 0, 0, {1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output1.dat"}}, + {{nullopt, {0, 777}, cyclic_prefix::NORMAL, {25, 0, 5, 1, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {49384, 288, 288, 49384, 0, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output2.dat"}}, + {{nullopt, {0, 9672}, cyclic_prefix::NORMAL, {25, 0, 1, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {27339, 185, 185, 27339, 2, 1, 0, 0, {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output3.dat"}}, + {{nullopt, {0, 3875}, cyclic_prefix::NORMAL, {25, 0, 10, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {53570, 512, 512, 53570, 2, 2, 0, 0, {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output4.dat"}}, + {{nullopt, {0, 5332}, cyclic_prefix::NORMAL, {25, 0, 12, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {30063, 583, 583, 30063, 0, 4, 0, 0, {1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output5.dat"}}, + {{nullopt, {0, 619}, cyclic_prefix::NORMAL, {25, 0, 7, 2, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46695, 169, 169, 46695, 0, 8, 0, 0, {0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output6.dat"}}, + {{nullopt, {0, 6720}, cyclic_prefix::NORMAL, {25, 0, 6, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26159, 809, 809, 26159, 3, 1, 0, 0, {0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output7.dat"}}, + {{nullopt, {0, 3775}, cyclic_prefix::NORMAL, {25, 0, 8, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {57779, 32, 32, 57779, 10, 2, 0, 0, {0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output8.dat"}}, + {{nullopt, {0, 6836}, cyclic_prefix::NORMAL, {25, 0, 3, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4454, 677, 677, 4454, 0, 4, 0, 0, {1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output9.dat"}}, + {{nullopt, {0, 6514}, cyclic_prefix::NORMAL, {25, 0, 8, 3, {1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {42223, 550, 550, 42223, 0, 8, 0, 0, {1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output10.dat"}}, + {{nullopt, {0, 4142}, cyclic_prefix::NORMAL, {52, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {6931, 1001, 1001, 6931, 5, 1, 0, 0, {1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output11.dat"}}, + {{nullopt, {0, 4404}, cyclic_prefix::NORMAL, {52, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17708, 333, 333, 17708, 0, 2, 0, 0, {1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output12.dat"}}, + {{nullopt, {0, 5968}, cyclic_prefix::NORMAL, {52, 0, 13, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {36727, 55, 55, 36727, 0, 4, 0, 0, {1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output13.dat"}}, + {{nullopt, {0, 6350}, cyclic_prefix::NORMAL, {52, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {6926, 955, 955, 6926, 0, 8, 0, 0, {1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output14.dat"}}, + {{nullopt, {0, 555}, cyclic_prefix::NORMAL, {52, 0, 5, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55960, 848, 848, 55960, 9, 1, 0, 0, {0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output15.dat"}}, + {{nullopt, {0, 7957}, cyclic_prefix::NORMAL, {52, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41347, 509, 509, 41347, 6, 2, 0, 0, {0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output16.dat"}}, + {{nullopt, {0, 8877}, cyclic_prefix::NORMAL, {52, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15385, 587, 587, 15385, 4, 4, 0, 0, {0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output17.dat"}}, + {{nullopt, {0, 4999}, cyclic_prefix::NORMAL, {52, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {12282, 110, 110, 12282, 8, 8, 0, 0, {0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output18.dat"}}, + {{nullopt, {0, 1709}, cyclic_prefix::NORMAL, {52, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46303, 77, 77, 46303, 0, 16, 0, 0, {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output19.dat"}}, + {{nullopt, {0, 8136}, cyclic_prefix::NORMAL, {52, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61104, 931, 931, 61104, 20, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output20.dat"}}, + {{nullopt, {0, 3829}, cyclic_prefix::NORMAL, {52, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17383, 178, 178, 17383, 6, 2, 0, 0, {0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output21.dat"}}, + {{nullopt, {0, 6963}, cyclic_prefix::NORMAL, {52, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43399, 772, 772, 43399, 20, 4, 0, 0, {1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output22.dat"}}, + {{nullopt, {0, 1017}, cyclic_prefix::NORMAL, {52, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61227, 836, 836, 61227, 8, 8, 0, 0, {1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output23.dat"}}, + {{nullopt, {0, 9589}, cyclic_prefix::NORMAL, {52, 0, 7, 3, {1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {46753, 934, 934, 46753, 0, 16, 0, 0, {1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output24.dat"}}, + {{nullopt, {0, 853}, cyclic_prefix::NORMAL, {79, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40640, 680, 680, 40640, 10, 1, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output25.dat"}}, + {{nullopt, {0, 10040}, cyclic_prefix::NORMAL, {79, 0, 4, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {36680, 134, 134, 36680, 8, 2, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output26.dat"}}, + {{nullopt, {0, 3336}, cyclic_prefix::NORMAL, {79, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54667, 501, 501, 54667, 0, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output27.dat"}}, + {{nullopt, {0, 5445}, cyclic_prefix::NORMAL, {79, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {33011, 905, 905, 33011, 0, 8, 0, 0, {0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output28.dat"}}, + {{nullopt, {0, 8844}, cyclic_prefix::NORMAL, {79, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54527, 19, 19, 54527, 6, 1, 0, 0, {0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output29.dat"}}, + {{nullopt, {0, 5369}, cyclic_prefix::NORMAL, {79, 0, 6, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {14492, 908, 908, 14492, 14, 2, 0, 0, {0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output30.dat"}}, + {{nullopt, {0, 9328}, cyclic_prefix::NORMAL, {79, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26367, 898, 898, 26367, 8, 4, 0, 0, {0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output31.dat"}}, + {{nullopt, {0, 2866}, cyclic_prefix::NORMAL, {79, 0, 1, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {16824, 434, 434, 16824, 0, 8, 0, 0, {0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output32.dat"}}, + {{nullopt, {0, 5693}, cyclic_prefix::NORMAL, {79, 0, 1, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {33507, 90, 90, 33507, 0, 16, 0, 0, {1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output33.dat"}}, + {{nullopt, {0, 4347}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {12828, 188, 188, 12828, 5, 1, 0, 0, {1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output34.dat"}}, + {{nullopt, {0, 3778}, cyclic_prefix::NORMAL, {79, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {9337, 16, 16, 9337, 14, 2, 0, 0, {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output35.dat"}}, + {{nullopt, {0, 5533}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {48154, 707, 707, 48154, 12, 4, 0, 0, {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output36.dat"}}, + {{nullopt, {0, 2460}, cyclic_prefix::NORMAL, {79, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {3251, 440, 440, 3251, 8, 8, 0, 0, {1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output37.dat"}}, + {{nullopt, {0, 9164}, cyclic_prefix::NORMAL, {79, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40497, 157, 157, 40497, 16, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output38.dat"}}, + {{nullopt, {0, 5539}, cyclic_prefix::NORMAL, {106, 0, 6, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {60899, 864, 864, 60899, 14, 1, 0, 0, {0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output39.dat"}}, + {{nullopt, {0, 2932}, cyclic_prefix::NORMAL, {106, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8491, 899, 899, 8491, 6, 2, 0, 0, {1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output40.dat"}}, {{nullopt, {0, 2389}, cyclic_prefix::NORMAL, {106, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {382, 441, 441, 382, 12, 4, 0, 0, {1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output41.dat"}}, - {{nullopt, {0, 9971}, cyclic_prefix::NORMAL, {106, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15524, 995, 995, 15524, 0, 8, 0, 0, {1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output42.dat"}}, - {{nullopt, {0, 6458}, cyclic_prefix::NORMAL, {106, 0, 7, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {3319, 986, 986, 3319, 0, 16, 0, 0, {1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output43.dat"}}, - {{nullopt, {0, 5568}, cyclic_prefix::NORMAL, {106, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {34663, 56, 56, 34663, 3, 1, 0, 0, {0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output44.dat"}}, + {{nullopt, {0, 9971}, cyclic_prefix::NORMAL, {106, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15520, 995, 995, 15520, 8, 8, 0, 0, {1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output42.dat"}}, + {{nullopt, {0, 6458}, cyclic_prefix::NORMAL, {106, 0, 7, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {3318, 986, 986, 3318, 0, 16, 0, 0, {1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output43.dat"}}, + {{nullopt, {0, 5568}, cyclic_prefix::NORMAL, {106, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {34654, 56, 56, 34654, 26, 1, 0, 0, {0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output44.dat"}}, {{nullopt, {0, 8675}, cyclic_prefix::NORMAL, {106, 0, 10, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {2101, 29, 29, 2101, 0, 2, 0, 0, {1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output45.dat"}}, - {{nullopt, {0, 2089}, cyclic_prefix::NORMAL, {106, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4494, 252, 252, 4494, 8, 4, 0, 0, {1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output46.dat"}}, - {{nullopt, {0, 1265}, cyclic_prefix::NORMAL, {106, 0, 10, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {52725, 745, 745, 52725, 8, 8, 0, 0, {0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output47.dat"}}, - {{nullopt, {0, 7199}, cyclic_prefix::NORMAL, {106, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {30589, 258, 258, 30589, 0, 16, 0, 0, {1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output48.dat"}}, - {{nullopt, {0, 9391}, cyclic_prefix::NORMAL, {106, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {47750, 590, 590, 47750, 36, 1, 0, 0, {0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output49.dat"}}, - {{nullopt, {0, 4933}, cyclic_prefix::NORMAL, {106, 0, 8, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {64262, 140, 140, 64262, 44, 2, 0, 0, {0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output50.dat"}}, - {{nullopt, {0, 9077}, cyclic_prefix::NORMAL, {106, 0, 4, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37214, 980, 980, 37214, 4, 4, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output51.dat"}}, - {{nullopt, {0, 8465}, cyclic_prefix::NORMAL, {106, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55463, 983, 983, 55463, 8, 8, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output52.dat"}}, - {{nullopt, {0, 598}, cyclic_prefix::NORMAL, {106, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {39514, 133, 133, 39514, 16, 16, 0, 0, {0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output53.dat"}}, - {{nullopt, {0, 5437}, cyclic_prefix::NORMAL, {133, 0, 9, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20184, 68, 68, 20184, 3, 1, 0, 0, {0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output54.dat"}}, - {{nullopt, {0, 3169}, cyclic_prefix::NORMAL, {133, 0, 7, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {35814, 377, 377, 35814, 6, 2, 0, 0, {1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output55.dat"}}, - {{nullopt, {0, 4775}, cyclic_prefix::NORMAL, {133, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61054, 164, 164, 61054, 0, 4, 0, 0, {0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output56.dat"}}, - {{nullopt, {0, 535}, cyclic_prefix::NORMAL, {133, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {51815, 732, 732, 51815, 0, 8, 0, 0, {1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output57.dat"}}, - {{nullopt, {0, 5320}, cyclic_prefix::NORMAL, {133, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {57421, 442, 442, 57421, 0, 16, 0, 0, {0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output58.dat"}}, - {{nullopt, {0, 4942}, cyclic_prefix::NORMAL, {133, 0, 11, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37917, 547, 547, 37917, 8, 1, 0, 0, {0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output59.dat"}}, - {{nullopt, {0, 5738}, cyclic_prefix::NORMAL, {133, 0, 5, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7423, 953, 953, 7423, 34, 2, 0, 0, {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output60.dat"}}, - {{nullopt, {0, 8218}, cyclic_prefix::NORMAL, {133, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22142, 145, 145, 22142, 36, 4, 0, 0, {1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output61.dat"}}, - {{nullopt, {0, 3545}, cyclic_prefix::NORMAL, {133, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {50745, 535, 535, 50745, 0, 8, 0, 0, {1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output62.dat"}}, - {{nullopt, {0, 8122}, cyclic_prefix::NORMAL, {133, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55206, 525, 525, 55206, 16, 16, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output63.dat"}}, - {{nullopt, {0, 8237}, cyclic_prefix::NORMAL, {133, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54472, 73, 73, 54472, 65, 1, 0, 0, {1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output64.dat"}}, - {{nullopt, {0, 3053}, cyclic_prefix::NORMAL, {133, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22753, 666, 666, 22753, 0, 2, 0, 0, {1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output65.dat"}}, - {{nullopt, {0, 5548}, cyclic_prefix::NORMAL, {133, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {34815, 683, 683, 34815, 0, 4, 0, 0, {1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output66.dat"}}, - {{nullopt, {0, 2262}, cyclic_prefix::NORMAL, {133, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61556, 496, 496, 61556, 24, 8, 0, 0, {1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output67.dat"}}, - {{nullopt, {0, 3894}, cyclic_prefix::NORMAL, {133, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40475, 717, 717, 40475, 32, 16, 0, 0, {0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output68.dat"}}, - {{nullopt, {0, 8211}, cyclic_prefix::NORMAL, {160, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {39694, 260, 260, 39694, 10, 1, 0, 0, {1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output69.dat"}}, - {{nullopt, {0, 3562}, cyclic_prefix::NORMAL, {160, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23718, 585, 585, 23718, 24, 2, 0, 0, {0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output70.dat"}}, - {{nullopt, {0, 7089}, cyclic_prefix::NORMAL, {160, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {47421, 839, 839, 47421, 12, 4, 0, 0, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output71.dat"}}, - {{nullopt, {0, 6556}, cyclic_prefix::NORMAL, {160, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23719, 329, 329, 23719, 0, 8, 0, 0, {1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output72.dat"}}, - {{nullopt, {0, 6145}, cyclic_prefix::NORMAL, {160, 0, 13, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41325, 551, 551, 41325, 0, 16, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output73.dat"}}, - {{nullopt, {0, 1294}, cyclic_prefix::NORMAL, {160, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37503, 58, 58, 37503, 7, 1, 0, 0, {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output74.dat"}}, - {{nullopt, {0, 9276}, cyclic_prefix::NORMAL, {160, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {11835, 866, 866, 11835, 16, 2, 0, 0, {1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output75.dat"}}, - {{nullopt, {0, 5554}, cyclic_prefix::NORMAL, {160, 0, 12, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55698, 71, 71, 55698, 44, 4, 0, 0, {1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output76.dat"}}, - {{nullopt, {0, 1040}, cyclic_prefix::NORMAL, {160, 0, 3, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {24717, 930, 930, 24717, 40, 8, 0, 0, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output77.dat"}}, - {{nullopt, {0, 6179}, cyclic_prefix::NORMAL, {160, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {64079, 638, 638, 64079, 16, 16, 0, 0, {0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output78.dat"}}, - {{nullopt, {0, 1238}, cyclic_prefix::NORMAL, {160, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55036, 46, 46, 55036, 71, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output79.dat"}}, - {{nullopt, {0, 9034}, cyclic_prefix::NORMAL, {160, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {29765, 459, 459, 29765, 74, 2, 0, 0, {1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output80.dat"}}, - {{nullopt, {0, 9256}, cyclic_prefix::NORMAL, {160, 0, 4, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {21049, 879, 879, 21049, 4, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output81.dat"}}, - {{nullopt, {0, 8436}, cyclic_prefix::NORMAL, {160, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {29382, 821, 821, 29382, 0, 8, 0, 0, {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output82.dat"}}, - {{nullopt, {0, 4304}, cyclic_prefix::NORMAL, {160, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {27452, 103, 103, 27452, 0, 16, 0, 0, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output83.dat"}}, - {{nullopt, {0, 7278}, cyclic_prefix::NORMAL, {216, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {49981, 671, 671, 49981, 28, 1, 0, 0, {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output84.dat"}}, - {{nullopt, {0, 1505}, cyclic_prefix::NORMAL, {216, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7217, 99, 99, 7217, 30, 2, 0, 0, {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output85.dat"}}, - {{nullopt, {0, 2931}, cyclic_prefix::NORMAL, {216, 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}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {44465, 554, 554, 44465, 32, 4, 0, 0, {1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output86.dat"}}, - {{nullopt, {0, 132}, cyclic_prefix::NORMAL, {216, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43301, 46, 46, 43301, 24, 8, 0, 0, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output87.dat"}}, - {{nullopt, {0, 8113}, cyclic_prefix::NORMAL, {216, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {19658, 61, 61, 19658, 16, 16, 0, 0, {0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output88.dat"}}, + {{nullopt, {0, 2089}, cyclic_prefix::NORMAL, {106, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4493, 252, 252, 4493, 8, 4, 0, 0, {1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output46.dat"}}, + {{nullopt, {0, 1265}, cyclic_prefix::NORMAL, {106, 0, 10, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {52712, 745, 745, 52712, 16, 8, 0, 0, {0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output47.dat"}}, + {{nullopt, {0, 7199}, cyclic_prefix::NORMAL, {106, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {30581, 258, 258, 30581, 16, 16, 0, 0, {1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output48.dat"}}, + {{nullopt, {0, 9391}, cyclic_prefix::NORMAL, {106, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {47738, 590, 590, 47738, 30, 1, 0, 0, {0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output49.dat"}}, + {{nullopt, {0, 4933}, cyclic_prefix::NORMAL, {106, 0, 8, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {64246, 140, 140, 64246, 18, 2, 0, 0, {0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output50.dat"}}, + {{nullopt, {0, 9077}, cyclic_prefix::NORMAL, {106, 0, 4, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37204, 980, 980, 37204, 28, 4, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output51.dat"}}, + {{nullopt, {0, 8465}, cyclic_prefix::NORMAL, {106, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55449, 983, 983, 55449, 40, 8, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output52.dat"}}, + {{nullopt, {0, 598}, cyclic_prefix::NORMAL, {106, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {39505, 133, 133, 39505, 16, 16, 0, 0, {0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output53.dat"}}, + {{nullopt, {0, 5437}, cyclic_prefix::NORMAL, {133, 0, 9, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20179, 68, 68, 20179, 14, 1, 0, 0, {0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output54.dat"}}, + {{nullopt, {0, 3169}, cyclic_prefix::NORMAL, {133, 0, 7, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {35805, 377, 377, 35805, 16, 2, 0, 0, {1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output55.dat"}}, + {{nullopt, {0, 4775}, cyclic_prefix::NORMAL, {133, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61039, 164, 164, 61039, 16, 4, 0, 0, {0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output56.dat"}}, + {{nullopt, {0, 535}, cyclic_prefix::NORMAL, {133, 0, 3, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {51803, 732, 732, 51803, 0, 8, 0, 0, {1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output57.dat"}}, + {{nullopt, {0, 5320}, cyclic_prefix::NORMAL, {133, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {57407, 442, 442, 57407, 0, 16, 0, 0, {0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output58.dat"}}, + {{nullopt, {0, 4942}, cyclic_prefix::NORMAL, {133, 0, 11, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37908, 547, 547, 37908, 23, 1, 0, 0, {0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output59.dat"}}, + {{nullopt, {0, 5738}, cyclic_prefix::NORMAL, {133, 0, 5, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7421, 953, 953, 7421, 18, 2, 0, 0, {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output60.dat"}}, + {{nullopt, {0, 8218}, cyclic_prefix::NORMAL, {133, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22137, 145, 145, 22137, 28, 4, 0, 0, {1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output61.dat"}}, + {{nullopt, {0, 3545}, cyclic_prefix::NORMAL, {133, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {50732, 535, 535, 50732, 8, 8, 0, 0, {1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output62.dat"}}, + {{nullopt, {0, 8122}, cyclic_prefix::NORMAL, {133, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55193, 525, 525, 55193, 16, 16, 0, 0, {1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output63.dat"}}, + {{nullopt, {0, 8237}, cyclic_prefix::NORMAL, {133, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54459, 73, 73, 54459, 20, 1, 0, 0, {1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output64.dat"}}, + {{nullopt, {0, 3053}, cyclic_prefix::NORMAL, {133, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22747, 666, 666, 22747, 20, 2, 0, 0, {1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output65.dat"}}, + {{nullopt, {0, 5548}, cyclic_prefix::NORMAL, {133, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {34807, 683, 683, 34807, 20, 4, 0, 0, {1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output66.dat"}}, + {{nullopt, {0, 2262}, cyclic_prefix::NORMAL, {133, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {61541, 496, 496, 61541, 24, 8, 0, 0, {1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output67.dat"}}, + {{nullopt, {0, 3894}, cyclic_prefix::NORMAL, {133, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {40465, 717, 717, 40465, 16, 16, 0, 0, {0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output68.dat"}}, + {{nullopt, {0, 8211}, cyclic_prefix::NORMAL, {160, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {39685, 260, 260, 39685, 11, 1, 0, 0, {1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output69.dat"}}, + {{nullopt, {0, 3562}, cyclic_prefix::NORMAL, {160, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23713, 585, 585, 23713, 16, 2, 0, 0, {0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output70.dat"}}, + {{nullopt, {0, 7089}, cyclic_prefix::NORMAL, {160, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {47410, 839, 839, 47410, 16, 4, 0, 0, {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output71.dat"}}, + {{nullopt, {0, 6556}, cyclic_prefix::NORMAL, {160, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23713, 329, 329, 23713, 16, 8, 0, 0, {1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output72.dat"}}, + {{nullopt, {0, 6145}, cyclic_prefix::NORMAL, {160, 0, 13, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41315, 551, 551, 41315, 0, 16, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output73.dat"}}, + {{nullopt, {0, 1294}, cyclic_prefix::NORMAL, {160, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {37494, 58, 58, 37494, 11, 1, 0, 0, {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output74.dat"}}, + {{nullopt, {0, 9276}, cyclic_prefix::NORMAL, {160, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {11832, 866, 866, 11832, 22, 2, 0, 0, {1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output75.dat"}}, + {{nullopt, {0, 5554}, cyclic_prefix::NORMAL, {160, 0, 12, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55685, 71, 71, 55685, 32, 4, 0, 0, {1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output76.dat"}}, + {{nullopt, {0, 1040}, cyclic_prefix::NORMAL, {160, 0, 3, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {24711, 930, 930, 24711, 8, 8, 0, 0, {1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output77.dat"}}, + {{nullopt, {0, 6179}, cyclic_prefix::NORMAL, {160, 0, 2, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {64063, 638, 638, 64063, 16, 16, 0, 0, {0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output78.dat"}}, + {{nullopt, {0, 1238}, cyclic_prefix::NORMAL, {160, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {55023, 46, 46, 55023, 7, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output79.dat"}}, + {{nullopt, {0, 9034}, cyclic_prefix::NORMAL, {160, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {29758, 459, 459, 29758, 28, 2, 0, 0, {1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output80.dat"}}, + {{nullopt, {0, 9256}, cyclic_prefix::NORMAL, {160, 0, 4, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {21044, 879, 879, 21044, 68, 4, 0, 0, {1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output81.dat"}}, + {{nullopt, {0, 8436}, cyclic_prefix::NORMAL, {160, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {29375, 821, 821, 29375, 8, 8, 0, 0, {1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output82.dat"}}, + {{nullopt, {0, 4304}, cyclic_prefix::NORMAL, {160, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {27445, 103, 103, 27445, 48, 16, 0, 0, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output83.dat"}}, + {{nullopt, {0, 7278}, cyclic_prefix::NORMAL, {216, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {49969, 671, 671, 49969, 8, 1, 0, 0, {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output84.dat"}}, + {{nullopt, {0, 1505}, cyclic_prefix::NORMAL, {216, 0, 8, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {7215, 99, 99, 7215, 20, 2, 0, 0, {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output85.dat"}}, + {{nullopt, {0, 2931}, cyclic_prefix::NORMAL, {216, 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}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {44454, 554, 554, 44454, 32, 4, 0, 0, {1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output86.dat"}}, + {{nullopt, {0, 132}, cyclic_prefix::NORMAL, {216, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43291, 46, 46, 43291, 16, 8, 0, 0, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output87.dat"}}, + {{nullopt, {0, 8113}, cyclic_prefix::NORMAL, {216, 0, 10, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {19653, 61, 61, 19653, 0, 16, 0, 0, {0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output88.dat"}}, {{nullopt, {0, 1512}, cyclic_prefix::NORMAL, {216, 0, 12, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {2422, 495, 495, 2422, 49, 1, 0, 0, {0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output89.dat"}}, - {{nullopt, {0, 1561}, cyclic_prefix::NORMAL, {216, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {58981, 944, 944, 58981, 66, 2, 0, 0, {1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output90.dat"}}, - {{nullopt, {0, 4104}, cyclic_prefix::NORMAL, {216, 0, 11, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41394, 846, 846, 41394, 16, 4, 0, 0, {0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output91.dat"}}, - {{nullopt, {0, 2981}, cyclic_prefix::NORMAL, {216, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15123, 499, 499, 15123, 0, 8, 0, 0, {0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output92.dat"}}, - {{nullopt, {0, 6667}, cyclic_prefix::NORMAL, {216, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {5567, 73, 73, 5567, 32, 16, 0, 0, {1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output93.dat"}}, - {{nullopt, {0, 1844}, cyclic_prefix::NORMAL, {216, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15498, 302, 302, 15498, 47, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output94.dat"}}, - {{nullopt, {0, 4493}, cyclic_prefix::NORMAL, {216, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43939, 539, 539, 43939, 48, 2, 0, 0, {0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output95.dat"}}, - {{nullopt, {0, 3756}, cyclic_prefix::NORMAL, {216, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {482, 0, 0, 482, 52, 4, 0, 0, {0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output96.dat"}}, - {{nullopt, {0, 8499}, cyclic_prefix::NORMAL, {216, 0, 7, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {16275, 109, 109, 16275, 48, 8, 0, 0, {1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output97.dat"}}, - {{nullopt, {0, 2808}, cyclic_prefix::NORMAL, {216, 0, 1, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23587, 438, 438, 23587, 32, 16, 0, 0, {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output98.dat"}}, - {{nullopt, {0, 4415}, cyclic_prefix::NORMAL, {270, 0, 4, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54336, 669, 669, 54336, 35, 1, 0, 0, {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output99.dat"}}, - {{nullopt, {0, 7742}, cyclic_prefix::NORMAL, {270, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22610, 351, 351, 22610, 18, 2, 0, 0, {1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output100.dat"}}, - {{nullopt, {0, 5194}, cyclic_prefix::NORMAL, {270, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17014, 462, 462, 17014, 8, 4, 0, 0, {0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output101.dat"}}, - {{nullopt, {0, 9260}, cyclic_prefix::NORMAL, {270, 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}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15770, 938, 938, 15770, 8, 8, 0, 0, {1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output102.dat"}}, - {{nullopt, {0, 8253}, cyclic_prefix::NORMAL, {270, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {18847, 388, 388, 18847, 16, 16, 0, 0, {0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output103.dat"}}, - {{nullopt, {0, 1784}, cyclic_prefix::NORMAL, {270, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {21455, 809, 809, 21455, 8, 1, 0, 0, {1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output104.dat"}}, - {{nullopt, {0, 3933}, cyclic_prefix::NORMAL, {270, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {65105, 977, 977, 65105, 72, 2, 0, 0, {1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output105.dat"}}, - {{nullopt, {0, 4648}, cyclic_prefix::NORMAL, {270, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {35745, 341, 341, 35745, 72, 4, 0, 0, {1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output106.dat"}}, + {{nullopt, {0, 1561}, cyclic_prefix::NORMAL, {216, 0, 7, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {58966, 944, 944, 58966, 26, 2, 0, 0, {1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output90.dat"}}, + {{nullopt, {0, 4104}, cyclic_prefix::NORMAL, {216, 0, 11, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {41383, 846, 846, 41383, 36, 4, 0, 0, {0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output91.dat"}}, + {{nullopt, {0, 2981}, cyclic_prefix::NORMAL, {216, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15119, 499, 499, 15119, 24, 8, 0, 0, {0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output92.dat"}}, + {{nullopt, {0, 6667}, cyclic_prefix::NORMAL, {216, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {5566, 73, 73, 5566, 32, 16, 0, 0, {1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output93.dat"}}, + {{nullopt, {0, 1844}, cyclic_prefix::NORMAL, {216, 0, 3, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15494, 302, 302, 15494, 6, 1, 0, 0, {0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output94.dat"}}, + {{nullopt, {0, 4493}, cyclic_prefix::NORMAL, {216, 0, 5, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {43928, 539, 539, 43928, 42, 2, 0, 0, {0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output95.dat"}}, + {{nullopt, {0, 3756}, cyclic_prefix::NORMAL, {216, 0, 2, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {481, 0, 0, 481, 20, 4, 0, 0, {0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output96.dat"}}, + {{nullopt, {0, 8499}, cyclic_prefix::NORMAL, {216, 0, 7, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {16271, 109, 109, 16271, 72, 8, 0, 0, {1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output97.dat"}}, + {{nullopt, {0, 2808}, cyclic_prefix::NORMAL, {216, 0, 1, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {23581, 438, 438, 23581, 32, 16, 0, 0, {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output98.dat"}}, + {{nullopt, {0, 4415}, cyclic_prefix::NORMAL, {270, 0, 4, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {54323, 669, 669, 54323, 16, 1, 0, 0, {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output99.dat"}}, + {{nullopt, {0, 7742}, cyclic_prefix::NORMAL, {270, 0, 5, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {22604, 351, 351, 22604, 4, 2, 0, 0, {1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output100.dat"}}, + {{nullopt, {0, 5194}, cyclic_prefix::NORMAL, {270, 0, 2, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {17010, 462, 462, 17010, 24, 4, 0, 0, {0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output101.dat"}}, + {{nullopt, {0, 9260}, cyclic_prefix::NORMAL, {270, 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}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {15767, 938, 938, 15767, 8, 8, 0, 0, {1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output102.dat"}}, + {{nullopt, {0, 8253}, cyclic_prefix::NORMAL, {270, 0, 11, 1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {18842, 388, 388, 18842, 0, 16, 0, 0, {0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output103.dat"}}, + {{nullopt, {0, 1784}, cyclic_prefix::NORMAL, {270, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {21450, 809, 809, 21450, 68, 1, 0, 0, {1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output104.dat"}}, + {{nullopt, {0, 3933}, cyclic_prefix::NORMAL, {270, 0, 4, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {65089, 977, 977, 65089, 20, 2, 0, 0, {1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output105.dat"}}, + {{nullopt, {0, 4648}, cyclic_prefix::NORMAL, {270, 0, 9, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {35736, 341, 341, 35736, 28, 4, 0, 0, {1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output106.dat"}}, {{nullopt, {0, 1168}, cyclic_prefix::NORMAL, {270, 0, 8, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {520, 970, 970, 520, 72, 8, 0, 0, {1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output107.dat"}}, - {{nullopt, {0, 4107}, cyclic_prefix::NORMAL, {270, 0, 6, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26313, 145, 145, 26313, 48, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output108.dat"}}, - {{nullopt, {0, 8334}, cyclic_prefix::NORMAL, {270, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20024, 679, 679, 20024, 59, 1, 0, 0, {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output109.dat"}}, - {{nullopt, {0, 2583}, cyclic_prefix::NORMAL, {270, 0, 9, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8874, 871, 871, 8874, 114, 2, 0, 0, {1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output110.dat"}}, - {{nullopt, {0, 2981}, cyclic_prefix::NORMAL, {270, 0, 8, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4022, 199, 199, 4022, 12, 4, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output111.dat"}}, - {{nullopt, {0, 7000}, cyclic_prefix::NORMAL, {270, 0, 10, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20907, 909, 909, 20907, 96, 8, 0, 0, {1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output112.dat"}}, - {{nullopt, {0, 5322}, cyclic_prefix::NORMAL, {270, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20179, 480, 480, 20179, 32, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output113.dat"}}, - // clang-format on + {{nullopt, {0, 4107}, cyclic_prefix::NORMAL, {270, 0, 6, 2, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {26306, 145, 145, 26306, 48, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output108.dat"}}, + {{nullopt, {0, 8334}, cyclic_prefix::NORMAL, {270, 0, 6, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20019, 679, 679, 20019, 57, 1, 0, 0, {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output109.dat"}}, + {{nullopt, {0, 2583}, cyclic_prefix::NORMAL, {270, 0, 9, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {8872, 871, 871, 8872, 54, 2, 0, 0, {1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1}, default_precoding}}, {"test_data/pdcch_processor_test_output110.dat"}}, + {{nullopt, {0, 2981}, cyclic_prefix::NORMAL, {270, 0, 8, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {4021, 199, 199, 4021, 60, 4, 0, 0, {0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output111.dat"}}, + {{nullopt, {0, 7000}, cyclic_prefix::NORMAL, {270, 0, 10, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20902, 909, 909, 20902, 48, 8, 0, 0, {1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output112.dat"}}, + {{nullopt, {0, 5322}, cyclic_prefix::NORMAL, {270, 0, 11, 3, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, pdcch_processor::cce_to_reg_mapping_type::NON_INTERLEAVED, 0, 0, 0}, {20174, 480, 480, 20174, 32, 16, 0, 0, {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0}, default_precoding}}, {"test_data/pdcch_processor_test_output113.dat"}}, +// clang-format on }; } // namespace srsran diff --git a/tests/unittests/phy/upper/channel_processors/pucch_processor_format1_vectortest.cpp b/tests/unittests/phy/upper/channel_processors/pucch_processor_format1_vectortest.cpp index 290708c511..558ced3d1d 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_format1_vectortest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_format1_vectortest.cpp @@ -93,9 +93,13 @@ class PucchProcessorFormat1Fixture : public ::testing::TestWithParam ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr) << "Cannot create port channel estimator factory."; std::shared_ptr estimator_factory = diff --git a/tests/unittests/phy/upper/channel_processors/pucch_processor_format2_vectortest.cpp b/tests/unittests/phy/upper/channel_processors/pucch_processor_format2_vectortest.cpp index 07f7da3b5f..1cab2c300b 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_format2_vectortest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_format2_vectortest.cpp @@ -89,9 +89,13 @@ class PucchProcessorF2Fixture : public ::testing::TestWithParam ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr) << "Cannot create port channel estimator factory."; std::shared_ptr estimator_factory = diff --git a/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format1_test.cpp b/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format1_test.cpp index 67b54afe56..9f7e0a9a6c 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format1_test.cpp +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format1_test.cpp @@ -220,9 +220,13 @@ class PucchProcessorFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr) << "Cannot create port channel estimator factory."; std::shared_ptr estimator_factory = diff --git a/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format2_test.cpp b/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format2_test.cpp index fd1e75d80d..5a42a991b9 100644 --- a/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format2_test.cpp +++ b/tests/unittests/phy/upper/channel_processors/pucch_processor_validator_format2_test.cpp @@ -276,9 +276,13 @@ class PucchProcessorFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr) << "Cannot create port channel estimator factory."; std::shared_ptr estimator_factory = diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_validator_test.cpp b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_validator_test.cpp index ea2d167853..9a97db6c3a 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_validator_test.cpp +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_validator_test.cpp @@ -202,9 +202,13 @@ class PuschProcessorFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create port channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr); // Create DM-RS for PUSCH channel estimator. diff --git a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_vectortest.cpp b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_vectortest.cpp index 41c8f0a2ff..9099712f24 100644 --- a/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_vectortest.cpp +++ b/tests/unittests/phy/upper/channel_processors/pusch/pusch_processor_vectortest.cpp @@ -229,9 +229,15 @@ class PuschProcessorFixture : public ::testing::TestWithParam ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + if (!ta_estimator_factory) { + return nullptr; + } + // Create port channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); if (!port_chan_estimator_factory) { return nullptr; } diff --git a/tests/unittests/phy/upper/signal_processors/CMakeLists.txt b/tests/unittests/phy/upper/signal_processors/CMakeLists.txt index 0c13126ead..23ee09d90b 100644 --- a/tests/unittests/phy/upper/signal_processors/CMakeLists.txt +++ b/tests/unittests/phy/upper/signal_processors/CMakeLists.txt @@ -32,6 +32,10 @@ target_link_libraries(sss_processor_test srsran_signal_processors srsvec srslog) add_test(sss_processor_test sss_processor_test) if (USE_PHY_TESTVECTORS) + add_executable(srs_estimator_vectortest srs/srs_estimator_vectortest.cpp) + target_link_libraries(srs_estimator_vectortest srsran_signal_processors srsvec srsran_sequence_generators srslog gtest gtest_main) + add_test_vector(srs_estimator_vectortest srs/srs_estimator_test_data.tar.gz "") + add_executable(dmrs_pbch_processor_test dmrs_pbch_processor_test.cpp) target_link_libraries(dmrs_pbch_processor_test srsran_signal_processors srsvec srsran_sequence_generators srslog) add_test_vector(dmrs_pbch_processor_test dmrs_pbch_processor_test_data.tar.gz "") diff --git a/tests/unittests/phy/upper/signal_processors/dmrs_pucch_processor_test.cpp b/tests/unittests/phy/upper/signal_processors/dmrs_pucch_processor_test.cpp index edbf1c9a15..eb3015e3a8 100644 --- a/tests/unittests/phy/upper/signal_processors/dmrs_pucch_processor_test.cpp +++ b/tests/unittests/phy/upper/signal_processors/dmrs_pucch_processor_test.cpp @@ -75,9 +75,13 @@ class DmrsPucchProcessorFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create channel estimator factory. std::shared_ptr port_chan_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_NE(port_chan_estimator_factory, nullptr) << "Cannot create port channel estimator factory."; // Create DM-RS for PUCCH estimator factory. diff --git a/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test.cpp b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test.cpp index cd083ee77b..1107656ee4 100644 --- a/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test.cpp +++ b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test.cpp @@ -92,9 +92,13 @@ class DmrsPuschEstimatorFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + // Create port estimator. std::shared_ptr port_estimator_factory = - create_port_channel_estimator_factory_sw(dft_factory); + create_port_channel_estimator_factory_sw(ta_estimator_factory); ASSERT_TRUE(port_estimator_factory); // Create estimator factory. diff --git a/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.h b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.h index fd9e7762ca..2a7d896d33 100644 --- a/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.h +++ b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 13-12-2023 (seed 0): +// This file was generated using the following MATLAB class on 05-03-2024 (seed 0): // + "srsPUSCHdmrsUnittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -45,53 +45,53 @@ struct test_case_t { static const std::vector dmrs_pusch_estimator_test_data = { // clang-format off {test_label::dmrs_creation, {{0, 0, 0, 0}, dmrs_type::TYPE1, 608, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output0.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates0.dat"}}, - {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE1, 451, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.77076, 2.2955, {"test_data/dmrs_pusch_estimator_test_output1.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates1.dat"}}, + {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE1, 451, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.76926, 2.3038, {"test_data/dmrs_pusch_estimator_test_output1.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates1.dat"}}, {test_label::dmrs_creation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 122, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output2.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates2.dat"}}, - {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 447, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.67883, 1.5996, {"test_data/dmrs_pusch_estimator_test_output3.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates3.dat"}}, + {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 447, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.67686, 1.6064, {"test_data/dmrs_pusch_estimator_test_output3.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates3.dat"}}, {test_label::dmrs_creation, {{0, 0, 1, 0}, dmrs_type::TYPE1, 871, 1, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output4.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates4.dat"}}, - {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE1, 771, 1, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.635, 0.13727, {"test_data/dmrs_pusch_estimator_test_output5.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates5.dat"}}, + {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE1, 771, 1, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.635, 0.13556, {"test_data/dmrs_pusch_estimator_test_output5.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates5.dat"}}, {test_label::dmrs_creation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 98, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output6.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates6.dat"}}, - {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE2, 745, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1835, 0.15871, {"test_data/dmrs_pusch_estimator_test_output7.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates7.dat"}}, + {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE2, 745, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1829, 0.15914, {"test_data/dmrs_pusch_estimator_test_output7.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates7.dat"}}, {test_label::dmrs_creation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 173, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output8.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates8.dat"}}, - {test_label::ch_estimation, {{0, 0, 8, 0}, dmrs_type::TYPE1, 332, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.92249, 3.346, {"test_data/dmrs_pusch_estimator_test_output9.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates9.dat"}}, + {test_label::ch_estimation, {{0, 0, 8, 0}, dmrs_type::TYPE1, 332, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.92276, 3.3482, {"test_data/dmrs_pusch_estimator_test_output9.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates9.dat"}}, {test_label::dmrs_creation, {{0, 0, 0, 0}, dmrs_type::TYPE2, 634, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output10.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates10.dat"}}, - {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 555, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.7592, 0.1798, {"test_data/dmrs_pusch_estimator_test_output11.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates11.dat"}}, + {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 555, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.76, 0.17846, {"test_data/dmrs_pusch_estimator_test_output11.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates11.dat"}}, {test_label::dmrs_creation, {{0, 0, 4, 0}, dmrs_type::TYPE1, 970, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output12.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates12.dat"}}, - {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE1, 395, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.97388, 3.3267, {"test_data/dmrs_pusch_estimator_test_output13.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates13.dat"}}, + {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE1, 395, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.97218, 3.3313, {"test_data/dmrs_pusch_estimator_test_output13.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates13.dat"}}, {test_label::dmrs_creation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 931, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output14.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates14.dat"}}, - {test_label::ch_estimation, {{0, 0, 7, 0}, dmrs_type::TYPE2, 698, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.2157, 1.9916, {"test_data/dmrs_pusch_estimator_test_output15.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates15.dat"}}, + {test_label::ch_estimation, {{0, 0, 7, 0}, dmrs_type::TYPE2, 698, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.2179, 1.9908, {"test_data/dmrs_pusch_estimator_test_output15.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates15.dat"}}, {test_label::dmrs_creation, {{0, 0, 6, 0}, dmrs_type::TYPE1, 293, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0}, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output16.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates16.dat"}}, - {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE1, 243, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0138, 0.066152, {"test_data/dmrs_pusch_estimator_test_output17.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates17.dat"}}, + {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE1, 243, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0138, 0.066158, {"test_data/dmrs_pusch_estimator_test_output17.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates17.dat"}}, {test_label::dmrs_creation, {{0, 0, 4, 0}, dmrs_type::TYPE2, 280, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output18.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates18.dat"}}, - {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE2, 691, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4473, 1.1245, {"test_data/dmrs_pusch_estimator_test_output19.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates19.dat"}}, + {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE2, 691, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4472, 1.1267, {"test_data/dmrs_pusch_estimator_test_output19.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates19.dat"}}, {test_label::dmrs_creation, {{0, 0, 8, 0}, dmrs_type::TYPE1, 31, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output20.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates20.dat"}}, - {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 642, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.8475, 0.047748, {"test_data/dmrs_pusch_estimator_test_output21.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates21.dat"}}, + {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 642, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.8526, 0.046904, {"test_data/dmrs_pusch_estimator_test_output21.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates21.dat"}}, {test_label::dmrs_creation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 360, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output22.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates22.dat"}}, - {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE2, 407, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0556, 0.18957, {"test_data/dmrs_pusch_estimator_test_output23.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates23.dat"}}, + {test_label::ch_estimation, {{0, 0, 3, 0}, dmrs_type::TYPE2, 407, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0563, 0.19081, {"test_data/dmrs_pusch_estimator_test_output23.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates23.dat"}}, {test_label::dmrs_creation, {{0, 0, 0, 0}, dmrs_type::TYPE1, 39, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output24.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates24.dat"}}, - {test_label::ch_estimation, {{0, 0, 0, 0}, dmrs_type::TYPE1, 21, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1719, 0.17326, {"test_data/dmrs_pusch_estimator_test_output25.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates25.dat"}}, + {test_label::ch_estimation, {{0, 0, 0, 0}, dmrs_type::TYPE1, 21, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1733, 0.17352, {"test_data/dmrs_pusch_estimator_test_output25.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates25.dat"}}, {test_label::dmrs_creation, {{0, 0, 7, 0}, dmrs_type::TYPE2, 459, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output26.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates26.dat"}}, - {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 959, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.85866, 0.33458, {"test_data/dmrs_pusch_estimator_test_output27.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates27.dat"}}, + {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 959, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.86049, 0.33325, {"test_data/dmrs_pusch_estimator_test_output27.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates27.dat"}}, {test_label::dmrs_creation, {{0, 0, 6, 0}, dmrs_type::TYPE1, 859, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output28.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates28.dat"}}, - {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 260, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.9659, 0.089262, {"test_data/dmrs_pusch_estimator_test_output29.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates29.dat"}}, + {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 260, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.96697, 0.089703, {"test_data/dmrs_pusch_estimator_test_output29.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates29.dat"}}, {test_label::dmrs_creation, {{0, 0, 2, 0}, dmrs_type::TYPE2, 302, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output30.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates30.dat"}}, - {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 652, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0564, 0.23449, {"test_data/dmrs_pusch_estimator_test_output31.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates31.dat"}}, + {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 652, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0537, 0.24, {"test_data/dmrs_pusch_estimator_test_output31.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates31.dat"}}, {test_label::dmrs_creation, {{0, 0, 4, 0}, dmrs_type::TYPE1, 174, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output32.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates32.dat"}}, - {test_label::ch_estimation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 544, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 3.523, 0.10102, {"test_data/dmrs_pusch_estimator_test_output33.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates33.dat"}}, + {test_label::ch_estimation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 544, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 3.5258, 0.098369, {"test_data/dmrs_pusch_estimator_test_output33.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates33.dat"}}, {test_label::dmrs_creation, {{0, 0, 2, 0}, dmrs_type::TYPE2, 33, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output34.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates34.dat"}}, - {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 757, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.6013, 0.16132, {"test_data/dmrs_pusch_estimator_test_output35.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates35.dat"}}, + {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 757, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.6035, 0.16374, {"test_data/dmrs_pusch_estimator_test_output35.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates35.dat"}}, {test_label::dmrs_creation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 772, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output36.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates36.dat"}}, - {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE1, 645, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 6.2912, 0.058265, {"test_data/dmrs_pusch_estimator_test_output37.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates37.dat"}}, + {test_label::ch_estimation, {{0, 0, 5, 0}, dmrs_type::TYPE1, 645, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 6.2964, 0.057175, {"test_data/dmrs_pusch_estimator_test_output37.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates37.dat"}}, {test_label::dmrs_creation, {{0, 0, 3, 0}, dmrs_type::TYPE2, 151, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output38.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates38.dat"}}, - {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 795, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.2852, 0.082309, {"test_data/dmrs_pusch_estimator_test_output39.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates39.dat"}}, + {test_label::ch_estimation, {{0, 0, 6, 0}, dmrs_type::TYPE2, 795, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.291, 0.080376, {"test_data/dmrs_pusch_estimator_test_output39.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates39.dat"}}, {test_label::dmrs_creation, {{0, 0, 8, 0}, dmrs_type::TYPE1, 677, 0, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output40.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates40.dat"}}, - {test_label::ch_estimation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 342, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.222, 0.065595, {"test_data/dmrs_pusch_estimator_test_output41.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates41.dat"}}, + {test_label::ch_estimation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 342, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.221, 0.065508, {"test_data/dmrs_pusch_estimator_test_output41.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates41.dat"}}, {test_label::dmrs_creation, {{0, 0, 9, 0}, dmrs_type::TYPE2, 743, 1, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output42.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates42.dat"}}, - {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 91, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.7131, 0.095908, {"test_data/dmrs_pusch_estimator_test_output43.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates43.dat"}}, + {test_label::ch_estimation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 91, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.7124, 0.10146, {"test_data/dmrs_pusch_estimator_test_output43.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates43.dat"}}, {test_label::dmrs_creation, {{0, 0, 3, 0}, dmrs_type::TYPE1, 704, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output44.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates44.dat"}}, - {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 599, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 12.6343, 0.048714, {"test_data/dmrs_pusch_estimator_test_output45.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates45.dat"}}, + {test_label::ch_estimation, {{0, 0, 9, 0}, dmrs_type::TYPE1, 599, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 12.6419, 0.045505, {"test_data/dmrs_pusch_estimator_test_output45.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates45.dat"}}, {test_label::dmrs_creation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 722, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output46.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates46.dat"}}, - {test_label::ch_estimation, {{0, 0, 7, 0}, dmrs_type::TYPE2, 864, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.96938, 0.40997, {"test_data/dmrs_pusch_estimator_test_output47.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates47.dat"}}, + {test_label::ch_estimation, {{0, 0, 7, 0}, dmrs_type::TYPE2, 864, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.96997, 0.41103, {"test_data/dmrs_pusch_estimator_test_output47.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates47.dat"}}, {test_label::dmrs_creation, {{0, 0, 8, 0}, dmrs_type::TYPE1, 300, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output48.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates48.dat"}}, {test_label::dmrs_creation, {{0, 0, 1, 0}, dmrs_type::TYPE2, 169, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output49.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates49.dat"}}, {test_label::dmrs_creation, {{0, 0, 2, 0}, dmrs_type::TYPE1, 998, 1, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output50.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates50.dat"}}, @@ -141,53 +141,53 @@ static const std::vector dmrs_pusch_estimator_test_data = { {test_label::dmrs_creation, {{0, 0, 7, 0}, dmrs_type::TYPE1, 719, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 4, {{0, 1, 2, 3}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output94.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates94.dat"}}, {test_label::dmrs_creation, {{0, 0, 5, 0}, dmrs_type::TYPE2, 833, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 4, {{0, 1, 2, 3}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output95.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates95.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 1}, dmrs_type::TYPE1, 751, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output96.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates96.dat"}}, - {test_label::ch_estimation, {{1, 0, 9, 0}, dmrs_type::TYPE1, 731, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.0699, 0.1884, {"test_data/dmrs_pusch_estimator_test_output97.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates97.dat"}}, + {test_label::ch_estimation, {{1, 0, 9, 0}, dmrs_type::TYPE1, 731, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.0689, 0.18748, {"test_data/dmrs_pusch_estimator_test_output97.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates97.dat"}}, {test_label::dmrs_creation, {{1, 0, 1, 1}, dmrs_type::TYPE2, 788, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output98.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates98.dat"}}, - {test_label::ch_estimation, {{1, 0, 8, 0}, dmrs_type::TYPE2, 839, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.80316, 0.50779, {"test_data/dmrs_pusch_estimator_test_output99.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates99.dat"}}, + {test_label::ch_estimation, {{1, 0, 8, 0}, dmrs_type::TYPE2, 839, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.80322, 0.50728, {"test_data/dmrs_pusch_estimator_test_output99.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates99.dat"}}, {test_label::dmrs_creation, {{1, 0, 2, 0}, dmrs_type::TYPE1, 418, 1, 1.4142, cyclic_prefix::NORMAL, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output100.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates100.dat"}}, - {test_label::ch_estimation, {{1, 0, 3, 0}, dmrs_type::TYPE1, 672, 1, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.4266, 0.093311, {"test_data/dmrs_pusch_estimator_test_output101.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates101.dat"}}, + {test_label::ch_estimation, {{1, 0, 3, 0}, dmrs_type::TYPE1, 672, 1, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.4282, 0.093163, {"test_data/dmrs_pusch_estimator_test_output101.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates101.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 517, 1, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output102.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates102.dat"}}, - {test_label::ch_estimation, {{1, 0, 2, 0}, dmrs_type::TYPE2, 943, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4904, 0.15686, {"test_data/dmrs_pusch_estimator_test_output103.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates103.dat"}}, + {test_label::ch_estimation, {{1, 0, 2, 0}, dmrs_type::TYPE2, 943, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4978, 0.15404, {"test_data/dmrs_pusch_estimator_test_output103.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates103.dat"}}, {test_label::dmrs_creation, {{1, 0, 1, 1}, dmrs_type::TYPE1, 335, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output104.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates104.dat"}}, - {test_label::ch_estimation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 120, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.91794, 2.8218, {"test_data/dmrs_pusch_estimator_test_output105.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates105.dat"}}, + {test_label::ch_estimation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 120, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.91719, 2.8256, {"test_data/dmrs_pusch_estimator_test_output105.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates105.dat"}}, {test_label::dmrs_creation, {{1, 0, 7, 0}, dmrs_type::TYPE2, 270, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output106.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates106.dat"}}, - {test_label::ch_estimation, {{1, 0, 1, 0}, dmrs_type::TYPE2, 389, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1915, 1.0792, {"test_data/dmrs_pusch_estimator_test_output107.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates107.dat"}}, + {test_label::ch_estimation, {{1, 0, 1, 0}, dmrs_type::TYPE2, 389, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.1917, 1.0793, {"test_data/dmrs_pusch_estimator_test_output107.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates107.dat"}}, {test_label::dmrs_creation, {{1, 0, 1, 1}, dmrs_type::TYPE1, 876, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output108.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates108.dat"}}, - {test_label::ch_estimation, {{1, 0, 8, 0}, dmrs_type::TYPE1, 766, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 8.3287, 0.055219, {"test_data/dmrs_pusch_estimator_test_output109.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates109.dat"}}, + {test_label::ch_estimation, {{1, 0, 8, 0}, dmrs_type::TYPE1, 766, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 8.3466, 0.050719, {"test_data/dmrs_pusch_estimator_test_output109.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates109.dat"}}, {test_label::dmrs_creation, {{1, 0, 7, 1}, dmrs_type::TYPE2, 518, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output110.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates110.dat"}}, - {test_label::ch_estimation, {{1, 0, 0, 1}, dmrs_type::TYPE2, 850, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.8247, 0.79507, {"test_data/dmrs_pusch_estimator_test_output111.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates111.dat"}}, + {test_label::ch_estimation, {{1, 0, 0, 1}, dmrs_type::TYPE2, 850, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.8262, 0.79928, {"test_data/dmrs_pusch_estimator_test_output111.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates111.dat"}}, {test_label::dmrs_creation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 803, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output112.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates112.dat"}}, - {test_label::ch_estimation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 227, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.6562, 0.10016, {"test_data/dmrs_pusch_estimator_test_output113.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates113.dat"}}, + {test_label::ch_estimation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 227, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.6571, 0.098255, {"test_data/dmrs_pusch_estimator_test_output113.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates113.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 0}, dmrs_type::TYPE2, 159, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output114.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates114.dat"}}, - {test_label::ch_estimation, {{1, 0, 6, 0}, dmrs_type::TYPE2, 592, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.146, 0.11122, {"test_data/dmrs_pusch_estimator_test_output115.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates115.dat"}}, + {test_label::ch_estimation, {{1, 0, 6, 0}, dmrs_type::TYPE2, 592, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.1488, 0.10768, {"test_data/dmrs_pusch_estimator_test_output115.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates115.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 0}, dmrs_type::TYPE1, 840, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output116.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates116.dat"}}, - {test_label::ch_estimation, {{1, 0, 4, 0}, dmrs_type::TYPE1, 235, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.8506, 0.070981, {"test_data/dmrs_pusch_estimator_test_output117.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates117.dat"}}, + {test_label::ch_estimation, {{1, 0, 4, 0}, dmrs_type::TYPE1, 235, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.8555, 0.070439, {"test_data/dmrs_pusch_estimator_test_output117.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates117.dat"}}, {test_label::dmrs_creation, {{1, 0, 8, 0}, dmrs_type::TYPE2, 804, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output118.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates118.dat"}}, - {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 709, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.715, 0.08957, {"test_data/dmrs_pusch_estimator_test_output119.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates119.dat"}}, + {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 709, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 2.7138, 0.09246, {"test_data/dmrs_pusch_estimator_test_output119.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates119.dat"}}, {test_label::dmrs_creation, {{1, 0, 3, 1}, dmrs_type::TYPE1, 54, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output120.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates120.dat"}}, - {test_label::ch_estimation, {{1, 0, 8, 1}, dmrs_type::TYPE1, 505, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.6282, 0.19485, {"test_data/dmrs_pusch_estimator_test_output121.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates121.dat"}}, + {test_label::ch_estimation, {{1, 0, 8, 1}, dmrs_type::TYPE1, 505, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 4.634, 0.19385, {"test_data/dmrs_pusch_estimator_test_output121.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates121.dat"}}, {test_label::dmrs_creation, {{1, 0, 0, 0}, dmrs_type::TYPE2, 487, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output122.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates122.dat"}}, - {test_label::ch_estimation, {{1, 0, 3, 1}, dmrs_type::TYPE2, 962, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.67526, 0.97983, {"test_data/dmrs_pusch_estimator_test_output123.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates123.dat"}}, + {test_label::ch_estimation, {{1, 0, 3, 1}, dmrs_type::TYPE2, 962, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.678, 0.98794, {"test_data/dmrs_pusch_estimator_test_output123.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates123.dat"}}, {test_label::dmrs_creation, {{1, 0, 0, 1}, dmrs_type::TYPE1, 375, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output124.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates124.dat"}}, - {test_label::ch_estimation, {{1, 0, 1, 1}, dmrs_type::TYPE1, 635, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.94854, 0.085867, {"test_data/dmrs_pusch_estimator_test_output125.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates125.dat"}}, + {test_label::ch_estimation, {{1, 0, 1, 1}, dmrs_type::TYPE1, 635, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.94873, 0.086209, {"test_data/dmrs_pusch_estimator_test_output125.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates125.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 0}, dmrs_type::TYPE2, 648, 1, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output126.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates126.dat"}}, - {test_label::ch_estimation, {{1, 0, 1, 1}, dmrs_type::TYPE2, 147, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4724, 0.16197, {"test_data/dmrs_pusch_estimator_test_output127.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates127.dat"}}, + {test_label::ch_estimation, {{1, 0, 1, 1}, dmrs_type::TYPE2, 147, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4729, 0.16011, {"test_data/dmrs_pusch_estimator_test_output127.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates127.dat"}}, {test_label::dmrs_creation, {{1, 0, 3, 0}, dmrs_type::TYPE1, 660, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output128.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates128.dat"}}, - {test_label::ch_estimation, {{1, 0, 3, 1}, dmrs_type::TYPE1, 930, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 6.693, 0.12096, {"test_data/dmrs_pusch_estimator_test_output129.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates129.dat"}}, + {test_label::ch_estimation, {{1, 0, 3, 1}, dmrs_type::TYPE1, 930, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 6.6925, 0.11878, {"test_data/dmrs_pusch_estimator_test_output129.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates129.dat"}}, {test_label::dmrs_creation, {{1, 0, 6, 0}, dmrs_type::TYPE2, 868, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output130.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates130.dat"}}, - {test_label::ch_estimation, {{1, 0, 5, 0}, dmrs_type::TYPE2, 878, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4063, 0.53599, {"test_data/dmrs_pusch_estimator_test_output131.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates131.dat"}}, + {test_label::ch_estimation, {{1, 0, 5, 0}, dmrs_type::TYPE2, 878, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.4066, 0.53761, {"test_data/dmrs_pusch_estimator_test_output131.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates131.dat"}}, {test_label::dmrs_creation, {{1, 0, 8, 1}, dmrs_type::TYPE1, 2, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output132.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates132.dat"}}, - {test_label::ch_estimation, {{1, 0, 3, 0}, dmrs_type::TYPE1, 789, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 11.5183, 0.12152, {"test_data/dmrs_pusch_estimator_test_output133.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates133.dat"}}, + {test_label::ch_estimation, {{1, 0, 3, 0}, dmrs_type::TYPE1, 789, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 11.533, 0.12049, {"test_data/dmrs_pusch_estimator_test_output133.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates133.dat"}}, {test_label::dmrs_creation, {{1, 0, 2, 1}, dmrs_type::TYPE2, 357, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output134.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates134.dat"}}, - {test_label::ch_estimation, {{1, 0, 5, 0}, dmrs_type::TYPE2, 95, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.9564, 0.081235, {"test_data/dmrs_pusch_estimator_test_output135.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates135.dat"}}, + {test_label::ch_estimation, {{1, 0, 5, 0}, dmrs_type::TYPE2, 95, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0.95646, 0.081691, {"test_data/dmrs_pusch_estimator_test_output135.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates135.dat"}}, {test_label::dmrs_creation, {{1, 0, 0, 0}, dmrs_type::TYPE1, 869, 1, 1.4142, cyclic_prefix::NORMAL, {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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output136.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates136.dat"}}, - {test_label::ch_estimation, {{1, 0, 2, 0}, dmrs_type::TYPE1, 165, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 8.6207, 0.071094, {"test_data/dmrs_pusch_estimator_test_output137.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates137.dat"}}, + {test_label::ch_estimation, {{1, 0, 2, 0}, dmrs_type::TYPE1, 165, 0, 1.4142, cyclic_prefix::NORMAL, {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 8.6283, 0.069842, {"test_data/dmrs_pusch_estimator_test_output137.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates137.dat"}}, {test_label::dmrs_creation, {{1, 0, 7, 1}, dmrs_type::TYPE2, 801, 1, 1.4142, cyclic_prefix::NORMAL, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output138.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates138.dat"}}, - {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 319, 0, 1.4142, cyclic_prefix::NORMAL, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.2292, 0.38855, {"test_data/dmrs_pusch_estimator_test_output139.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates139.dat"}}, + {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 319, 0, 1.4142, cyclic_prefix::NORMAL, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.228, 0.38726, {"test_data/dmrs_pusch_estimator_test_output139.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates139.dat"}}, {test_label::dmrs_creation, {{1, 0, 8, 1}, dmrs_type::TYPE1, 690, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output140.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates140.dat"}}, - {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE1, 738, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.329, 0.046271, {"test_data/dmrs_pusch_estimator_test_output141.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates141.dat"}}, + {test_label::ch_estimation, {{1, 0, 9, 1}, dmrs_type::TYPE1, 738, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.3293, 0.046092, {"test_data/dmrs_pusch_estimator_test_output141.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates141.dat"}}, {test_label::dmrs_creation, {{1, 0, 1, 0}, dmrs_type::TYPE2, 879, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output142.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates142.dat"}}, - {test_label::ch_estimation, {{1, 0, 9, 0}, dmrs_type::TYPE2, 135, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.006, 0.32467, {"test_data/dmrs_pusch_estimator_test_output143.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates143.dat"}}, + {test_label::ch_estimation, {{1, 0, 9, 0}, dmrs_type::TYPE2, 135, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 1, {0}}, 1.0067, 0.32662, {"test_data/dmrs_pusch_estimator_test_output143.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates143.dat"}}, {test_label::dmrs_creation, {{1, 0, 6, 1}, dmrs_type::TYPE1, 593, 0, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output144.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates144.dat"}}, {test_label::dmrs_creation, {{1, 0, 9, 1}, dmrs_type::TYPE2, 268, 1, 1.4142, cyclic_prefix::NORMAL, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output145.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates145.dat"}}, {test_label::dmrs_creation, {{1, 0, 3, 1}, dmrs_type::TYPE1, 67, 0, 1.4142, cyclic_prefix::NORMAL, {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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 1, 13, 2, {{0, 1}}}, 0, 0, {"test_data/dmrs_pusch_estimator_test_output146.dat"}, {"test_data/dmrs_pusch_estimator_ch_estimates146.dat"}}, diff --git a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test.cpp b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test.cpp index 68be2bfa29..bb5d47ebbd 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test.cpp +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test.cpp @@ -67,7 +67,11 @@ class ChannelEstFixture : public ::testing::TestWithParam } ASSERT_NE(dft_factory, nullptr) << "Cannot create DFT factory."; - ch_est_factory = create_port_channel_estimator_factory_sw(std::move(dft_factory)); + std::shared_ptr ta_estimator_factory = + create_time_alignment_estimator_dft_factory(dft_factory); + ASSERT_NE(ta_estimator_factory, nullptr) << "Cannot create TA estimator factory."; + + ch_est_factory = create_port_channel_estimator_factory_sw(std::move(ta_estimator_factory)); ASSERT_NE(ch_est_factory, nullptr); } } 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 4f8527cf84..25d9875fcc 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 22-11-2023 (seed 0): +// This file was generated using the following MATLAB class on 05-03-2024 (seed 0): // + "srsChEstimatorUnittest.m" #include "../../support/resource_grid_test_doubles.h" @@ -47,20 +47,20 @@ 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}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0144, 2.0226, 20, 20.3186, 0.009382, 0, {"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}, {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}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 1.9737, 1.98, 20, 20.2693, 0.0092975, 0.12207, {"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, 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}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0181, 1.9989, 20, 20.0758, 0.0099393, 0.7487, {"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, 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, 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}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0161, 2.0086, 20, 19.9898, 0.010128, 0.53711, {"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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0114, 2.0016, 20, 20.1563, 0.0097246, 0.53711, {"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, 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}, {}, nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.98151, 1.0151, 20, 18.1549, 0.015011, 0.42318, {"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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.89825, 0.96164, 20, 14.8101, 0.029675, 0.6429, {"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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.9395, 0.99641, 20, 15.6328, 0.025681, 0.63477, {"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::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, 1, 0}, {0, 0, 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}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.95886, 1.01, 20, 16.0416, 0.023856, 0.54525, {"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::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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 0.99674, 1.0529, 20, 16.398, 0.022844, 0.7487, {"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::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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 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}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0368, 1.0681, 20, 21.4519, 0.0074216, 0.38249, {"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::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, 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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0089, 0.98303, 20, 22.417, 0.005783, 0.53711, {"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::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, 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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0093, 1.01, 20, 20.815, 0.0083664, 0.21159, {"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::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}, {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}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.1361, 1.0308, 20, 20.2591, 0.010703, 0.96029, {"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::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}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0142, 2.0226, 20, 20.3665, 0.0092779, 0, {"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}, {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}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 1.974, 1.98, 20, 20.4101, 0.009002, 0.12207, {"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, 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}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.024, 1.9989, 20, 20.5577, 0.0089217, 0.7487, {"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, 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, 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}, 7, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0196, 2.0086, 20, 20.2465, 0.0095636, 0.53711, {"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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {}, nullopt, {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}}}, {0}, 1.4125}, 52, 2.0127, 2.0016, 20, 20.2558, 0.0095102, 0.53711, {"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, 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}, {}, nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.97, 1.0151, 20, 20.655, 0.008342, 0.66732, {"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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}, 10, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.87208, 0.96164, 20, 18.8145, 0.011458, 1.0498, {"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, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {}, nullopt, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.91172, 0.99641, 20, 19.4351, 0.010384, 1.0254, {"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::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, 1, 0}, {0, 0, 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}, 7, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, {0}, 1}, 52, 0.9395, 1.01, 20, 18.6912, 0.012699, 0.86263, {"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::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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 0.98011, 1.0529, 20, 18.8057, 0.012903, 1.0417, {"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::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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 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}, 1, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0321, 1.0681, 20, 22.8276, 0.0053822, 0.52083, {"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::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, 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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0258, 0.98303, 20, 23.3508, 0.0047421, 0.53711, {"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::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, 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}, {}, nullopt, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.0101, 1.01, 20, 20.8373, 0.0083301, 0.21159, {"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::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}, {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}, 6, {0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0}}}, {0}, 1}, 52, 1.1507, 1.0308, 20, 20.6124, 0.0099939, 0.96029, {"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"}}, // clang-format on }; diff --git a/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.h b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.h new file mode 100644 index 0000000000..083b30d8c9 --- /dev/null +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.h @@ -0,0 +1,121 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#pragma once + +// This file was generated using the following MATLAB class on 08-03-2024 (seed 0): +// + "srsSRSEstimatorUnittest.m" + +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_result.h" +#include "srsran/ran/phy_time_unit.h" + +namespace srsran { + +struct test_context { + srs_estimator_configuration config; + srs_estimator_result result; +}; + +struct test_case_t { + test_context context; + file_vector rx_grid; +}; + +static const std::vector srs_estimator_test_data = { + // clang-format off + {{{{0, 130, 8, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 12, 17, 647, 2, srs_resource_configuration::comb_size_enum(2), 1, 1, 66, 1, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.512938, -0.044587), cf_t(0.505400, -0.144933)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input0.dat"}}, + {{{{0, 811, 4, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 13, 54, 671, 3, srs_resource_configuration::comb_size_enum(4), 2, 8, 26, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.207799, -0.556693), cf_t(0.628191, -0.811101)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input1.dat"}}, + {{{{0, 99, 2, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 11, 15, 711, 3, srs_resource_configuration::comb_size_enum(2), 0, 3, 41, 8, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.125423, -0.138631), cf_t(0.139874, 1.122673), cf_t(1.003604, 0.206181), cf_t(-0.568843, 0.492588)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input2.dat"}}, + {{{{0, 581, 7, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 1, 49, 55, 3, srs_resource_configuration::comb_size_enum(4), 0, 5, 0, 5, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.310396, -1.269030), cf_t(0.070776, -0.385040), cf_t(0.594235, -0.627934), cf_t(0.214622, -0.424495)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input3.dat"}}, + {{{{0, 766, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 6, 9, 85, 0, srs_resource_configuration::comb_size_enum(2), 1, 6, 9, 2, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.797257, 0.247614), cf_t(-0.185259, -1.237587), cf_t(-0.692403, -0.817699), cf_t(0.681813, 0.367738), cf_t(-0.211472, 0.016186), cf_t(-0.201986, -0.587865), cf_t(-0.377282, -1.416077), cf_t(-0.014162, -0.024587)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input4.dat"}}, + {{{{0, 378, 3, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 1, 15, 798, 1, srs_resource_configuration::comb_size_enum(4), 0, 11, 65, 4, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.217460, -0.888917), cf_t(0.559616, -0.941869), cf_t(0.235828, 0.276729), cf_t(0.129888, -0.336691), cf_t(-0.611978, -0.124828), cf_t(-1.647465, -1.024667), cf_t(0.319386, -0.092125), cf_t(0.609541, -0.962863)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input5.dat"}}, + {{{{0, 377, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 8, 59, 798, 3, srs_resource_configuration::comb_size_enum(2), 0, 5, 20, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.016296, 0.036268), cf_t(0.584115, 1.079736)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input6.dat"}}, + {{{{0, 831, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 6, 56, 359, 2, srs_resource_configuration::comb_size_enum(4), 2, 2, 20, 10, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.103276, -0.376189), cf_t(1.189427, -0.619234)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input7.dat"}}, + {{{{0, 233, 2, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 5, 27, 318, 0, srs_resource_configuration::comb_size_enum(2), 1, 5, 7, 10, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.314399, -0.110267), cf_t(0.313547, 0.277111), cf_t(0.195210, -0.184671), cf_t(-0.884364, -0.670310)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input8.dat"}}, + {{{{0, 434, 2, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 6, 51, 87, 0, srs_resource_configuration::comb_size_enum(4), 3, 5, 39, 2, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-1.106662, -0.059778), cf_t(0.029256, -0.519136), cf_t(1.134161, 0.069542), cf_t(-0.021789, 0.164294)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input9.dat"}}, + {{{{0, 376, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 12, 58, 38, 3, srs_resource_configuration::comb_size_enum(2), 0, 4, 46, 9, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-1.181010, 0.333496), cf_t(0.461285, 0.231266), cf_t(-0.460261, 0.181766), cf_t(0.653951, 0.000035), cf_t(-0.857612, 0.046803), cf_t(0.765537, 0.711404), cf_t(-0.667776, -0.934646), cf_t(-0.038834, 0.644264)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input10.dat"}}, + {{{{0, 880, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 10, 15, 590, 3, srs_resource_configuration::comb_size_enum(4), 0, 2, 66, 2, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.609325, 0.000822), cf_t(0.410951, -1.550286), cf_t(-0.670677, 0.290968), cf_t(-0.488723, 0.317758), cf_t(-0.050089, -1.758068), cf_t(-1.639979, 0.056522), cf_t(0.478696, 0.606508), cf_t(0.071159, 0.584120)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input11.dat"}}, + {{{{0, 464, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 4, 33, 845, 1, srs_resource_configuration::comb_size_enum(2), 1, 3, 29, 4, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-1.507619, 0.809893), cf_t(-0.444834, -0.851250)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input12.dat"}}, + {{{{0, 501, 3, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 3, 3, 974, 2, srs_resource_configuration::comb_size_enum(4), 1, 6, 64, 10, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.193073, 1.114613), cf_t(-0.340074, 0.231586)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input13.dat"}}, + {{{{0, 714, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 7, 12, 182, 1, srs_resource_configuration::comb_size_enum(2), 0, 7, 15, 4, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.066638, 0.237739), cf_t(0.247532, -1.298148), cf_t(-0.639687, -0.203828), cf_t(0.732546, 1.714353)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input14.dat"}}, + {{{{0, 598, 7, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 1, 52, 928, 1, srs_resource_configuration::comb_size_enum(4), 2, 5, 21, 9, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.725303, -0.642580), cf_t(0.429638, -0.083296), cf_t(-0.148420, -1.201278), cf_t(0.494381, 0.190670)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input15.dat"}}, + {{{{0, 70, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 3, 26, 543, 3, srs_resource_configuration::comb_size_enum(2), 1, 6, 22, 7, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-1.047507, 0.109947), cf_t(-0.382394, -0.218243), cf_t(-0.127802, 0.032415), cf_t(0.077299, 1.282703), cf_t(0.578803, -0.206891), cf_t(-0.775409, -0.348611), cf_t(-0.045101, 0.432279), cf_t(0.220634, 1.275970)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input16.dat"}}, + {{{{0, 296, 2, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 7, 16, 711, 0, srs_resource_configuration::comb_size_enum(4), 2, 4, 53, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.385755, -0.743616), cf_t(1.072163, -0.023028), cf_t(0.416792, -0.044400), cf_t(0.433111, -0.038810), cf_t(0.281052, -0.531670), cf_t(1.156826, -0.300562), cf_t(-1.429741, -0.694472), cf_t(-0.791063, -0.442917)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input17.dat"}}, + {{{{0, 756, 6, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 3, 48, 939, 0, srs_resource_configuration::comb_size_enum(2), 0, 6, 46, 2, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.212476, -0.263801), cf_t(0.576637, 0.564898), cf_t(0.084998, 0.403933), cf_t(0.291891, -0.697887)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input18.dat"}}, + {{{{0, 122, 7, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 8, 42, 460, 3, srs_resource_configuration::comb_size_enum(4), 1, 4, 57, 5, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.311126, -0.436190), cf_t(0.194339, 0.425043), cf_t(0.065272, 1.223183), cf_t(-0.430315, -0.521180)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input19.dat"}}, + {{{{0, 661, 1, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 6, 7, 654, 0, srs_resource_configuration::comb_size_enum(2), 0, 4, 51, 1, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.275253, 0.531199), cf_t(0.047204, 0.025088), cf_t(1.257417, 0.864836), cf_t(1.574846, -0.048942), cf_t(-0.907399, -1.646820), cf_t(-0.358732, 0.166743), cf_t(0.637762, -1.297993), cf_t(0.173810, 0.049529)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input20.dat"}}, + {{{{0, 600, 3, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 3, 15, 45, 1, srs_resource_configuration::comb_size_enum(4), 2, 8, 26, 8, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.716159, 0.445007), cf_t(0.695472, -0.210504), cf_t(-0.150624, -0.612140), cf_t(0.808703, -0.375912), cf_t(-0.737589, -0.190967), cf_t(0.687708, -0.369287), cf_t(-0.309813, -0.288976), cf_t(0.124859, 0.686415)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input21.dat"}}, + {{{{0, 809, 3, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 13, 56, 335, 2, srs_resource_configuration::comb_size_enum(2), 0, 4, 50, 5, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.224441, 0.292467), cf_t(-0.010013, -0.817083), cf_t(0.625061, 0.127461), cf_t(-0.033849, 1.203025), cf_t(-0.408061, 0.101825), cf_t(-0.006735, -0.487770), cf_t(0.389513, 0.482929), cf_t(-0.360421, -0.002019), cf_t(-1.158712, -0.537465), cf_t(-0.471427, 0.611046), cf_t(0.827745, 0.336484), cf_t(0.650444, 0.105931), cf_t(-0.578974, 0.367504), cf_t(0.080200, 0.281685), cf_t(0.998599, 0.015987), cf_t(0.993438, 0.731234)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input22.dat"}}, + {{{{0, 682, 5, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 1, 46, 640, 3, srs_resource_configuration::comb_size_enum(4), 3, 6, 63, 7, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.300864, -0.929650), cf_t(0.424471, -0.962736), cf_t(-0.832210, -0.700412), cf_t(-0.001575, 0.065838), cf_t(-0.294447, 0.865985), cf_t(0.245785, -0.128583), cf_t(-0.829459, -1.220062), cf_t(-0.267397, -1.048410), cf_t(-0.030819, 0.411835), cf_t(-0.664351, -0.026540), cf_t(0.203808, -1.127258), cf_t(-0.030984, 0.679406), cf_t(-0.711703, 0.045620), cf_t(-1.340890, -1.504707), cf_t(0.077936, 0.556540), cf_t(1.229125, -0.304202)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input23.dat"}}, + {{{{0, 655, 2, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 5, 5, 210, 0, srs_resource_configuration::comb_size_enum(2), 0, 7, 39, 10, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.502566, 0.549424), cf_t(0.440099, 0.457767), cf_t(-0.300967, 0.741459), cf_t(0.467190, 1.773970)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input24.dat"}}, + {{{{0, 525, 8, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 2, 1, 408, 3, srs_resource_configuration::comb_size_enum(4), 1, 3, 31, 1, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.289443, -0.673615), cf_t(0.224377, 0.055169), cf_t(0.936482, -0.150734), cf_t(-0.095091, -0.828274)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input25.dat"}}, + {{{{0, 338, 1, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 11, 34, 120, 2, srs_resource_configuration::comb_size_enum(2), 1, 4, 31, 10, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.487940, 0.392979), cf_t(-0.260223, -0.962346), cf_t(-0.792140, -1.083778), cf_t(0.551237, 0.310711), cf_t(-0.776310, -1.001103), cf_t(-0.063373, 0.722083), cf_t(0.042123, -0.290798), cf_t(-0.617997, 0.293237)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input26.dat"}}, + {{{{0, 188, 7, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 7, 13, 307, 3, srs_resource_configuration::comb_size_enum(4), 0, 0, 30, 1, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-2.285396, -0.768596), cf_t(-0.176800, -1.109674), cf_t(-1.008643, -0.717325), cf_t(-0.337561, -0.946092), cf_t(-0.150803, -0.230056), cf_t(0.021425, 0.603223), cf_t(1.374897, -0.404305), cf_t(0.285850, -0.495413)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input27.dat"}}, + {{{{0, 926, 0, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 6, 21, 111, 1, srs_resource_configuration::comb_size_enum(2), 1, 0, 45, 9, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.283365, 0.067276), cf_t(-0.357473, -0.843795), cf_t(-0.043939, 0.847841), cf_t(1.972178, 0.514471), cf_t(0.351209, 0.765260), cf_t(0.457478, -0.250049), cf_t(0.566890, 0.744799), cf_t(-0.546639, 0.591589), cf_t(0.686210, -0.402039), cf_t(0.032834, -0.560699), cf_t(-0.529536, -0.662083), cf_t(-0.797850, -1.007252), cf_t(0.572737, 0.122504), cf_t(-1.096379, 0.121330), cf_t(-0.897380, 0.352125), cf_t(0.507308, -0.550062)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input28.dat"}}, + {{{{0, 597, 6, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 9, 62, 240, 3, srs_resource_configuration::comb_size_enum(4), 0, 4, 46, 8, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.291353, 0.286727), cf_t(0.191186, -0.461579), cf_t(-0.502981, 0.043449), cf_t(0.382285, 0.690024), cf_t(-0.257232, -0.423749), cf_t(0.337451, -0.050431), cf_t(-1.305411, -0.281664), cf_t(-0.110924, 0.196434), cf_t(-0.416902, 0.603545), cf_t(-0.663479, 0.114101), cf_t(-0.384347, -0.644810), cf_t(0.452207, -0.057260), cf_t(-1.310275, -0.146585), cf_t(-0.189634, -0.289824), cf_t(0.461528, -0.519208), cf_t(0.382453, -0.892768)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input29.dat"}}, + {{{{0, 272, 9, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 8, 25, 499, 1, srs_resource_configuration::comb_size_enum(2), 0, 5, 30, 8, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.286806, -1.003631), cf_t(-0.515796, 0.811283), cf_t(0.422754, -0.906003), cf_t(-1.557943, -0.403932)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input30.dat"}}, + {{{{0, 671, 0, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 7, 40, 543, 0, srs_resource_configuration::comb_size_enum(4), 0, 1, 11, 1, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.636361, -0.202011), cf_t(-0.326981, -0.289762), cf_t(-0.356056, 0.872073), cf_t(0.431551, 0.041770)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input31.dat"}}, + {{{{0, 79, 1, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 10, 20, 723, 0, srs_resource_configuration::comb_size_enum(2), 1, 2, 17, 6, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.059603, -1.408555), cf_t(-0.441845, -0.826412), cf_t(0.594851, -0.293208), cf_t(0.277593, 0.920540), cf_t(1.352116, -0.276407), cf_t(-0.419768, 0.308564), cf_t(0.289335, -0.807819), cf_t(-0.356638, 0.072201)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input32.dat"}}, + {{{{0, 343, 8, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 3, 23, 463, 2, srs_resource_configuration::comb_size_enum(4), 2, 5, 8, 4, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.547663, -0.985192), cf_t(0.578071, 0.346595), cf_t(-0.273109, 0.371646), cf_t(0.541114, 0.550326), cf_t(1.077114, 1.271728), cf_t(-1.046734, 0.382095), cf_t(-0.082650, -0.226413), cf_t(-0.064728, -0.537580)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input33.dat"}}, + {{{{0, 179, 0, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 1, 33, 681, 2, srs_resource_configuration::comb_size_enum(2), 0, 6, 46, 9, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-0.673214, 0.603899), cf_t(-0.134281, -0.730380), cf_t(0.119153, -0.212985), cf_t(0.634096, 0.356899), cf_t(0.275168, -0.817416), cf_t(-0.228602, 0.542016), cf_t(-0.494023, 0.588858), cf_t(-0.283477, -0.363345), cf_t(0.028101, -0.318621), cf_t(1.233670, -0.820612), cf_t(-0.491160, -0.326601), cf_t(0.563117, -0.474603), cf_t(0.077250, -0.177168), cf_t(1.681084, 1.079100), cf_t(0.624812, 0.308259), cf_t(0.839095, 0.559111)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input34.dat"}}, + {{{{0, 650, 8, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 10, 55, 454, 2, srs_resource_configuration::comb_size_enum(4), 1, 2, 44, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.208033, -0.550019), cf_t(1.250866, 1.068143), cf_t(-0.283071, -0.475036), cf_t(-0.248823, 0.190594), cf_t(-0.753019, -1.250458), cf_t(0.115973, -0.199944), cf_t(0.407031, -0.550195), cf_t(-1.813340, 0.329416), cf_t(-0.299049, -0.744656), cf_t(0.814704, -0.810703), cf_t(-0.752051, 0.391015), cf_t(1.310666, 0.734889), cf_t(0.458032, -0.224597), cf_t(0.476377, -0.473134), cf_t(-0.299409, 0.255681), cf_t(0.644101, -0.169516)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input35.dat"}}, + {{{{1, 542, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 3, 14, 254, 3, srs_resource_configuration::comb_size_enum(2), 1, 6, 5, 4, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.921012, 0.996958), cf_t(-1.175595, 1.374392)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input36.dat"}}, + {{{{1, 802, 0, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 7, 40, 906, 0, srs_resource_configuration::comb_size_enum(4), 0, 0, 7, 9, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.055288, 1.489612), cf_t(-0.506181, -0.198355)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input37.dat"}}, + {{{{1, 692, 9, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 13, 42, 785, 0, srs_resource_configuration::comb_size_enum(2), 0, 6, 27, 3, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.206282, 0.698406), cf_t(0.197838, 0.036218), cf_t(0.277847, 0.137569), cf_t(-0.547630, 0.556339)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input38.dat"}}, + {{{{1, 994, 9, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 4, 26, 907, 0, srs_resource_configuration::comb_size_enum(4), 0, 8, 53, 5, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.372978, 0.604012), cf_t(-0.118482, 0.249620), cf_t(0.948829, -1.767437), cf_t(0.507175, -0.922669)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input39.dat"}}, + {{{{1, 488, 2, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 8, 53, 242, 3, srs_resource_configuration::comb_size_enum(2), 1, 2, 6, 1, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-0.029460, -0.435229), cf_t(-1.232027, 0.145172), cf_t(-0.894940, -0.105593), cf_t(0.585758, 0.153964), cf_t(0.929248, -1.028887), cf_t(0.843529, -0.567682), cf_t(-1.157143, 0.012264), cf_t(-1.350040, -0.379590)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input40.dat"}}, + {{{{1, 442, 0, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(1), 13, 57, 831, 0, srs_resource_configuration::comb_size_enum(4), 1, 11, 48, 5, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.347014, -0.414454), cf_t(0.406248, 0.199292), cf_t(0.449819, 0.560862), cf_t(1.129429, 0.079507), cf_t(0.526724, -0.585594), cf_t(0.805611, -0.301134), cf_t(-0.635249, 0.110482), cf_t(-0.218231, 0.322907)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input41.dat"}}, + {{{{1, 423, 3, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 6, 20, 711, 3, srs_resource_configuration::comb_size_enum(2), 1, 0, 24, 10, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.166872, -0.590556), cf_t(-0.902237, 0.436310)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input42.dat"}}, + {{{{1, 676, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 0, 15, 357, 2, srs_resource_configuration::comb_size_enum(4), 3, 8, 9, 4, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.947208, -0.685286), cf_t(0.147584, -0.437412)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input43.dat"}}, + {{{{1, 501, 8, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 11, 23, 361, 2, srs_resource_configuration::comb_size_enum(2), 1, 1, 66, 7, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.282669, -0.462991), cf_t(-0.639815, -0.285800), cf_t(-0.209550, -1.058481), cf_t(-0.513217, -0.612697)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input44.dat"}}, + {{{{1, 905, 3, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 1, 3, 952, 1, srs_resource_configuration::comb_size_enum(4), 2, 6, 46, 4, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.447532, -1.031698), cf_t(-0.317564, 0.671239), cf_t(-0.411331, -1.294111), cf_t(0.507308, 1.617739)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input45.dat"}}, + {{{{1, 944, 5, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 10, 63, 292, 2, srs_resource_configuration::comb_size_enum(2), 1, 5, 38, 5, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-0.558371, 1.006185), cf_t(-0.604529, -0.760306), cf_t(0.844868, 0.428552), cf_t(-0.684263, 0.142872), cf_t(0.004477, 0.485415), cf_t(-0.064324, -0.178737), cf_t(0.382201, -1.021726), cf_t(-0.245987, 0.912230)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input46.dat"}}, + {{{{1, 820, 9, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(2), 11, 60, 611, 2, srs_resource_configuration::comb_size_enum(4), 2, 0, 30, 9, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.253469, 0.025613), cf_t(0.156464, 1.930669), cf_t(1.119082, 1.929857), cf_t(0.568076, -0.933312), cf_t(-0.257833, 1.252300), cf_t(-0.209421, 0.399017), cf_t(0.214652, -0.558797), cf_t(-0.193638, 0.192239)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input47.dat"}}, + {{{{1, 496, 9, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 8, 63, 427, 3, srs_resource_configuration::comb_size_enum(2), 0, 2, 53, 10, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.945606, 1.503083), cf_t(0.038216, 0.115284)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input48.dat"}}, + {{{{1, 461, 1, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 2, 56, 921, 1, srs_resource_configuration::comb_size_enum(4), 2, 1, 27, 8, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.286323, 0.373253), cf_t(-0.712030, 0.770058)}}, 1, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input49.dat"}}, + {{{{1, 509, 8, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 7, 21, 854, 1, srs_resource_configuration::comb_size_enum(2), 1, 4, 27, 2, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.023821, 0.324054), cf_t(-0.202709, 0.422861), cf_t(0.906250, 0.438470), cf_t(-0.173618, -1.259171)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input50.dat"}}, + {{{{1, 332, 0, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 3, 6, 11, 0, srs_resource_configuration::comb_size_enum(4), 2, 11, 38, 5, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.041238, -0.405974), cf_t(-1.241520, -0.181979), cf_t(-0.138036, -0.035731), cf_t(0.530006, -0.403591)}}, 2, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input51.dat"}}, + {{{{1, 907, 6, 0}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 10, 44, 195, 3, srs_resource_configuration::comb_size_enum(2), 1, 1, 26, 4, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.171510, -0.071169), cf_t(0.725625, -0.536077), cf_t(0.317324, 0.000443), cf_t(-0.561339, 0.607959), cf_t(-1.149083, -1.070859), cf_t(1.469612, -1.571182), cf_t(-0.534742, 0.285901), cf_t(0.047284, -1.159222)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input52.dat"}}, + {{{{1, 20, 0, 1}, {srs_resource_configuration::one_two_four_enum(2), srs_resource_configuration::one_two_four_enum(4), 4, 33, 852, 3, srs_resource_configuration::comb_size_enum(4), 0, 1, 35, 6, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-0.257082, 0.105752), cf_t(0.385946, 1.421233), cf_t(-0.664008, -1.229594), cf_t(0.739507, -0.672446), cf_t(-1.374982, 1.077556), cf_t(1.001737, 0.008118), cf_t(0.012000, 0.154969), cf_t(0.562007, 0.050509)}}, 4, 2}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input53.dat"}}, + {{{{1, 604, 1, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 6, 37, 964, 3, srs_resource_configuration::comb_size_enum(2), 0, 5, 20, 2, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.231468, 0.336242), cf_t(-0.091927, -0.420271), cf_t(-0.313791, -0.935170), cf_t(-0.607773, -0.999143)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input54.dat"}}, + {{{{1, 304, 4, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 5, 45, 122, 0, srs_resource_configuration::comb_size_enum(4), 3, 4, 0, 5, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.243688, -0.936150), cf_t(-0.406470, -0.523759), cf_t(-0.837923, -1.460077), cf_t(0.399558, 1.414314)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input55.dat"}}, + {{{{1, 494, 9, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 5, 48, 536, 0, srs_resource_configuration::comb_size_enum(2), 1, 7, 37, 10, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.373312, 0.511281), cf_t(0.288552, 0.758270), cf_t(-0.601000, -0.563129), cf_t(0.684467, 0.191022), cf_t(0.512891, 1.192567), cf_t(-0.448593, 0.445310), cf_t(-0.273222, -0.357144), cf_t(-0.056027, 0.973650)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input56.dat"}}, + {{{{1, 733, 0, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 2, 20, 344, 1, srs_resource_configuration::comb_size_enum(4), 2, 6, 18, 2, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.260730, -0.592676), cf_t(-0.413370, -0.437986), cf_t(-0.199740, 2.524278), cf_t(0.378515, 0.341523), cf_t(2.409489, 0.810993), cf_t(0.076703, -0.240618), cf_t(0.556675, -0.903780), cf_t(-0.654674, 0.003763)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input57.dat"}}, + {{{{1, 589, 7, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 10, 32, 661, 1, srs_resource_configuration::comb_size_enum(2), 0, 2, 45, 1, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(-0.162135, 0.185439), cf_t(-0.262829, 0.843482), cf_t(0.476870, 0.479701), cf_t(0.231619, 1.066407), cf_t(-0.634967, -1.525443), cf_t(0.674331, -1.000588), cf_t(-0.221027, 0.268166), cf_t(-0.628554, -0.678317), cf_t(0.066409, -0.672587), cf_t(-0.023586, 0.184638), cf_t(-1.593040, -0.826149), cf_t(-0.348405, 0.311874), cf_t(0.829146, 1.226898), cf_t(0.369813, 0.478561), cf_t(0.849918, -0.467213), cf_t(-0.144790, -0.691414)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input58.dat"}}, + {{{{1, 383, 1, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(1), 1, 39, 445, 0, srs_resource_configuration::comb_size_enum(4), 2, 2, 30, 1, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.206324, -0.434601), cf_t(0.010686, -0.823421), cf_t(-1.538884, -0.845455), cf_t(0.680434, -0.179587), cf_t(-0.009647, 0.291408), cf_t(0.349905, -0.859735), cf_t(0.258326, 1.705855), cf_t(1.337673, -0.862850), cf_t(-0.662665, 0.590545), cf_t(1.124857, 0.372274), cf_t(0.523434, 0.219024), cf_t(-0.266040, 0.037073), cf_t(0.773956, 0.227109), cf_t(0.187255, -0.278316), cf_t(-0.383243, 0.086467), cf_t(-1.381640, 0.399813)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input59.dat"}}, + {{{{1, 849, 5, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 11, 28, 807, 3, srs_resource_configuration::comb_size_enum(2), 0, 3, 35, 3, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(1.266379, 0.563750), cf_t(-0.312895, -0.444835), cf_t(1.084558, 1.932905), cf_t(0.118397, -0.338609)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input60.dat"}}, + {{{{1, 598, 0, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 12, 18, 62, 3, srs_resource_configuration::comb_size_enum(4), 0, 4, 56, 6, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(0.302950, -0.710066), cf_t(-0.447378, -0.739429), cf_t(0.357589, 0.234727), cf_t(-1.156411, -1.348340)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input61.dat"}}, + {{{{1, 565, 4, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 0, 28, 55, 1, srs_resource_configuration::comb_size_enum(2), 1, 6, 48, 8, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.579742, -0.604119), cf_t(-0.588301, 0.352068), cf_t(0.252662, 1.943459), cf_t(1.637395, -0.561320), cf_t(-1.069836, 0.306870), cf_t(0.382516, -0.395316), cf_t(-0.162470, -0.584838), cf_t(1.397643, 0.385133)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input62.dat"}}, + {{{{1, 510, 4, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 10, 37, 365, 3, srs_resource_configuration::comb_size_enum(4), 0, 8, 2, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.442257, 0.532423), cf_t(-0.247652, 1.145426), cf_t(0.150956, -0.544638), cf_t(-0.035944, -0.574664), cf_t(-0.005045, 0.065893), cf_t(-0.310010, 0.607129), cf_t(0.661322, 0.469178), cf_t(0.138039, 0.628520)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input63.dat"}}, + {{{{1, 547, 9, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 12, 19, 118, 2, srs_resource_configuration::comb_size_enum(2), 1, 6, 29, 0, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.048509, 0.531387), cf_t(0.199778, -0.795551), cf_t(-0.165430, -0.740153), cf_t(0.694686, -0.078803), cf_t(-0.487499, 0.318773), cf_t(-0.699310, -1.071874), cf_t(1.119576, -0.176362), cf_t(0.916376, 1.259566), cf_t(-1.106640, -0.055717), cf_t(-1.575795, -0.107142), cf_t(0.915010, 0.255959), cf_t(-0.046397, -0.180794), cf_t(-0.665947, -0.461643), cf_t(0.822184, -0.128648), cf_t(-0.186006, 0.765192), cf_t(0.286122, 0.248730)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input64.dat"}}, + {{{{1, 752, 7, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(2), 12, 19, 555, 0, srs_resource_configuration::comb_size_enum(4), 0, 5, 0, 5, 0, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(1.588208, 0.522751), cf_t(-0.115881, -0.047546), cf_t(0.874858, 0.761694), cf_t(-0.122555, 0.435790), cf_t(-1.462046, -0.816391), cf_t(-0.708233, -0.392912), cf_t(-0.024636, -0.356373), cf_t(0.610883, -1.001910), cf_t(-0.075796, -1.211188), cf_t(-0.955695, 0.257536), cf_t(-0.865512, 0.083799), cf_t(0.141387, 0.138470), cf_t(-0.325195, 0.771454), cf_t(-0.319759, 0.553923), cf_t(0.678450, -0.241074), cf_t(-0.106867, 0.631294)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input65.dat"}}, + {{{{1, 648, 3, 1}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 6, 63, 335, 3, srs_resource_configuration::comb_size_enum(2), 0, 0, 41, 8, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.700760, -0.178987), cf_t(0.713658, 0.036071), cf_t(-0.311433, -0.599958), cf_t(-0.169968, 0.426335)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input66.dat"}}, + {{{{1, 877, 1, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 0, 18, 708, 0, srs_resource_configuration::comb_size_enum(4), 2, 7, 61, 10, 3, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0}}, {{{{cf_t(-0.835890, 0.412843), cf_t(-0.410129, -0.396947), cf_t(-1.100185, 0.777965), cf_t(0.123785, 0.709660)}}, 1, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input67.dat"}}, + {{{{1, 973, 8, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 5, 47, 773, 0, srs_resource_configuration::comb_size_enum(2), 0, 3, 22, 0, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(-0.114515, -0.345706), cf_t(0.469718, -0.496576), cf_t(-0.157531, 0.192380), cf_t(0.354492, 0.382060), cf_t(-0.826276, -0.865664), cf_t(0.700567, 0.699596), cf_t(-1.484556, -0.275943), cf_t(-0.487084, -0.605876)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input68.dat"}}, + {{{{1, 851, 5, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 8, 43, 570, 0, srs_resource_configuration::comb_size_enum(4), 1, 6, 67, 2, 1, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1}}, {{{{cf_t(0.525011, 0.808650), cf_t(0.777273, 0.461898), cf_t(-0.646801, 0.127139), cf_t(-0.357141, -0.336578), cf_t(-0.695332, 0.272115), cf_t(-1.450673, -0.316999), cf_t(0.230303, 0.916630), cf_t(-1.096862, 0.657486)}}, 2, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input69.dat"}}, + {{{{1, 346, 7, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 9, 57, 565, 1, srs_resource_configuration::comb_size_enum(2), 1, 7, 54, 10, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.636428, -1.082735), cf_t(0.429025, 1.155765), cf_t(-1.474862, 0.166852), cf_t(-0.183946, -0.161783), cf_t(0.356821, -0.611092), cf_t(-0.440877, -0.954665), cf_t(-0.550427, 0.777508), cf_t(-0.371099, 0.797842), cf_t(-0.266265, 0.557208), cf_t(-0.821828, -0.667706), cf_t(-0.604975, 0.005344), cf_t(0.389007, 1.311787), cf_t(0.210863, -0.115783), cf_t(-0.474618, 0.407775), cf_t(-0.662973, -0.481935), cf_t(-0.196080, 0.754222)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input70.dat"}}, + {{{{1, 820, 0, 0}, {srs_resource_configuration::one_two_four_enum(4), srs_resource_configuration::one_two_four_enum(4), 2, 52, 954, 2, srs_resource_configuration::comb_size_enum(4), 3, 2, 21, 8, 2, srs_resource_configuration::group_or_sequence_hopping_enum::neither, {}}, {0, 1, 2, 3}}, {{{{cf_t(0.131911, 0.672419), cf_t(-0.394426, -0.075346), cf_t(-0.388132, -0.089103), cf_t(0.518831, 0.085087), cf_t(-0.558981, -0.346113), cf_t(-0.152142, 0.334808), cf_t(0.211835, 0.209425), cf_t(0.803508, -0.485622), cf_t(2.103271, -0.440234), cf_t(0.965654, -1.158102), cf_t(0.849082, 0.770869), cf_t(0.333530, 0.203889), cf_t(1.357859, 0.679635), cf_t(1.430992, 0.549980), cf_t(-0.253641, -0.091873), cf_t(0.984190, -0.951414)}}, 4, 4}, 0, phy_time_unit::from_seconds(0.000000)}}, {"test_data/srs_estimator_test_input71.dat"}}, + // clang-format on +}; + +} // namespace srsran diff --git a/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp new file mode 100644 index 0000000000..9fc09eba03 --- /dev/null +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp @@ -0,0 +1,91 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "../../../support/resource_grid_test_doubles.h" +#include "srs_estimator_test_data.h" +#include "srsran/phy/upper/signal_processors/srs/formatters.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h" +#include "srsran/phy/upper/signal_processors/srs/srs_estimator_result.h" +#include "srsran/ran/srs/srs_channel_matrix_formatters.h" +#include +#include +#include + +namespace srsran { + +std::ostream& operator<<(std::ostream& os, const test_case_t& test_case) +{ + fmt::print(os, "{}", test_case.context.config); + return os; +} + +std::ostream& operator<<(std::ostream& os, const srs_channel_matrix& channel) +{ + fmt::print(os, "{}", channel); + return os; +} + +bool operator==(const srs_channel_matrix& left, const srs_channel_matrix& right) +{ + return left.is_near(right, 1e-2); +} + +} // namespace srsran + +using namespace srsran; + +class SrsEstimatorFixture : public ::testing::TestWithParam +{ +protected: + void SetUp() override + { + std::shared_ptr sequence_generator_factory = + create_low_papr_sequence_generator_sw_factory(); + ASSERT_NE(sequence_generator_factory, nullptr); + + std::shared_ptr srs_est_factory = + create_srs_estimator_generic_factory(sequence_generator_factory); + ASSERT_NE(srs_est_factory, nullptr); + + estimator = srs_est_factory->create(); + ASSERT_NE(estimator, nullptr); + } + + std::unique_ptr estimator = nullptr; +}; + +TEST_P(SrsEstimatorFixture, FromVector) +{ + const test_case_t& test_case = GetParam(); + const srs_estimator_configuration& config = test_case.context.config; + + resource_grid_reader_spy grid; + grid.write(GetParam().rx_grid.read()); + + srs_estimator_result result = estimator->estimate(grid, config); + + ASSERT_EQ(test_case.context.result.channel_matrix, result.channel_matrix); +} + +INSTANTIATE_TEST_SUITE_P(SrsEstimatorFixture, SrsEstimatorFixture, ::testing::ValuesIn(srs_estimator_test_data)); \ No newline at end of file diff --git a/tests/unittests/psup/psup_packing_test.cpp b/tests/unittests/psup/psup_packing_test.cpp index 9762cfbdfc..13aaeecb2b 100644 --- a/tests/unittests/psup/psup_packing_test.cpp +++ b/tests/unittests/psup/psup_packing_test.cpp @@ -72,7 +72,7 @@ TEST_F(psup_packing_test, pack_psup_dl_pdu_session_information_smallest) // No further fields // No padding }; - EXPECT_EQ(out_buf, byte_buffer{expected_vec}); + EXPECT_EQ(out_buf, byte_buffer::create(expected_vec).value()); } TEST_F(psup_packing_test, unpack_psup_dl_pdu_session_information_smallest) @@ -83,7 +83,7 @@ TEST_F(psup_packing_test, unpack_psup_dl_pdu_session_information_smallest) // No further fields // No padding }; - byte_buffer packed_buf{packed_vec}; + byte_buffer packed_buf = byte_buffer::create(packed_vec).value(); psup_dl_pdu_session_information out_sess_info; packer->unpack(out_sess_info, packed_buf); psup_dl_pdu_session_information expected_sess_info{}; @@ -117,7 +117,7 @@ TEST_F(psup_packing_test, pack_psup_dl_pdu_session_information_largest) 0x01, // No padding }; - EXPECT_EQ(out_buf, byte_buffer{expected_vec}); + EXPECT_EQ(out_buf, byte_buffer::create(expected_vec).value()); } TEST_F(psup_packing_test, unpack_psup_dl_pdu_session_information_largest) @@ -139,7 +139,7 @@ TEST_F(psup_packing_test, unpack_psup_dl_pdu_session_information_largest) 0x01, // No padding }; - byte_buffer packed_buf{packed_vec}; + byte_buffer packed_buf = byte_buffer::create(packed_vec).value(); psup_dl_pdu_session_information out_sess_info; packer->unpack(out_sess_info, packed_buf); psup_dl_pdu_session_information expected_sess_info{}; @@ -161,7 +161,7 @@ TEST_F(psup_packing_test, pack_unpack_psup_dl_pdu_session_information_grow) buf_out.clear(); packer->pack(buf_out, sess_info_in); EXPECT_TRUE((buf_out.length() + 2) % 4 == 0); - buf_in = buf_out.deep_copy(); + buf_in = buf_out.deep_copy().value(); packer->unpack(sess_info_out, buf_in); EXPECT_EQ(sess_info_out, sess_info_in); @@ -170,7 +170,7 @@ TEST_F(psup_packing_test, pack_unpack_psup_dl_pdu_session_information_grow) packer->pack(buf_out, sess_info_in); EXPECT_EQ(buf_out.length(), 6); EXPECT_TRUE((buf_out.length() + 2) % 4 == 0); - buf_in = buf_out.deep_copy(); + buf_in = buf_out.deep_copy().value(); packer->unpack(sess_info_out, buf_in); EXPECT_EQ(sess_info_out, sess_info_in); @@ -179,7 +179,7 @@ TEST_F(psup_packing_test, pack_unpack_psup_dl_pdu_session_information_grow) packer->pack(buf_out, sess_info_in); EXPECT_EQ(buf_out.length(), 14); EXPECT_TRUE((buf_out.length() + 2) % 4 == 0); - buf_in = buf_out.deep_copy(); + buf_in = buf_out.deep_copy().value(); packer->unpack(sess_info_out, buf_in); EXPECT_EQ(sess_info_out, sess_info_in); @@ -188,7 +188,7 @@ TEST_F(psup_packing_test, pack_unpack_psup_dl_pdu_session_information_grow) packer->pack(buf_out, sess_info_in); EXPECT_EQ(buf_out.length(), 14); EXPECT_TRUE((buf_out.length() + 2) % 4 == 0); - buf_in = buf_out.deep_copy(); + buf_in = buf_out.deep_copy().value(); packer->unpack(sess_info_out, buf_in); EXPECT_EQ(sess_info_out, sess_info_in); } diff --git a/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h b/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h index 870f9b34d3..5f1c325229 100644 --- a/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h +++ b/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h @@ -22,7 +22,7 @@ #pragma once -// This file was generated using the following MATLAB class on 14-09-2023 (seed 0): +// This file was generated using the following MATLAB class on 05-03-2024 (seed 0): // + "srsPDCCHCandidatesUeUnittest.m" #include "srsran/ran/pdcch/pdcch_candidates.h" @@ -36,224 +36,224 @@ struct test_case_t { static const std::vector pdcch_candidates_ue_test_data = { // clang-format off - {{aggregation_level::n1, 0, 24, to_coreset_id(9), to_rnti(59362), 20}, {}}, - {{aggregation_level::n1, 1, 24, to_coreset_id(11), to_rnti(41442), 15}, {5}}, - {{aggregation_level::n2, 1, 24, to_coreset_id(4), to_rnti(35840), 153}, {22}}, - {{aggregation_level::n4, 1, 24, to_coreset_id(11), to_rnti(10330), 155}, {4}}, - {{aggregation_level::n8, 1, 24, to_coreset_id(11), to_rnti(31810), 128}, {8}}, - {{aggregation_level::n16, 1, 24, to_coreset_id(2), to_rnti(27641), 146}, {0}}, - {{aggregation_level::n1, 2, 24, to_coreset_id(9), to_rnti(62881), 104}, {12, 0}}, - {{aggregation_level::n2, 2, 24, to_coreset_id(1), to_rnti(55648), 149}, {14, 2}}, - {{aggregation_level::n4, 2, 24, to_coreset_id(8), to_rnti(49659), 118}, {8, 20}}, - {{aggregation_level::n8, 2, 24, to_coreset_id(5), to_rnti(42957), 27}, {0, 8}}, - {{aggregation_level::n1, 3, 24, to_coreset_id(8), to_rnti(2087), 44}, {13, 21, 5}}, - {{aggregation_level::n2, 3, 24, to_coreset_id(1), to_rnti(6366), 131}, {2, 10, 18}}, - {{aggregation_level::n4, 3, 24, to_coreset_id(8), to_rnti(20782), 152}, {8, 16, 0}}, - {{aggregation_level::n8, 3, 24, to_coreset_id(1), to_rnti(28754), 61}, {0, 8, 16}}, - {{aggregation_level::n1, 4, 24, to_coreset_id(9), to_rnti(52114), 29}, {11, 17, 23, 5}}, - {{aggregation_level::n2, 4, 24, to_coreset_id(6), to_rnti(29202), 103}, {22, 4, 10, 16}}, - {{aggregation_level::n4, 4, 24, to_coreset_id(8), to_rnti(49459), 44}, {8, 12, 20, 0}}, - {{aggregation_level::n1, 5, 24, to_coreset_id(8), to_rnti(42932), 26}, {14, 18, 23, 4, 9}}, - {{aggregation_level::n2, 5, 24, to_coreset_id(2), to_rnti(32661), 153}, {10, 14, 18, 0, 4}}, - {{aggregation_level::n4, 5, 24, to_coreset_id(4), to_rnti(38356), 35}, {12, 16, 20, 0, 4}}, - {{aggregation_level::n1, 6, 24, to_coreset_id(9), to_rnti(16718), 80}, {18, 22, 2, 6, 10, 14}}, - {{aggregation_level::n2, 6, 24, to_coreset_id(8), to_rnti(58386), 153}, {20, 0, 4, 8, 12, 16}}, - {{aggregation_level::n4, 6, 24, to_coreset_id(7), to_rnti(9085), 23}, {12, 16, 20, 0, 4, 8}}, - {{aggregation_level::n1, 7, 24, to_coreset_id(3), to_rnti(55097), 40}, {0, 3, 6, 10, 13, 17, 20}}, - {{aggregation_level::n2, 7, 24, to_coreset_id(9), to_rnti(15960), 148}, {10, 12, 16, 20, 22, 2, 6}}, - {{aggregation_level::n1, 8, 24, to_coreset_id(4), to_rnti(12884), 40}, {1, 4, 7, 10, 13, 16, 19, 22}}, - {{aggregation_level::n2, 8, 24, to_coreset_id(7), to_rnti(31017), 56}, {14, 16, 20, 22, 2, 4, 8, 10}}, - {{aggregation_level::n1, 0, 48, to_coreset_id(10), to_rnti(38356), 87}, {}}, - {{aggregation_level::n1, 1, 48, to_coreset_id(11), to_rnti(18733), 121}, {1}}, - {{aggregation_level::n2, 1, 48, to_coreset_id(9), to_rnti(24933), 90}, {26}}, - {{aggregation_level::n4, 1, 48, to_coreset_id(1), to_rnti(3536), 84}, {24}}, - {{aggregation_level::n8, 1, 48, to_coreset_id(9), to_rnti(61211), 20}, {32}}, - {{aggregation_level::n16, 1, 48, to_coreset_id(7), to_rnti(30762), 1}, {16}}, - {{aggregation_level::n1, 2, 48, to_coreset_id(4), to_rnti(10629), 127}, {19, 43}}, - {{aggregation_level::n2, 2, 48, to_coreset_id(4), to_rnti(34638), 26}, {32, 8}}, - {{aggregation_level::n4, 2, 48, to_coreset_id(7), to_rnti(17234), 104}, {8, 32}}, - {{aggregation_level::n8, 2, 48, to_coreset_id(8), to_rnti(49031), 72}, {16, 40}}, - {{aggregation_level::n16, 2, 48, to_coreset_id(1), to_rnti(15007), 146}, {0, 16}}, - {{aggregation_level::n1, 3, 48, to_coreset_id(2), to_rnti(54120), 86}, {24, 40, 8}}, - {{aggregation_level::n2, 3, 48, to_coreset_id(11), to_rnti(5124), 70}, {10, 26, 42}}, - {{aggregation_level::n4, 3, 48, to_coreset_id(2), to_rnti(63038), 0}, {28, 44, 12}}, - {{aggregation_level::n8, 3, 48, to_coreset_id(9), to_rnti(53562), 138}, {16, 32, 0}}, - {{aggregation_level::n16, 3, 48, to_coreset_id(1), to_rnti(26200), 41}, {32, 0, 16}}, - {{aggregation_level::n1, 4, 48, to_coreset_id(9), to_rnti(28273), 145}, {30, 42, 6, 18}}, - {{aggregation_level::n2, 4, 48, to_coreset_id(3), to_rnti(17289), 23}, {40, 4, 16, 28}}, - {{aggregation_level::n4, 4, 48, to_coreset_id(2), to_rnti(56970), 92}, {36, 0, 12, 24}}, - {{aggregation_level::n8, 4, 48, to_coreset_id(7), to_rnti(9500), 136}, {40, 0, 16, 24}}, - {{aggregation_level::n1, 5, 48, to_coreset_id(7), to_rnti(23000), 82}, {43, 4, 14, 23, 33}}, - {{aggregation_level::n2, 5, 48, to_coreset_id(5), to_rnti(4979), 38}, {28, 36, 46, 8, 18}}, - {{aggregation_level::n4, 5, 48, to_coreset_id(2), to_rnti(12053), 38}, {8, 16, 24, 36, 44}}, - {{aggregation_level::n8, 5, 48, to_coreset_id(5), to_rnti(3255), 144}, {32, 40, 0, 8, 16}}, - {{aggregation_level::n1, 6, 48, to_coreset_id(11), to_rnti(32169), 78}, {3, 11, 19, 27, 35, 43}}, - {{aggregation_level::n2, 6, 48, to_coreset_id(4), to_rnti(58986), 59}, {44, 4, 12, 20, 28, 36}}, - {{aggregation_level::n4, 6, 48, to_coreset_id(2), to_rnti(51134), 62}, {16, 24, 32, 40, 0, 8}}, - {{aggregation_level::n8, 6, 48, to_coreset_id(3), to_rnti(26471), 15}, {0, 8, 16, 24, 32, 40}}, - {{aggregation_level::n1, 7, 48, to_coreset_id(2), to_rnti(61738), 152}, {27, 33, 40, 47, 6, 13, 20}}, - {{aggregation_level::n2, 7, 48, to_coreset_id(7), to_rnti(3918), 37}, {26, 32, 38, 46, 4, 12, 18}}, - {{aggregation_level::n4, 7, 48, to_coreset_id(4), to_rnti(53817), 2}, {40, 44, 4, 12, 16, 24, 32}}, - {{aggregation_level::n1, 8, 48, to_coreset_id(1), to_rnti(11075), 103}, {26, 32, 38, 44, 2, 8, 14, 20}}, - {{aggregation_level::n2, 8, 48, to_coreset_id(9), to_rnti(42451), 72}, {42, 0, 6, 12, 18, 24, 30, 36}}, - {{aggregation_level::n4, 8, 48, to_coreset_id(7), to_rnti(19420), 119}, {8, 12, 20, 24, 32, 36, 44, 0}}, - {{aggregation_level::n1, 0, 72, to_coreset_id(3), to_rnti(45008), 29}, {}}, - {{aggregation_level::n1, 1, 72, to_coreset_id(5), to_rnti(41000), 124}, {8}}, - {{aggregation_level::n2, 1, 72, to_coreset_id(1), to_rnti(60908), 124}, {20}}, - {{aggregation_level::n4, 1, 72, to_coreset_id(6), to_rnti(28564), 71}, {52}}, - {{aggregation_level::n8, 1, 72, to_coreset_id(4), to_rnti(33326), 81}, {32}}, - {{aggregation_level::n16, 1, 72, to_coreset_id(9), to_rnti(52090), 103}, {32}}, - {{aggregation_level::n1, 2, 72, to_coreset_id(5), to_rnti(53187), 85}, {49, 13}}, - {{aggregation_level::n2, 2, 72, to_coreset_id(4), to_rnti(61538), 140}, {46, 10}}, - {{aggregation_level::n4, 2, 72, to_coreset_id(7), to_rnti(40794), 93}, {0, 36}}, - {{aggregation_level::n8, 2, 72, to_coreset_id(3), to_rnti(19743), 75}, {32, 64}}, - {{aggregation_level::n16, 2, 72, to_coreset_id(3), to_rnti(55332), 31}, {32, 0}}, - {{aggregation_level::n1, 3, 72, to_coreset_id(3), to_rnti(11188), 36}, {50, 2, 26}}, - {{aggregation_level::n2, 3, 72, to_coreset_id(5), to_rnti(20389), 147}, {2, 26, 50}}, - {{aggregation_level::n4, 3, 72, to_coreset_id(5), to_rnti(12112), 144}, {32, 56, 8}}, - {{aggregation_level::n8, 3, 72, to_coreset_id(11), to_rnti(28762), 17}, {56, 8, 32}}, - {{aggregation_level::n16, 3, 72, to_coreset_id(3), to_rnti(26786), 95}, {0, 16, 48}}, - {{aggregation_level::n1, 4, 72, to_coreset_id(3), to_rnti(39508), 113}, {26, 44, 62, 8}}, - {{aggregation_level::n2, 4, 72, to_coreset_id(3), to_rnti(7695), 47}, {62, 8, 26, 44}}, - {{aggregation_level::n4, 4, 72, to_coreset_id(4), to_rnti(27798), 81}, {44, 60, 8, 24}}, - {{aggregation_level::n8, 4, 72, to_coreset_id(1), to_rnti(17202), 128}, {16, 32, 48, 64}}, - {{aggregation_level::n16, 4, 72, to_coreset_id(1), to_rnti(60873), 116}, {16, 32, 48, 0}}, - {{aggregation_level::n1, 5, 72, to_coreset_id(6), to_rnti(37914), 37}, {48, 62, 4, 19, 33}}, - {{aggregation_level::n2, 5, 72, to_coreset_id(6), to_rnti(63117), 87}, {22, 36, 50, 64, 6}}, - {{aggregation_level::n4, 5, 72, to_coreset_id(6), to_rnti(15178), 78}, {12, 24, 40, 52, 68}}, - {{aggregation_level::n8, 5, 72, to_coreset_id(7), to_rnti(44508), 63}, {48, 56, 0, 16, 32}}, - {{aggregation_level::n1, 6, 72, to_coreset_id(5), to_rnti(64748), 6}, {40, 52, 64, 4, 16, 28}}, - {{aggregation_level::n2, 6, 72, to_coreset_id(10), to_rnti(59853), 127}, {68, 8, 20, 32, 44, 56}}, - {{aggregation_level::n4, 6, 72, to_coreset_id(2), to_rnti(17162), 53}, {24, 36, 48, 60, 0, 12}}, - {{aggregation_level::n8, 6, 72, to_coreset_id(8), to_rnti(8950), 115}, {16, 24, 40, 48, 64, 0}}, - {{aggregation_level::n1, 7, 72, to_coreset_id(2), to_rnti(42844), 79}, {67, 5, 15, 25, 36, 46, 56}}, - {{aggregation_level::n2, 7, 72, to_coreset_id(9), to_rnti(46860), 144}, {62, 0, 10, 20, 30, 40, 50}}, - {{aggregation_level::n4, 7, 72, to_coreset_id(10), to_rnti(21900), 111}, {20, 28, 40, 48, 60, 68, 8}}, + {{aggregation_level::n1, 0, 24, to_coreset_id(9), to_rnti(59347), 20}, {}}, + {{aggregation_level::n1, 1, 24, to_coreset_id(11), to_rnti(41432), 15}, {18}}, + {{aggregation_level::n2, 1, 24, to_coreset_id(4), to_rnti(35832), 153}, {10}}, + {{aggregation_level::n4, 1, 24, to_coreset_id(11), to_rnti(10327), 155}, {8}}, + {{aggregation_level::n8, 1, 24, to_coreset_id(11), to_rnti(31802), 128}, {8}}, + {{aggregation_level::n16, 1, 24, to_coreset_id(2), to_rnti(27634), 146}, {0}}, + {{aggregation_level::n1, 2, 24, to_coreset_id(9), to_rnti(62865), 104}, {3, 15}}, + {{aggregation_level::n2, 2, 24, to_coreset_id(1), to_rnti(55635), 149}, {8, 20}}, + {{aggregation_level::n4, 2, 24, to_coreset_id(8), to_rnti(49647), 118}, {16, 4}}, + {{aggregation_level::n8, 2, 24, to_coreset_id(5), to_rnti(42947), 27}, {8, 16}}, + {{aggregation_level::n1, 3, 24, to_coreset_id(8), to_rnti(2086), 44}, {13, 21, 5}}, + {{aggregation_level::n2, 3, 24, to_coreset_id(1), to_rnti(6364), 131}, {0, 8, 16}}, + {{aggregation_level::n4, 3, 24, to_coreset_id(8), to_rnti(20777), 152}, {0, 8, 16}}, + {{aggregation_level::n8, 3, 24, to_coreset_id(1), to_rnti(28747), 61}, {8, 16, 0}}, + {{aggregation_level::n1, 4, 24, to_coreset_id(9), to_rnti(52101), 29}, {0, 6, 12, 18}}, + {{aggregation_level::n2, 4, 24, to_coreset_id(6), to_rnti(29195), 103}, {20, 2, 8, 14}}, + {{aggregation_level::n4, 4, 24, to_coreset_id(8), to_rnti(49447), 44}, {0, 4, 12, 16}}, + {{aggregation_level::n1, 5, 24, to_coreset_id(8), to_rnti(42922), 26}, {5, 9, 14, 19, 0}}, + {{aggregation_level::n2, 5, 24, to_coreset_id(2), to_rnti(32653), 153}, {16, 20, 0, 6, 10}}, + {{aggregation_level::n4, 5, 24, to_coreset_id(4), to_rnti(38347), 35}, {0, 4, 8, 12, 16}}, + {{aggregation_level::n1, 6, 24, to_coreset_id(9), to_rnti(16714), 80}, {5, 9, 13, 17, 21, 1}}, + {{aggregation_level::n2, 6, 24, to_coreset_id(8), to_rnti(58372), 153}, {22, 2, 6, 10, 14, 18}}, + {{aggregation_level::n4, 6, 24, to_coreset_id(7), to_rnti(9083), 23}, {12, 16, 20, 0, 4, 8}}, + {{aggregation_level::n1, 7, 24, to_coreset_id(3), to_rnti(55083), 40}, {7, 10, 13, 17, 20, 0, 3}}, + {{aggregation_level::n2, 7, 24, to_coreset_id(9), to_rnti(15956), 148}, {18, 20, 0, 4, 6, 10, 14}}, + {{aggregation_level::n1, 8, 24, to_coreset_id(4), to_rnti(12881), 40}, {18, 21, 0, 3, 6, 9, 12, 15}}, + {{aggregation_level::n2, 8, 24, to_coreset_id(7), to_rnti(31010), 56}, {20, 22, 2, 4, 8, 10, 14, 16}}, + {{aggregation_level::n1, 0, 48, to_coreset_id(10), to_rnti(38346), 87}, {}}, + {{aggregation_level::n1, 1, 48, to_coreset_id(11), to_rnti(18728), 121}, {10}}, + {{aggregation_level::n2, 1, 48, to_coreset_id(9), to_rnti(24927), 90}, {2}}, + {{aggregation_level::n4, 1, 48, to_coreset_id(1), to_rnti(3535), 84}, {0}}, + {{aggregation_level::n8, 1, 48, to_coreset_id(9), to_rnti(61196), 20}, {32}}, + {{aggregation_level::n16, 1, 48, to_coreset_id(7), to_rnti(30755), 1}, {32}}, + {{aggregation_level::n1, 2, 48, to_coreset_id(4), to_rnti(10627), 127}, {38, 14}}, + {{aggregation_level::n2, 2, 48, to_coreset_id(4), to_rnti(34629), 26}, {24, 0}}, + {{aggregation_level::n4, 2, 48, to_coreset_id(7), to_rnti(17230), 104}, {12, 36}}, + {{aggregation_level::n8, 2, 48, to_coreset_id(8), to_rnti(49019), 72}, {0, 24}}, + {{aggregation_level::n16, 2, 48, to_coreset_id(1), to_rnti(15003), 146}, {16, 32}}, + {{aggregation_level::n1, 3, 48, to_coreset_id(2), to_rnti(54107), 86}, {3, 19, 35}}, + {{aggregation_level::n2, 3, 48, to_coreset_id(11), to_rnti(5122), 70}, {24, 40, 8}}, + {{aggregation_level::n4, 3, 48, to_coreset_id(2), to_rnti(63023), 0}, {28, 44, 12}}, + {{aggregation_level::n8, 3, 48, to_coreset_id(9), to_rnti(53549), 138}, {24, 40, 8}}, + {{aggregation_level::n16, 3, 48, to_coreset_id(1), to_rnti(26194), 41}, {16, 32, 0}}, + {{aggregation_level::n1, 4, 48, to_coreset_id(9), to_rnti(28266), 145}, {25, 37, 1, 13}}, + {{aggregation_level::n2, 4, 48, to_coreset_id(3), to_rnti(17285), 23}, {46, 10, 22, 34}}, + {{aggregation_level::n4, 4, 48, to_coreset_id(2), to_rnti(56956), 92}, {4, 16, 28, 40}}, + {{aggregation_level::n8, 4, 48, to_coreset_id(7), to_rnti(9498), 136}, {16, 24, 40, 0}}, + {{aggregation_level::n1, 5, 48, to_coreset_id(7), to_rnti(22995), 82}, {43, 4, 14, 23, 33}}, + {{aggregation_level::n2, 5, 48, to_coreset_id(5), to_rnti(4978), 38}, {44, 4, 14, 24, 34}}, + {{aggregation_level::n4, 5, 48, to_coreset_id(2), to_rnti(12050), 38}, {16, 24, 32, 44, 4}}, + {{aggregation_level::n8, 5, 48, to_coreset_id(5), to_rnti(3254), 144}, {40, 0, 8, 16, 24}}, + {{aggregation_level::n1, 6, 48, to_coreset_id(11), to_rnti(32161), 78}, {39, 47, 7, 15, 23, 31}}, + {{aggregation_level::n2, 6, 48, to_coreset_id(4), to_rnti(58971), 59}, {2, 10, 18, 26, 34, 42}}, + {{aggregation_level::n4, 6, 48, to_coreset_id(2), to_rnti(51122), 62}, {40, 0, 8, 16, 24, 32}}, + {{aggregation_level::n8, 6, 48, to_coreset_id(3), to_rnti(26464), 15}, {8, 16, 24, 32, 40, 0}}, + {{aggregation_level::n1, 7, 48, to_coreset_id(2), to_rnti(61723), 152}, {10, 16, 23, 30, 37, 44, 3}}, + {{aggregation_level::n2, 7, 48, to_coreset_id(7), to_rnti(3917), 37}, {42, 0, 6, 14, 20, 28, 34}}, + {{aggregation_level::n4, 7, 48, to_coreset_id(4), to_rnti(53804), 2}, {32, 36, 44, 4, 8, 16, 24}}, + {{aggregation_level::n1, 8, 48, to_coreset_id(1), to_rnti(11073), 103}, {41, 47, 5, 11, 17, 23, 29, 35}}, + {{aggregation_level::n2, 8, 48, to_coreset_id(9), to_rnti(42440), 72}, {44, 2, 8, 14, 20, 26, 32, 38}}, + {{aggregation_level::n4, 8, 48, to_coreset_id(7), to_rnti(19415), 119}, {32, 36, 44, 0, 8, 12, 20, 24}}, + {{aggregation_level::n1, 0, 72, to_coreset_id(3), to_rnti(44997), 29}, {}}, + {{aggregation_level::n1, 1, 72, to_coreset_id(5), to_rnti(40990), 124}, {7}}, + {{aggregation_level::n2, 1, 72, to_coreset_id(1), to_rnti(60893), 124}, {18}}, + {{aggregation_level::n4, 1, 72, to_coreset_id(6), to_rnti(28558), 71}, {36}}, + {{aggregation_level::n8, 1, 72, to_coreset_id(4), to_rnti(33317), 81}, {40}}, + {{aggregation_level::n16, 1, 72, to_coreset_id(9), to_rnti(52077), 103}, {32}}, + {{aggregation_level::n1, 2, 72, to_coreset_id(5), to_rnti(53174), 85}, {33, 69}}, + {{aggregation_level::n2, 2, 72, to_coreset_id(4), to_rnti(61523), 140}, {2, 38}}, + {{aggregation_level::n4, 2, 72, to_coreset_id(7), to_rnti(40784), 93}, {16, 52}}, + {{aggregation_level::n8, 2, 72, to_coreset_id(3), to_rnti(19738), 75}, {24, 56}}, + {{aggregation_level::n16, 2, 72, to_coreset_id(3), to_rnti(55319), 31}, {0, 32}}, + {{aggregation_level::n1, 3, 72, to_coreset_id(3), to_rnti(11185), 36}, {47, 71, 23}}, + {{aggregation_level::n2, 3, 72, to_coreset_id(5), to_rnti(20384), 147}, {38, 62, 14}}, + {{aggregation_level::n4, 3, 72, to_coreset_id(5), to_rnti(12109), 144}, {36, 60, 12}}, + {{aggregation_level::n8, 3, 72, to_coreset_id(11), to_rnti(28755), 17}, {24, 48, 0}}, + {{aggregation_level::n16, 3, 72, to_coreset_id(3), to_rnti(26779), 95}, {0, 16, 48}}, + {{aggregation_level::n1, 4, 72, to_coreset_id(3), to_rnti(39498), 113}, {26, 44, 62, 8}}, + {{aggregation_level::n2, 4, 72, to_coreset_id(3), to_rnti(7694), 47}, {2, 20, 38, 56}}, + {{aggregation_level::n4, 4, 72, to_coreset_id(4), to_rnti(27791), 81}, {68, 12, 32, 48}}, + {{aggregation_level::n8, 4, 72, to_coreset_id(1), to_rnti(17198), 128}, {24, 40, 56, 0}}, + {{aggregation_level::n16, 4, 72, to_coreset_id(1), to_rnti(60858), 116}, {0, 16, 32, 48}}, + {{aggregation_level::n1, 5, 72, to_coreset_id(6), to_rnti(37905), 37}, {52, 66, 8, 23, 37}}, + {{aggregation_level::n2, 5, 72, to_coreset_id(6), to_rnti(63101), 87}, {24, 38, 52, 66, 8}}, + {{aggregation_level::n4, 5, 72, to_coreset_id(6), to_rnti(15174), 78}, {20, 32, 48, 60, 4}}, + {{aggregation_level::n8, 5, 72, to_coreset_id(7), to_rnti(44497), 63}, {16, 24, 40, 56, 0}}, + {{aggregation_level::n1, 6, 72, to_coreset_id(5), to_rnti(64732), 6}, {60, 0, 12, 24, 36, 48}}, + {{aggregation_level::n2, 6, 72, to_coreset_id(10), to_rnti(59838), 127}, {22, 34, 46, 58, 70, 10}}, + {{aggregation_level::n4, 6, 72, to_coreset_id(2), to_rnti(17158), 53}, {24, 36, 48, 60, 0, 12}}, + {{aggregation_level::n8, 6, 72, to_coreset_id(8), to_rnti(8947), 115}, {48, 56, 0, 8, 24, 32}}, + {{aggregation_level::n1, 7, 72, to_coreset_id(2), to_rnti(42834), 79}, {70, 8, 18, 28, 39, 49, 59}}, + {{aggregation_level::n2, 7, 72, to_coreset_id(9), to_rnti(46849), 144}, {2, 12, 22, 32, 42, 52, 62}}, + {{aggregation_level::n4, 7, 72, to_coreset_id(10), to_rnti(21895), 111}, {40, 48, 60, 68, 8, 16, 28}}, {{aggregation_level::n8, 7, 72, to_coreset_id(3), to_rnti(2002), 119}, {40, 48, 56, 64, 8, 16, 24}}, - {{aggregation_level::n1, 8, 72, to_coreset_id(6), to_rnti(31452), 144}, {38, 47, 56, 65, 2, 11, 20, 29}}, - {{aggregation_level::n2, 8, 72, to_coreset_id(7), to_rnti(40479), 137}, {22, 30, 40, 48, 58, 66, 4, 12}}, - {{aggregation_level::n4, 8, 72, to_coreset_id(9), to_rnti(37796), 29}, {48, 56, 64, 0, 12, 20, 28, 36}}, - {{aggregation_level::n8, 8, 72, to_coreset_id(3), to_rnti(58098), 4}, {0, 8, 16, 24, 32, 40, 48, 56}}, - {{aggregation_level::n1, 0, 96, to_coreset_id(6), to_rnti(11006), 156}, {}}, - {{aggregation_level::n1, 1, 96, to_coreset_id(8), to_rnti(32799), 75}, {18}}, - {{aggregation_level::n2, 1, 96, to_coreset_id(1), to_rnti(44694), 6}, {62}}, - {{aggregation_level::n4, 1, 96, to_coreset_id(1), to_rnti(34187), 15}, {92}}, - {{aggregation_level::n8, 1, 96, to_coreset_id(9), to_rnti(53578), 115}, {8}}, - {{aggregation_level::n16, 1, 96, to_coreset_id(2), to_rnti(43228), 82}, {48}}, - {{aggregation_level::n1, 2, 96, to_coreset_id(11), to_rnti(42532), 128}, {78, 30}}, - {{aggregation_level::n2, 2, 96, to_coreset_id(5), to_rnti(28337), 132}, {30, 78}}, - {{aggregation_level::n4, 2, 96, to_coreset_id(1), to_rnti(8728), 27}, {0, 48}}, - {{aggregation_level::n8, 2, 96, to_coreset_id(5), to_rnti(54485), 128}, {80, 32}}, - {{aggregation_level::n16, 2, 96, to_coreset_id(1), to_rnti(26166), 84}, {64, 16}}, - {{aggregation_level::n1, 3, 96, to_coreset_id(5), to_rnti(43048), 100}, {32, 64, 0}}, - {{aggregation_level::n2, 3, 96, to_coreset_id(4), to_rnti(28289), 2}, {14, 46, 78}}, - {{aggregation_level::n4, 3, 96, to_coreset_id(11), to_rnti(10956), 16}, {4, 36, 68}}, - {{aggregation_level::n8, 3, 96, to_coreset_id(5), to_rnti(12984), 78}, {88, 24, 56}}, - {{aggregation_level::n16, 3, 96, to_coreset_id(4), to_rnti(62366), 147}, {48, 80, 16}}, - {{aggregation_level::n1, 4, 96, to_coreset_id(1), to_rnti(48356), 43}, {51, 75, 3, 27}}, - {{aggregation_level::n2, 4, 96, to_coreset_id(5), to_rnti(35905), 150}, {62, 86, 14, 38}}, - {{aggregation_level::n4, 4, 96, to_coreset_id(5), to_rnti(64425), 48}, {44, 68, 92, 20}}, - {{aggregation_level::n8, 4, 96, to_coreset_id(8), to_rnti(43669), 86}, {0, 24, 48, 72}}, - {{aggregation_level::n16, 4, 96, to_coreset_id(8), to_rnti(43681), 28}, {80, 0, 32, 48}}, - {{aggregation_level::n1, 5, 96, to_coreset_id(2), to_rnti(65475), 27}, {22, 41, 60, 79, 2}}, - {{aggregation_level::n2, 5, 96, to_coreset_id(1), to_rnti(36779), 141}, {20, 38, 58, 76, 0}}, - {{aggregation_level::n4, 5, 96, to_coreset_id(8), to_rnti(12481), 59}, {68, 84, 8, 28, 48}}, - {{aggregation_level::n8, 5, 96, to_coreset_id(6), to_rnti(64332), 25}, {32, 48, 64, 88, 8}}, - {{aggregation_level::n16, 5, 96, to_coreset_id(10), to_rnti(42255), 60}, {16, 32, 48, 64, 80}}, - {{aggregation_level::n1, 6, 96, to_coreset_id(3), to_rnti(28066), 77}, {38, 54, 70, 86, 6, 22}}, - {{aggregation_level::n2, 6, 96, to_coreset_id(2), to_rnti(38634), 36}, {38, 54, 70, 86, 6, 22}}, - {{aggregation_level::n4, 6, 96, to_coreset_id(5), to_rnti(38207), 40}, {28, 44, 60, 76, 92, 12}}, - {{aggregation_level::n8, 6, 96, to_coreset_id(4), to_rnti(40442), 42}, {24, 40, 56, 72, 88, 8}}, - {{aggregation_level::n16, 6, 96, to_coreset_id(10), to_rnti(64399), 116}, {48, 64, 80, 0, 16, 32}}, - {{aggregation_level::n1, 7, 96, to_coreset_id(4), to_rnti(38277), 17}, {52, 65, 79, 93, 10, 24, 38}}, - {{aggregation_level::n2, 7, 96, to_coreset_id(10), to_rnti(57649), 130}, {60, 72, 86, 4, 18, 32, 46}}, - {{aggregation_level::n4, 7, 96, to_coreset_id(3), to_rnti(38952), 3}, {80, 92, 8, 24, 36, 52, 64}}, - {{aggregation_level::n8, 7, 96, to_coreset_id(5), to_rnti(20495), 25}, {80, 88, 8, 24, 32, 48, 64}}, - {{aggregation_level::n1, 8, 96, to_coreset_id(2), to_rnti(27714), 15}, {40, 52, 64, 76, 88, 4, 16, 28}}, - {{aggregation_level::n2, 8, 96, to_coreset_id(7), to_rnti(30863), 111}, {22, 34, 46, 58, 70, 82, 94, 10}}, - {{aggregation_level::n4, 8, 96, to_coreset_id(8), to_rnti(41847), 5}, {92, 8, 20, 32, 44, 56, 68, 80}}, - {{aggregation_level::n8, 8, 96, to_coreset_id(1), to_rnti(20945), 84}, {40, 48, 64, 72, 88, 0, 16, 24}}, - {{aggregation_level::n1, 0, 120, to_coreset_id(8), to_rnti(26714), 131}, {}}, - {{aggregation_level::n1, 1, 120, to_coreset_id(8), to_rnti(63481), 85}, {55}}, - {{aggregation_level::n2, 1, 120, to_coreset_id(4), to_rnti(6923), 97}, {94}}, - {{aggregation_level::n4, 1, 120, to_coreset_id(9), to_rnti(27751), 14}, {104}}, - {{aggregation_level::n8, 1, 120, to_coreset_id(3), to_rnti(10070), 44}, {40}}, - {{aggregation_level::n16, 1, 120, to_coreset_id(5), to_rnti(34547), 73}, {32}}, - {{aggregation_level::n1, 2, 120, to_coreset_id(10), to_rnti(33951), 150}, {82, 22}}, - {{aggregation_level::n2, 2, 120, to_coreset_id(8), to_rnti(62763), 38}, {62, 2}}, - {{aggregation_level::n4, 2, 120, to_coreset_id(8), to_rnti(18944), 107}, {4, 64}}, - {{aggregation_level::n8, 2, 120, to_coreset_id(8), to_rnti(4456), 40}, {72, 8}}, - {{aggregation_level::n16, 2, 120, to_coreset_id(3), to_rnti(43767), 135}, {80, 16}}, - {{aggregation_level::n1, 3, 120, to_coreset_id(4), to_rnti(51152), 108}, {41, 81, 1}}, - {{aggregation_level::n2, 3, 120, to_coreset_id(1), to_rnti(39464), 61}, {6, 46, 86}}, + {{aggregation_level::n1, 8, 72, to_coreset_id(6), to_rnti(31445), 144}, {58, 67, 4, 13, 22, 31, 40, 49}}, + {{aggregation_level::n2, 8, 72, to_coreset_id(7), to_rnti(40469), 137}, {14, 22, 32, 40, 50, 58, 68, 4}}, + {{aggregation_level::n4, 8, 72, to_coreset_id(9), to_rnti(37787), 29}, {4, 12, 20, 28, 40, 48, 56, 64}}, + {{aggregation_level::n8, 8, 72, to_coreset_id(3), to_rnti(58084), 4}, {16, 24, 32, 40, 48, 56, 64, 0}}, + {{aggregation_level::n1, 0, 96, to_coreset_id(6), to_rnti(11003), 156}, {}}, + {{aggregation_level::n1, 1, 96, to_coreset_id(8), to_rnti(32791), 75}, {70}}, + {{aggregation_level::n2, 1, 96, to_coreset_id(1), to_rnti(44683), 6}, {10}}, + {{aggregation_level::n4, 1, 96, to_coreset_id(1), to_rnti(34178), 15}, {60}}, + {{aggregation_level::n8, 1, 96, to_coreset_id(9), to_rnti(53565), 115}, {0}}, + {{aggregation_level::n16, 1, 96, to_coreset_id(2), to_rnti(43217), 82}, {80}}, + {{aggregation_level::n1, 2, 96, to_coreset_id(11), to_rnti(42522), 128}, {71, 23}}, + {{aggregation_level::n2, 2, 96, to_coreset_id(5), to_rnti(28330), 132}, {32, 80}}, + {{aggregation_level::n4, 2, 96, to_coreset_id(1), to_rnti(8726), 27}, {16, 64}}, + {{aggregation_level::n8, 2, 96, to_coreset_id(5), to_rnti(54472), 128}, {48, 0}}, + {{aggregation_level::n16, 2, 96, to_coreset_id(1), to_rnti(26159), 84}, {48, 0}}, + {{aggregation_level::n1, 3, 96, to_coreset_id(5), to_rnti(43037), 100}, {40, 72, 8}}, + {{aggregation_level::n2, 3, 96, to_coreset_id(4), to_rnti(28282), 2}, {20, 52, 84}}, + {{aggregation_level::n4, 3, 96, to_coreset_id(11), to_rnti(10953), 16}, {64, 0, 32}}, + {{aggregation_level::n8, 3, 96, to_coreset_id(5), to_rnti(12981), 78}, {32, 64, 0}}, + {{aggregation_level::n16, 3, 96, to_coreset_id(4), to_rnti(62350), 147}, {0, 32, 64}}, + {{aggregation_level::n1, 4, 96, to_coreset_id(1), to_rnti(48344), 43}, {90, 18, 42, 66}}, + {{aggregation_level::n2, 4, 96, to_coreset_id(5), to_rnti(35896), 150}, {68, 92, 20, 44}}, + {{aggregation_level::n4, 4, 96, to_coreset_id(5), to_rnti(64409), 48}, {72, 0, 24, 48}}, + {{aggregation_level::n8, 4, 96, to_coreset_id(8), to_rnti(43658), 86}, {8, 32, 56, 80}}, + {{aggregation_level::n16, 4, 96, to_coreset_id(8), to_rnti(43671), 28}, {32, 48, 80, 0}}, + {{aggregation_level::n1, 5, 96, to_coreset_id(2), to_rnti(65459), 27}, {14, 33, 52, 71, 90}}, + {{aggregation_level::n2, 5, 96, to_coreset_id(1), to_rnti(36770), 141}, {72, 90, 14, 32, 52}}, + {{aggregation_level::n4, 5, 96, to_coreset_id(8), to_rnti(12477), 59}, {72, 88, 12, 32, 52}}, + {{aggregation_level::n8, 5, 96, to_coreset_id(6), to_rnti(64316), 25}, {72, 88, 8, 32, 48}}, + {{aggregation_level::n16, 5, 96, to_coreset_id(10), to_rnti(42245), 60}, {16, 32, 48, 64, 80}}, + {{aggregation_level::n1, 6, 96, to_coreset_id(3), to_rnti(28059), 77}, {82, 2, 18, 34, 50, 66}}, + {{aggregation_level::n2, 6, 96, to_coreset_id(2), to_rnti(38624), 36}, {86, 6, 22, 38, 54, 70}}, + {{aggregation_level::n4, 6, 96, to_coreset_id(5), to_rnti(38197), 40}, {80, 0, 16, 32, 48, 64}}, + {{aggregation_level::n8, 6, 96, to_coreset_id(4), to_rnti(40432), 42}, {8, 24, 40, 56, 72, 88}}, + {{aggregation_level::n16, 6, 96, to_coreset_id(10), to_rnti(64384), 116}, {80, 0, 16, 32, 48, 64}}, + {{aggregation_level::n1, 7, 96, to_coreset_id(4), to_rnti(38268), 17}, {22, 35, 49, 63, 76, 90, 8}}, + {{aggregation_level::n2, 7, 96, to_coreset_id(10), to_rnti(57635), 130}, {82, 94, 12, 26, 40, 54, 68}}, + {{aggregation_level::n4, 7, 96, to_coreset_id(3), to_rnti(38942), 3}, {4, 16, 28, 44, 56, 72, 84}}, + {{aggregation_level::n8, 7, 96, to_coreset_id(5), to_rnti(20490), 25}, {32, 40, 56, 72, 80, 0, 16}}, + {{aggregation_level::n1, 8, 96, to_coreset_id(2), to_rnti(27708), 15}, {58, 70, 82, 94, 10, 22, 34, 46}}, + {{aggregation_level::n2, 8, 96, to_coreset_id(7), to_rnti(30855), 111}, {4, 16, 28, 40, 52, 64, 76, 88}}, + {{aggregation_level::n4, 8, 96, to_coreset_id(8), to_rnti(41836), 5}, {84, 0, 12, 24, 36, 48, 60, 72}}, + {{aggregation_level::n8, 8, 96, to_coreset_id(1), to_rnti(20940), 84}, {32, 40, 56, 64, 80, 88, 8, 16}}, + {{aggregation_level::n1, 0, 120, to_coreset_id(8), to_rnti(26707), 131}, {}}, + {{aggregation_level::n1, 1, 120, to_coreset_id(8), to_rnti(63465), 85}, {14}}, + {{aggregation_level::n2, 1, 120, to_coreset_id(4), to_rnti(6921), 97}, {118}}, + {{aggregation_level::n4, 1, 120, to_coreset_id(9), to_rnti(27745), 14}, {80}}, + {{aggregation_level::n8, 1, 120, to_coreset_id(3), to_rnti(10068), 44}, {32}}, + {{aggregation_level::n16, 1, 120, to_coreset_id(5), to_rnti(34538), 73}, {48}}, + {{aggregation_level::n1, 2, 120, to_coreset_id(10), to_rnti(33943), 150}, {88, 28}}, + {{aggregation_level::n2, 2, 120, to_coreset_id(8), to_rnti(62748), 38}, {30, 90}}, + {{aggregation_level::n4, 2, 120, to_coreset_id(8), to_rnti(18940), 107}, {72, 12}}, + {{aggregation_level::n8, 2, 120, to_coreset_id(8), to_rnti(4455), 40}, {48, 104}}, + {{aggregation_level::n16, 2, 120, to_coreset_id(3), to_rnti(43756), 135}, {16, 64}}, + {{aggregation_level::n1, 3, 120, to_coreset_id(4), to_rnti(51139), 108}, {68, 108, 28}}, + {{aggregation_level::n2, 3, 120, to_coreset_id(1), to_rnti(39454), 61}, {58, 98, 18}}, {{aggregation_level::n4, 3, 120, to_coreset_id(11), to_rnti(76), 73}, {112, 32, 72}}, - {{aggregation_level::n8, 3, 120, to_coreset_id(5), to_rnti(30207), 123}, {56, 96, 16}}, - {{aggregation_level::n16, 3, 120, to_coreset_id(4), to_rnti(51428), 75}, {64, 96, 32}}, - {{aggregation_level::n1, 4, 120, to_coreset_id(1), to_rnti(11526), 115}, {84, 114, 24, 54}}, - {{aggregation_level::n2, 4, 120, to_coreset_id(6), to_rnti(10009), 54}, {118, 28, 58, 88}}, - {{aggregation_level::n4, 4, 120, to_coreset_id(7), to_rnti(12567), 118}, {60, 88, 0, 28}}, - {{aggregation_level::n8, 4, 120, to_coreset_id(3), to_rnti(60124), 43}, {32, 56, 88, 0}}, - {{aggregation_level::n16, 4, 120, to_coreset_id(9), to_rnti(12364), 45}, {16, 32, 64, 96}}, - {{aggregation_level::n1, 5, 120, to_coreset_id(2), to_rnti(37762), 109}, {12, 36, 60, 84, 108}}, - {{aggregation_level::n2, 5, 120, to_coreset_id(7), to_rnti(27901), 103}, {6, 30, 54, 78, 102}}, - {{aggregation_level::n4, 5, 120, to_coreset_id(8), to_rnti(44500), 101}, {32, 56, 80, 104, 8}}, - {{aggregation_level::n8, 5, 120, to_coreset_id(11), to_rnti(13693), 113}, {8, 32, 56, 80, 104}}, - {{aggregation_level::n16, 5, 120, to_coreset_id(3), to_rnti(7825), 97}, {0, 16, 48, 64, 96}}, - {{aggregation_level::n1, 6, 120, to_coreset_id(5), to_rnti(30063), 105}, {15, 35, 55, 75, 95, 115}}, - {{aggregation_level::n2, 6, 120, to_coreset_id(9), to_rnti(22952), 105}, {88, 108, 8, 28, 48, 68}}, - {{aggregation_level::n4, 6, 120, to_coreset_id(5), to_rnti(55176), 133}, {48, 68, 88, 108, 8, 28}}, - {{aggregation_level::n8, 6, 120, to_coreset_id(3), to_rnti(40204), 93}, {40, 56, 80, 96, 0, 16}}, - {{aggregation_level::n16, 6, 120, to_coreset_id(6), to_rnti(57012), 42}, {80, 96, 0, 16, 48, 64}}, - {{aggregation_level::n1, 7, 120, to_coreset_id(4), to_rnti(7813), 150}, {28, 45, 62, 79, 96, 113, 10}}, - {{aggregation_level::n2, 7, 120, to_coreset_id(8), to_rnti(31422), 102}, {106, 2, 20, 36, 54, 70, 88}}, - {{aggregation_level::n4, 7, 120, to_coreset_id(6), to_rnti(42422), 87}, {32, 48, 64, 80, 100, 116, 12}}, - {{aggregation_level::n8, 7, 120, to_coreset_id(8), to_rnti(34242), 158}, {0, 16, 32, 48, 64, 80, 96}}, - {{aggregation_level::n16, 7, 120, to_coreset_id(3), to_rnti(6934), 17}, {64, 80, 96, 0, 16, 32, 48}}, - {{aggregation_level::n1, 8, 120, to_coreset_id(1), to_rnti(26515), 71}, {71, 86, 101, 116, 11, 26, 41, 56}}, - {{aggregation_level::n2, 8, 120, to_coreset_id(5), to_rnti(50037), 100}, {46, 60, 76, 90, 106, 0, 16, 30}}, - {{aggregation_level::n4, 8, 120, to_coreset_id(9), to_rnti(61135), 155}, {8, 20, 36, 52, 68, 80, 96, 112}}, - {{aggregation_level::n8, 8, 120, to_coreset_id(3), to_rnti(9102), 111}, {24, 32, 48, 64, 80, 96, 112, 8}}, - {{aggregation_level::n1, 0, 144, to_coreset_id(2), to_rnti(34433), 84}, {}}, - {{aggregation_level::n1, 1, 144, to_coreset_id(10), to_rnti(31775), 62}, {86}}, - {{aggregation_level::n2, 1, 144, to_coreset_id(8), to_rnti(48579), 83}, {116}}, - {{aggregation_level::n4, 1, 144, to_coreset_id(4), to_rnti(9831), 93}, {136}}, - {{aggregation_level::n8, 1, 144, to_coreset_id(3), to_rnti(2914), 120}, {56}}, - {{aggregation_level::n16, 1, 144, to_coreset_id(3), to_rnti(28993), 110}, {64}}, - {{aggregation_level::n1, 2, 144, to_coreset_id(4), to_rnti(48257), 63}, {61, 133}}, - {{aggregation_level::n2, 2, 144, to_coreset_id(8), to_rnti(46140), 70}, {16, 88}}, - {{aggregation_level::n4, 2, 144, to_coreset_id(1), to_rnti(21683), 67}, {104, 32}}, - {{aggregation_level::n8, 2, 144, to_coreset_id(3), to_rnti(12914), 131}, {32, 104}}, - {{aggregation_level::n16, 2, 144, to_coreset_id(5), to_rnti(58181), 62}, {128, 48}}, - {{aggregation_level::n1, 3, 144, to_coreset_id(9), to_rnti(26004), 129}, {51, 99, 3}}, - {{aggregation_level::n2, 3, 144, to_coreset_id(9), to_rnti(24733), 34}, {36, 84, 132}}, - {{aggregation_level::n4, 3, 144, to_coreset_id(9), to_rnti(62213), 52}, {124, 28, 76}}, - {{aggregation_level::n8, 3, 144, to_coreset_id(8), to_rnti(28747), 133}, {32, 80, 128}}, - {{aggregation_level::n16, 3, 144, to_coreset_id(9), to_rnti(10961), 137}, {0, 48, 96}}, - {{aggregation_level::n1, 4, 144, to_coreset_id(11), to_rnti(33713), 141}, {120, 12, 48, 84}}, - {{aggregation_level::n2, 4, 144, to_coreset_id(7), to_rnti(10142), 31}, {8, 44, 80, 116}}, - {{aggregation_level::n4, 4, 144, to_coreset_id(5), to_rnti(49067), 132}, {72, 108, 0, 36}}, - {{aggregation_level::n8, 4, 144, to_coreset_id(9), to_rnti(20875), 85}, {96, 128, 24, 56}}, - {{aggregation_level::n16, 4, 144, to_coreset_id(1), to_rnti(7321), 21}, {128, 16, 48, 80}}, - {{aggregation_level::n1, 5, 144, to_coreset_id(8), to_rnti(32452), 30}, {93, 121, 6, 35, 64}}, - {{aggregation_level::n2, 5, 144, to_coreset_id(6), to_rnti(9674), 8}, {96, 124, 8, 38, 66}}, - {{aggregation_level::n4, 5, 144, to_coreset_id(10), to_rnti(36737), 148}, {8, 36, 64, 92, 120}}, - {{aggregation_level::n8, 5, 144, to_coreset_id(8), to_rnti(38194), 130}, {32, 56, 88, 112, 0}}, - {{aggregation_level::n16, 5, 144, to_coreset_id(10), to_rnti(64809), 0}, {32, 48, 80, 112, 0}}, - {{aggregation_level::n1, 6, 144, to_coreset_id(10), to_rnti(40145), 158}, {80, 104, 128, 8, 32, 56}}, - {{aggregation_level::n2, 6, 144, to_coreset_id(6), to_rnti(31426), 128}, {28, 52, 76, 100, 124, 4}}, - {{aggregation_level::n4, 6, 144, to_coreset_id(3), to_rnti(32643), 144}, {112, 136, 16, 40, 64, 88}}, - {{aggregation_level::n8, 6, 144, to_coreset_id(7), to_rnti(55389), 118}, {128, 8, 32, 56, 80, 104}}, - {{aggregation_level::n16, 6, 144, to_coreset_id(7), to_rnti(16170), 106}, {128, 0, 32, 48, 80, 96}}, - {{aggregation_level::n1, 7, 144, to_coreset_id(1), to_rnti(41023), 105}, {72, 92, 113, 133, 10, 30, 51}}, - {{aggregation_level::n2, 7, 144, to_coreset_id(9), to_rnti(58376), 157}, {60, 80, 100, 120, 142, 18, 38}}, - {{aggregation_level::n4, 7, 144, to_coreset_id(9), to_rnti(38106), 148}, {60, 80, 100, 120, 140, 16, 36}}, + {{aggregation_level::n8, 3, 120, to_coreset_id(5), to_rnti(30199), 123}, {88, 8, 48}}, + {{aggregation_level::n16, 3, 120, to_coreset_id(4), to_rnti(51416), 75}, {0, 32, 80}}, + {{aggregation_level::n1, 4, 120, to_coreset_id(1), to_rnti(11524), 115}, {80, 110, 20, 50}}, + {{aggregation_level::n2, 4, 120, to_coreset_id(6), to_rnti(10007), 54}, {74, 104, 14, 44}}, + {{aggregation_level::n4, 4, 120, to_coreset_id(7), to_rnti(12563), 118}, {96, 4, 36, 64}}, + {{aggregation_level::n8, 4, 120, to_coreset_id(3), to_rnti(60109), 43}, {104, 8, 40, 72}}, + {{aggregation_level::n16, 4, 120, to_coreset_id(9), to_rnti(12361), 45}, {32, 48, 80, 0}}, + {{aggregation_level::n1, 5, 120, to_coreset_id(2), to_rnti(37753), 109}, {36, 60, 84, 108, 12}}, + {{aggregation_level::n2, 5, 120, to_coreset_id(7), to_rnti(27894), 103}, {76, 100, 4, 28, 52}}, + {{aggregation_level::n4, 5, 120, to_coreset_id(8), to_rnti(44489), 101}, {24, 48, 72, 96, 0}}, + {{aggregation_level::n8, 5, 120, to_coreset_id(11), to_rnti(13690), 113}, {112, 16, 40, 64, 88}}, + {{aggregation_level::n16, 5, 120, to_coreset_id(3), to_rnti(7823), 97}, {0, 16, 48, 64, 96}}, + {{aggregation_level::n1, 6, 120, to_coreset_id(5), to_rnti(30056), 105}, {5, 25, 45, 65, 85, 105}}, + {{aggregation_level::n2, 6, 120, to_coreset_id(9), to_rnti(22946), 105}, {106, 6, 26, 46, 66, 86}}, + {{aggregation_level::n4, 6, 120, to_coreset_id(5), to_rnti(55163), 133}, {88, 108, 8, 28, 48, 68}}, + {{aggregation_level::n8, 6, 120, to_coreset_id(3), to_rnti(40194), 93}, {56, 72, 96, 112, 16, 32}}, + {{aggregation_level::n16, 6, 120, to_coreset_id(6), to_rnti(56998), 42}, {80, 96, 0, 16, 48, 64}}, + {{aggregation_level::n1, 7, 120, to_coreset_id(4), to_rnti(7811), 150}, {68, 85, 102, 119, 16, 33, 50}}, + {{aggregation_level::n2, 7, 120, to_coreset_id(8), to_rnti(31414), 102}, {112, 8, 26, 42, 60, 76, 94}}, + {{aggregation_level::n4, 7, 120, to_coreset_id(6), to_rnti(42412), 87}, {112, 8, 24, 40, 60, 76, 92}}, + {{aggregation_level::n8, 7, 120, to_coreset_id(8), to_rnti(34234), 158}, {56, 72, 88, 104, 0, 16, 32}}, + {{aggregation_level::n16, 7, 120, to_coreset_id(3), to_rnti(6932), 17}, {80, 96, 0, 16, 32, 48, 64}}, + {{aggregation_level::n1, 8, 120, to_coreset_id(1), to_rnti(26508), 71}, {98, 113, 8, 23, 38, 53, 68, 83}}, + {{aggregation_level::n2, 8, 120, to_coreset_id(5), to_rnti(50025), 100}, {84, 98, 114, 8, 24, 38, 54, 68}}, + {{aggregation_level::n4, 8, 120, to_coreset_id(9), to_rnti(61120), 155}, {44, 56, 72, 88, 104, 116, 12, 28}}, + {{aggregation_level::n8, 8, 120, to_coreset_id(3), to_rnti(9099), 111}, {72, 80, 96, 112, 8, 24, 40, 56}}, + {{aggregation_level::n1, 0, 144, to_coreset_id(2), to_rnti(34424), 84}, {}}, + {{aggregation_level::n1, 1, 144, to_coreset_id(10), to_rnti(31768), 62}, {55}}, + {{aggregation_level::n2, 1, 144, to_coreset_id(8), to_rnti(48567), 83}, {68}}, + {{aggregation_level::n4, 1, 144, to_coreset_id(4), to_rnti(9828), 93}, {32}}, + {{aggregation_level::n8, 1, 144, to_coreset_id(3), to_rnti(2913), 120}, {128}}, + {{aggregation_level::n16, 1, 144, to_coreset_id(3), to_rnti(28986), 110}, {80}}, + {{aggregation_level::n1, 2, 144, to_coreset_id(4), to_rnti(48245), 63}, {126, 54}}, + {{aggregation_level::n2, 2, 144, to_coreset_id(8), to_rnti(46129), 70}, {94, 22}}, + {{aggregation_level::n4, 2, 144, to_coreset_id(1), to_rnti(21678), 67}, {116, 44}}, + {{aggregation_level::n8, 2, 144, to_coreset_id(3), to_rnti(12911), 131}, {72, 0}}, + {{aggregation_level::n16, 2, 144, to_coreset_id(5), to_rnti(58166), 62}, {64, 128}}, + {{aggregation_level::n1, 3, 144, to_coreset_id(9), to_rnti(25998), 129}, {15, 63, 111}}, + {{aggregation_level::n2, 3, 144, to_coreset_id(9), to_rnti(24727), 34}, {64, 112, 16}}, + {{aggregation_level::n4, 3, 144, to_coreset_id(9), to_rnti(62198), 52}, {72, 120, 24}}, + {{aggregation_level::n8, 3, 144, to_coreset_id(8), to_rnti(28740), 133}, {104, 8, 56}}, + {{aggregation_level::n16, 3, 144, to_coreset_id(9), to_rnti(10959), 137}, {80, 128, 32}}, + {{aggregation_level::n1, 4, 144, to_coreset_id(11), to_rnti(33705), 141}, {30, 66, 102, 138}}, + {{aggregation_level::n2, 4, 144, to_coreset_id(7), to_rnti(10140), 31}, {122, 14, 50, 86}}, + {{aggregation_level::n4, 4, 144, to_coreset_id(5), to_rnti(49055), 132}, {28, 64, 100, 136}}, + {{aggregation_level::n8, 4, 144, to_coreset_id(9), to_rnti(20870), 85}, {80, 112, 8, 40}}, + {{aggregation_level::n16, 4, 144, to_coreset_id(1), to_rnti(7319), 21}, {48, 80, 112, 0}}, + {{aggregation_level::n1, 5, 144, to_coreset_id(8), to_rnti(32444), 30}, {130, 14, 43, 72, 101}}, + {{aggregation_level::n2, 5, 144, to_coreset_id(6), to_rnti(9672), 8}, {4, 32, 60, 90, 118}}, + {{aggregation_level::n4, 5, 144, to_coreset_id(10), to_rnti(36728), 148}, {56, 84, 112, 140, 24}}, + {{aggregation_level::n8, 5, 144, to_coreset_id(8), to_rnti(38184), 130}, {56, 80, 112, 136, 24}}, + {{aggregation_level::n16, 5, 144, to_coreset_id(10), to_rnti(64793), 0}, {0, 16, 48, 80, 112}}, + {{aggregation_level::n1, 6, 144, to_coreset_id(10), to_rnti(40135), 158}, {65, 89, 113, 137, 17, 41}}, + {{aggregation_level::n2, 6, 144, to_coreset_id(6), to_rnti(31418), 128}, {14, 38, 62, 86, 110, 134}}, + {{aggregation_level::n4, 6, 144, to_coreset_id(3), to_rnti(32635), 144}, {0, 24, 48, 72, 96, 120}}, + {{aggregation_level::n8, 6, 144, to_coreset_id(7), to_rnti(55376), 118}, {112, 136, 16, 40, 64, 88}}, + {{aggregation_level::n16, 6, 144, to_coreset_id(7), to_rnti(16166), 106}, {64, 80, 112, 128, 16, 32}}, + {{aggregation_level::n1, 7, 144, to_coreset_id(1), to_rnti(41013), 105}, {31, 51, 72, 92, 113, 133, 10}}, + {{aggregation_level::n2, 7, 144, to_coreset_id(9), to_rnti(58362), 157}, {78, 98, 118, 138, 16, 36, 56}}, + {{aggregation_level::n4, 7, 144, to_coreset_id(9), to_rnti(38096), 148}, {80, 100, 120, 140, 16, 36, 56}}, {{aggregation_level::n8, 7, 144, to_coreset_id(7), to_rnti(1113), 19}, {128, 0, 24, 40, 64, 80, 104}}, - {{aggregation_level::n16, 7, 144, to_coreset_id(10), to_rnti(31739), 135}, {32, 48, 64, 80, 112, 128, 0}}, - {{aggregation_level::n1, 8, 144, to_coreset_id(3), to_rnti(36195), 100}, {55, 73, 91, 109, 127, 1, 19, 37}}, - {{aggregation_level::n2, 8, 144, to_coreset_id(1), to_rnti(40286), 57}, {90, 108, 126, 0, 18, 36, 54, 72}}, - {{aggregation_level::n4, 8, 144, to_coreset_id(1), to_rnti(32084), 30}, {4, 20, 40, 56, 76, 92, 112, 128}}, - {{aggregation_level::n8, 8, 144, to_coreset_id(2), to_rnti(13468), 23}, {16, 32, 48, 64, 88, 104, 120, 136}}, - {{aggregation_level::n16, 8, 144, to_coreset_id(3), to_rnti(2796), 101}, {112, 128, 0, 16, 32, 48, 64, 80}}, + {{aggregation_level::n16, 7, 144, to_coreset_id(10), to_rnti(31731), 135}, {64, 80, 96, 112, 0, 16, 32}}, + {{aggregation_level::n1, 8, 144, to_coreset_id(3), to_rnti(36186), 100}, {5, 23, 41, 59, 77, 95, 113, 131}}, + {{aggregation_level::n2, 8, 144, to_coreset_id(1), to_rnti(40276), 57}, {132, 6, 24, 42, 60, 78, 96, 114}}, + {{aggregation_level::n4, 8, 144, to_coreset_id(1), to_rnti(32077), 30}, {120, 136, 12, 28, 48, 64, 84, 100}}, + {{aggregation_level::n8, 8, 144, to_coreset_id(2), to_rnti(13464), 23}, {16, 32, 48, 64, 88, 104, 120, 136}}, + {{aggregation_level::n16, 8, 144, to_coreset_id(3), to_rnti(2795), 101}, {128, 0, 16, 32, 48, 64, 80, 96}}, // clang-format on }; diff --git a/tests/unittests/rlc/rlc_pdu_recycler_test.cpp b/tests/unittests/rlc/rlc_pdu_recycler_test.cpp index 77b123e3a8..84a8761e2e 100644 --- a/tests/unittests/rlc/rlc_pdu_recycler_test.cpp +++ b/tests/unittests/rlc/rlc_pdu_recycler_test.cpp @@ -75,7 +75,7 @@ TEST_F(rlc_pdu_recycler_test, recycler_memory_reserved) TEST_F(rlc_pdu_recycler_test, clear_by_executor) { byte_buffer pdu = create_sdu(1, 0xaa); - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu.deep_copy().value())); // Check the PDU is stored in first recycle bin std::array, 3>& recycle_bins = pdu_recycler->get_recycle_bins(); EXPECT_EQ(recycle_bins[2].size(), 0); @@ -104,7 +104,7 @@ TEST_F(rlc_pdu_recycler_test, clear_multiple_times) byte_buffer pdu2 = create_sdu(1, 0xbb); byte_buffer pdu3 = create_sdu(1, 0xcc); byte_buffer pdu4 = create_sdu(1, 0xdd); - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu1.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu1.deep_copy().value())); // Check the PDU is stored in first recycle bin std::array, 3>& recycle_bins = pdu_recycler->get_recycle_bins(); EXPECT_EQ(recycle_bins[2].size(), 0); @@ -120,7 +120,7 @@ TEST_F(rlc_pdu_recycler_test, clear_multiple_times) EXPECT_EQ(recycle_bins[0][0], pdu1); // Discard PDU2, check its stored in second recycle bin - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu2.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu2.deep_copy().value())); EXPECT_EQ(recycle_bins[2].size(), 0); ASSERT_EQ(recycle_bins[1].size(), 1); ASSERT_EQ(recycle_bins[0].size(), 1); @@ -140,7 +140,7 @@ TEST_F(rlc_pdu_recycler_test, clear_multiple_times) ASSERT_EQ(recycle_bins[0].size(), 0); // Discard PDU3, check its stored in third recycle bin - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu3.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu3.deep_copy().value())); ASSERT_EQ(recycle_bins[2].size(), 1); ASSERT_EQ(recycle_bins[1].size(), 1); EXPECT_EQ(recycle_bins[0].size(), 0); @@ -167,7 +167,7 @@ TEST_F(rlc_pdu_recycler_test, clear_multiple_times) } // We start again at first recycling bin - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu4.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu4.deep_copy().value())); // Check the PDU is stored in first recycle bin EXPECT_EQ(recycle_bins[2].size(), 0); EXPECT_EQ(recycle_bins[1].size(), 0); @@ -181,11 +181,11 @@ TEST_F(rlc_pdu_recycler_test, full_recycle_bin) byte_buffer pdu2 = create_sdu(1, 0xbb); byte_buffer pdu3 = create_sdu(1, 0xcc); - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu1.deep_copy())); - EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu2.deep_copy())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu1.deep_copy().value())); + EXPECT_TRUE(pdu_recycler->add_discarded_pdu(pdu2.deep_copy().value())); // Recycle bin is full - any extra PDU will be deleted on the spot and the function returns false - EXPECT_FALSE(pdu_recycler->add_discarded_pdu(pdu3.deep_copy())); + EXPECT_FALSE(pdu_recycler->add_discarded_pdu(pdu3.deep_copy().value())); // Check the PDUs are stored in first recycle bin std::array, 3>& recycle_bins = pdu_recycler->get_recycle_bins(); diff --git a/tests/unittests/rlc/rlc_rx_am_test.cpp b/tests/unittests/rlc/rlc_rx_am_test.cpp index d4663906bf..d3758d68f6 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -240,7 +240,7 @@ class rlc_rx_am_test : public ::testing::Test, // Push PDUs into RLC for (std::vector& pdu_buf : pdu_originals) { // write PDU into lower end - byte_buffer_slice pdu = {std::move(pdu_buf)}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_buf)).value(); rlc->handle_pdu(std::move(pdu)); if (not reverse_sdus) { @@ -323,7 +323,7 @@ class rlc_rx_am_test : public ::testing::Test, // Push PDUs into RLC for (std::list>& segment_list : pdu_originals) { for (std::vector& pdu_buf : segment_list) { - byte_buffer_slice pdu = {std::move(pdu_buf)}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_buf)).value(); rlc->handle_pdu(std::move(pdu)); } @@ -386,7 +386,7 @@ class rlc_rx_am_test : public ::testing::Test, uint32_t i = 0; for (const std::vector& pdu_buf : pdu_list_a) { if (i != skip_a1 && i != skip_a2) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -398,7 +398,7 @@ class rlc_rx_am_test : public ::testing::Test, // Push all PDUs again; check that nothing is forwarded to upper layer before except after Rx of 5th segment // Push B PDUs into RLC for (const std::vector& pdu_buf : pdu_list_b) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } ASSERT_EQ(tester->sdu_queue.size(), 1); @@ -494,7 +494,7 @@ TEST_P(rlc_rx_am_test, rx_valid_control_pdu) EXPECT_EQ(status.pack(pdu_buf), status.get_packed_size()); // Pass through RLC - byte_buffer_slice pdu = {std::move(pdu_buf)}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_buf)).value(); rlc->handle_pdu(std::move(pdu)); // Pick and verify the received status PDU on the other end @@ -521,7 +521,7 @@ TEST_P(rlc_rx_am_test, rx_invalid_control_pdu) *(pdu_buf.begin()) |= 0x70; // Push into RLC - byte_buffer_slice pdu = {std::move(pdu_buf)}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_buf)).value(); rlc->handle_pdu(std::move(pdu)); // Pick and verify the received status PDU on the other end @@ -604,7 +604,7 @@ TEST_P(rlc_rx_am_test, rx_polling_bit_sn_inside_rx_window) *(pdu_list.front().begin()) |= 0b01000000; // set P = 1; // Push into RLC - byte_buffer_slice pdu = {std::move(pdu_list.front())}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_list.front())).value(); rlc->handle_pdu(std::move(pdu)); // Check if polling bit of PDU was properly considered @@ -637,7 +637,7 @@ TEST_P(rlc_rx_am_test, rx_polling_bit_sn_outside_rx_window) *(pdu_list.front().begin()) |= 0b01000000; // set P = 1; // Push into RLC - byte_buffer_slice pdu = {std::move(pdu_list.front())}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_list.front())).value(); rlc->handle_pdu(std::move(pdu)); // Check if polling bit was considered, despite out-of-window SN @@ -664,7 +664,7 @@ TEST_P(rlc_rx_am_test, rx_polling_bit_sdu_duplicate) sn_state++; // Push into RLC - byte_buffer_slice pdu = {pdu_list.front()}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_list.front()).value(); rlc->handle_pdu(std::move(pdu)); // Check if polling bit has not changed @@ -681,7 +681,7 @@ TEST_P(rlc_rx_am_test, rx_polling_bit_sdu_duplicate) *(pdu_list.front().begin()) |= 0b01000000; // set P = 1; // Push into RLC - pdu = {pdu_list.front()}; + pdu = byte_buffer_slice::create(pdu_list.front()).value(); rlc->handle_pdu(std::move(pdu)); // Check if polling bit was considered, despite duplicate SN @@ -721,7 +721,7 @@ TEST_P(rlc_rx_am_test, rx_duplicate_segments) int i = 0; for (const std::vector& pdu_buf : pdu_list) { if (i != 5) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -733,7 +733,7 @@ TEST_P(rlc_rx_am_test, rx_duplicate_segments) // Push all PDUs again; check that nothing is forwarded to upper layer before except after Rx of 5th segment i = 0; for (const std::vector& pdu_buf : pdu_list) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); if (i == 5) { // check if SDU has been assembled correctly @@ -860,7 +860,7 @@ TEST_P(rlc_rx_am_test, status_prohibit_timer) *(pdu_list.front().begin()) |= 0b01000000; // set P = 1; // Push into RLC - byte_buffer_slice pdu = {std::move(pdu_list.front())}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_list.front())).value(); rlc->handle_pdu(std::move(pdu)); // Status report must not be required as long as status_prohibit_timer is running @@ -923,7 +923,7 @@ TEST_P(rlc_rx_am_test, reassembly_timer) int i = 0; for (const std::vector& pdu_buf : pdu_list) { if (i != 5) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -992,7 +992,7 @@ TEST_P(rlc_rx_am_test, when_rx_next_highest_equal_to_rx_next_reassembly_timer_tr } ASSERT_EQ(0, st.rx_next); if (i != 5) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -1042,7 +1042,7 @@ TEST_P(rlc_rx_am_test, when_rx_next_highest_larger_then_rx_next_reassembly_timer int i = 0; for (const auto& pdu_it : pdus) { if (i != 5) { - byte_buffer_slice pdu = {pdu_it.front()}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_it.front()).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -1087,7 +1087,7 @@ TEST_P(rlc_rx_am_test, when_rx_next_highest_equal_to_rx_next_but_no_byte_missing } ASSERT_EQ(0, st.rx_next); if (i != 9) { - byte_buffer_slice pdu = {pdu_buf}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_buf).value(); rlc->handle_pdu(std::move(pdu)); } i++; @@ -1136,7 +1136,7 @@ TEST_P(rlc_rx_am_test, status_report) uint32_t i = 0; for (std::vector& pdu_buf : pdu_list) { if (i != 4 && i != 6 && i != 7 && i != 9) { - byte_buffer_slice pdu = {std::move(pdu_buf)}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_buf)).value(); rlc->handle_pdu(std::move(pdu)); } else { missing_pdus.push_back(std::move(pdu_buf)); @@ -1155,7 +1155,7 @@ TEST_P(rlc_rx_am_test, status_report) // Push PDUs except for 4th, 6th and 7th into RLC if (sn_state != 4 && sn_state != 6 && sn_state != 7) { - byte_buffer_slice pdu = {std::move(pdu_list.front())}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_list.front())).value(); rlc->handle_pdu(std::move(pdu)); } else { missing_pdus.push_back(std::move(pdu_list.front())); @@ -1210,7 +1210,7 @@ TEST_P(rlc_rx_am_test, status_report) *(pdu_list.front().begin()) |= 0b01000000; // set P = 1; // Push into RLC - byte_buffer_slice pdu = {std::move(pdu_list.front())}; + byte_buffer_slice pdu = byte_buffer_slice::create(std::move(pdu_list.front())).value(); rlc->handle_pdu(std::move(pdu)); EXPECT_FALSE(rlc->status_report_required()); // status prohibit timer is not yet expired, regardless we read status @@ -1312,7 +1312,7 @@ TEST_P(rlc_rx_am_test_with_limit, status_report_large_window) ASSERT_NO_FATAL_FAILURE(create_pdus(pdu_list, sdu, sn_state, sdu_size, segment_size, sn_state)); // Push only first segment - byte_buffer_slice pdu = {pdu_list.front()}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_list.front()).value(); rlc->handle_pdu(std::move(pdu)); } @@ -1326,7 +1326,7 @@ TEST_P(rlc_rx_am_test_with_limit, status_report_large_window) ASSERT_NO_FATAL_FAILURE(create_pdus(pdu_list, sdu, sn_state, sdu_size, segment_size, sn_state)); // Push only first segment - byte_buffer_slice pdu = {pdu_list.front()}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_list.front()).value(); rlc->handle_pdu(std::move(pdu)); } @@ -1340,7 +1340,7 @@ TEST_P(rlc_rx_am_test_with_limit, status_report_large_window) ASSERT_NO_FATAL_FAILURE(create_pdus(pdu_list, sdu, sn_state, sdu_size, segment_size, sn_state)); // Push only first segment - byte_buffer_slice pdu = {pdu_list.front()}; + byte_buffer_slice pdu = byte_buffer_slice::create(pdu_list.front()).value(); rlc->handle_pdu(std::move(pdu)); } diff --git a/tests/unittests/rlc/rlc_rx_tm_test.cpp b/tests/unittests/rlc/rlc_rx_tm_test.cpp index 2d6a8a6a51..61af9ba4db 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -91,14 +91,14 @@ TEST_F(rlc_rx_am_test, test_rx) // write first PDU into lower end byte_buffer pdu_buf = create_sdu(sdu_size, count); - byte_buffer_slice pdu = {pdu_buf.deep_copy()}; + byte_buffer_slice pdu = {pdu_buf.deep_copy().value()}; rlc->handle_pdu(std::move(pdu)); count++; // write second PDU into lower end byte_buffer pdu_buf2 = create_sdu(sdu_size, count); - pdu = {pdu_buf2.deep_copy()}; + pdu = {pdu_buf2.deep_copy().value()}; rlc->handle_pdu(std::move(pdu)); // read first SDU from tester diff --git a/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp b/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp index dbb05329fc..bb0b8bad67 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp @@ -35,7 +35,7 @@ void queue_unqueue_test() rlc_sdu_queue_lockfree tx_queue(4096, logger); // Write 1 SDU - byte_buffer buf = {0x00, 0x01}; + byte_buffer buf = byte_buffer::create({0x00, 0x01}).value(); rlc_sdu write_sdu = {std::move(buf), 10}; TESTASSERT(tx_queue.write(std::move(write_sdu))); @@ -52,7 +52,7 @@ void queue_unqueue_test() TESTASSERT_EQ(0, tx_queue.size_bytes()); // Check SDU - byte_buffer expected_msg({0x00, 0x01}); + byte_buffer expected_msg = byte_buffer::create({0x00, 0x01}).value(); TESTASSERT(read_sdu.pdcp_sn.has_value()); TESTASSERT_EQ(10, read_sdu.pdcp_sn.value()); TESTASSERT(expected_msg == read_sdu.buf); diff --git a/tests/unittests/rlc/rlc_sdu_queue_test.cpp b/tests/unittests/rlc/rlc_sdu_queue_test.cpp index 3128543401..4e6f51e1af 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_test.cpp @@ -33,7 +33,7 @@ void queue_unqueue_test() rlc_sdu_queue tx_queue; // Write 1 SDU - byte_buffer buf = {0x00, 0x01}; + byte_buffer buf = byte_buffer::create({0x00, 0x01}).value(); rlc_sdu write_sdu = {std::move(buf), 10}; TESTASSERT(tx_queue.write(std::move(write_sdu))); @@ -50,7 +50,7 @@ void queue_unqueue_test() TESTASSERT_EQ(0, tx_queue.size_bytes()); // Check SDU - byte_buffer expected_msg({0x00, 0x01}); + byte_buffer expected_msg = byte_buffer::create({0x00, 0x01}).value(); TESTASSERT(read_sdu.pdcp_sn.has_value()); TESTASSERT_EQ(10, read_sdu.pdcp_sn.value()); TESTASSERT(expected_msg == read_sdu.buf); diff --git a/tests/unittests/rlc/rlc_tx_am_test.cpp b/tests/unittests/rlc/rlc_tx_am_test.cpp index dd49295468..d86470dcda 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -158,7 +158,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf sdu_bufs[i] = create_sdu(sdu_size, i); // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), /* pdcp_sn = */ i}; // no std::move - keep local copy for later comparison rlc->handle_sdu(std::move(sdu)); } @@ -177,7 +177,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf pdu_buf.resize(data_pdu_size); size_t pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - out_pdus[i] = byte_buffer_chain{byte_buffer{pdu_buf}}; + out_pdus[i] = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); // Check PDU size EXPECT_EQ(out_pdus[i].length(), data_pdu_size); @@ -225,7 +225,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf sdu_bufs[i] = create_sdu(sdu_size, i); // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), /* pdcp_sn = */ i}; // no std::move - keep local copy for later comparison rlc->handle_sdu(std::move(sdu)); } @@ -245,7 +245,7 @@ class rlc_tx_am_test : public ::testing::Test, public ::testing::WithParamInterf seg_buf.resize(pdu_size); size_t seg_len = rlc->pull_pdu(seg_buf); seg_buf.resize(seg_len); - out_pdus[i] = byte_buffer_chain{byte_buffer{seg_buf}}; + out_pdus[i] = byte_buffer_chain::create(byte_buffer::create(seg_buf).value()).value(); // Check PDU size EXPECT_GT(out_pdus[i].length(), header_size); @@ -328,8 +328,12 @@ TEST_P(rlc_tx_am_test, create_new_entity) TEST_P(rlc_tx_am_test, tx_without_segmentation) { - const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = 5; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, 1); tx_full_pdus(pdus, n_pdus, 5); @@ -347,7 +351,21 @@ TEST_P(rlc_tx_am_test, tx_small_grant_) const uint32_t so_size = 2; const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_segmented_pdus(pdus, n_pdus, pdu_size, n_sdus, sdu_size); tx_segmented_pdus(pdus, n_pdus, pdu_size, n_sdus, sdu_size); @@ -457,7 +475,7 @@ TEST_P(rlc_tx_am_test, sdu_discard) sdu_bufs[i] = create_sdu(sdu_size, i); // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), /* pdcp_sn = */ i}; // no std::move - keep local copy for later comparison rlc->handle_sdu(std::move(sdu)); } @@ -571,7 +589,7 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) sdu_bufs[i] = create_sdu(sdu_size, i); // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), /* pdcp_sn = */ (pdcp_sn_start + i) % pdcp_sn_mod}; // no std::move, keep copy for later comparison rlc->handle_sdu(std::move(sdu)); } @@ -672,9 +690,13 @@ TEST_P(rlc_tx_am_test, sdu_discard_with_pdcp_sn_wraparound) TEST_P(rlc_tx_am_test, invalid_status_report_ack_sn_larger_than_tx_next) { - const uint32_t sdu_size = 3; - const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + const uint32_t sdu_size = 3; + const uint32_t n_pdus = 5; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); @@ -698,7 +720,11 @@ TEST_P(rlc_tx_am_test, retx_pdu_without_segmentation) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -721,7 +747,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_without_segmentation) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_EQ(retx_pdu, pdus[nack.nack_sn]); @@ -749,7 +775,11 @@ TEST_P(rlc_tx_am_test, retx_pdu_with_segmentation) const uint32_t so_size = 2; const uint32_t header_max_size = header_min_size + so_size; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -770,13 +800,12 @@ TEST_P(rlc_tx_am_test, retx_pdu_with_segmentation) // Read ReTx in segments std::vector pdu_buf; size_t pdu_len; - byte_buffer_chain retx_pdu; for (uint32_t i = 0; i < sdu_size; i++) { uint32_t header_size = i == 0 ? header_min_size : header_max_size; pdu_buf.resize(1 + header_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - retx_pdu = byte_buffer_chain{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE( @@ -784,7 +813,8 @@ TEST_P(rlc_tx_am_test, retx_pdu_with_segmentation) EXPECT_EQ(tester->bsr_count, n_bsr); // Check SI - rlc_si_field si, si_expect; + rlc_si_field si; + rlc_si_field si_expect; si = static_cast((*retx_pdu.begin() >> 4) & 0b11); if (i == 0) { // first segment @@ -818,7 +848,11 @@ TEST_P(rlc_tx_am_test, retx_pdu_first_segment_without_segmentation) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -845,7 +879,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_first_segment_without_segmentation) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE( @@ -876,7 +910,13 @@ TEST_P(rlc_tx_am_test, retx_pdu_middle_segment_without_segmentation) const uint32_t so_size = 2; const uint32_t header_max_size = header_min_size + so_size; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -903,7 +943,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_middle_segment_without_segmentation) pdu_buf.resize(sdu_size + header_max_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE(std::equal(retx_pdu.begin() + header_max_size, @@ -935,7 +975,13 @@ TEST_P(rlc_tx_am_test, retx_pdu_last_segment_without_segmentation) const uint32_t so_size = 2; const uint32_t header_max_size = header_min_size + so_size; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -962,7 +1008,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_last_segment_without_segmentation) pdu_buf.resize(sdu_size + header_max_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE(std::equal(retx_pdu.begin() + header_max_size, @@ -994,11 +1040,24 @@ TEST_P(rlc_tx_am_test, retx_of_sn_under_segmentation_is_trimmed_to_already_sent_ const uint32_t n_splits = 3; - const uint32_t n_pdus = n_sdus * n_splits - 1; - const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); - const uint32_t so_size = 2; - const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = n_sdus * n_splits - 1; + const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); + const uint32_t so_size = 2; + const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; const uint32_t unsent_sdu_bytes = sdu_size / n_splits - so_size; // subtract 2 extra bytes from 1st segment (no SO) tx_segmented_pdus(pdus, n_pdus, pdu_size, n_sdus, sdu_size, unsent_sdu_bytes + header_size + so_size); @@ -1048,11 +1107,26 @@ TEST_P(rlc_tx_am_test, retx_of_sn_under_segmentation_is_ignored_for_unsent_bytes const uint32_t n_splits = 3; - const uint32_t n_pdus = n_sdus * n_splits - 1; - const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); - const uint32_t so_size = 2; - const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = n_sdus * n_splits - 1; + const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); + const uint32_t so_size = 2; + const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; const uint32_t unsent_sdu_bytes = sdu_size / n_splits - so_size; // subtract 2 extra bytes from 1st segment (no SO) tx_segmented_pdus(pdus, n_pdus, pdu_size, n_sdus, sdu_size, unsent_sdu_bytes + header_size + so_size); @@ -1112,11 +1186,26 @@ TEST_P(rlc_tx_am_test, retx_only_sent_bytes_of_sn_under_segmentation) const uint32_t n_splits = 3; - const uint32_t n_pdus = n_sdus * n_splits - 1; - const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); - const uint32_t so_size = 2; - const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = n_sdus * n_splits - 1; + const uint32_t header_size = (sn_size == rlc_am_sn_size::size12bits ? 2 : 3); + const uint32_t so_size = 2; + const uint32_t pdu_size = header_size + so_size + (sdu_size / n_splits); + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; const uint32_t unsent_sdu_bytes = sdu_size / n_splits - so_size; // subtract 2 extra bytes from 1st segment (no SO) tx_segmented_pdus(pdus, n_pdus, pdu_size, n_sdus, sdu_size, unsent_sdu_bytes + header_size + so_size); @@ -1161,7 +1250,13 @@ TEST_P(rlc_tx_am_test, retx_pdu_segment_invalid_so_start_and_so_end) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -1188,7 +1283,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_segment_invalid_so_start_and_so_end) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE( @@ -1217,7 +1312,13 @@ TEST_P(rlc_tx_am_test, retx_pdu_segment_invalid_so_start_larger_than_so_end) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -1244,7 +1345,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_segment_invalid_so_start_larger_than_so_end) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[nack.nack_sn].begin(), pdus[nack.nack_sn].end(), "pdus[{}]:", nack.nack_sn); EXPECT_TRUE( @@ -1268,9 +1369,22 @@ TEST_P(rlc_tx_am_test, retx_pdu_segment_invalid_so_start_larger_than_so_end) TEST_P(rlc_tx_am_test, invalid_nack_nack_sn_outside_rx_window) { - const uint32_t sdu_size = 3; - const uint32_t n_pdus = 12; - byte_buffer_chain pdus[n_pdus]; + const uint32_t sdu_size = 3; + const uint32_t n_pdus = 12; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); @@ -1320,9 +1434,22 @@ TEST_P(rlc_tx_am_test, invalid_nack_nack_sn_outside_rx_window) TEST_P(rlc_tx_am_test, invalid_nack_sn_larger_than_ack_sn) { - const uint32_t sdu_size = 3; - const uint32_t n_pdus = 12; - byte_buffer_chain pdus[n_pdus]; + const uint32_t sdu_size = 3; + const uint32_t n_pdus = 12; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; tx_full_pdus(pdus, n_pdus, sdu_size); @@ -1401,7 +1528,11 @@ TEST_P(rlc_tx_am_test, retx_insufficient_space) const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t short_size = header_min_size; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); EXPECT_EQ(rlc->get_buffer_state(), 0); @@ -1448,7 +1579,11 @@ TEST_P(rlc_tx_am_test, retx_pdu_range_without_segmentation) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; uint32_t sn_start = cardinality(to_number(sn_size)) - 2; uint32_t nack_sn = sn_start + 1; @@ -1486,7 +1621,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_range_without_segmentation) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[i - sn_start].begin(), pdus[i - sn_start].end(), "pdus[{}]:", i - sn_start); EXPECT_TRUE(std::equal(retx_pdu.begin() + 1, retx_pdu.end(), pdus[i - sn_start].begin() + 1)); // skip header P bit @@ -1512,7 +1647,11 @@ TEST_P(rlc_tx_am_test, retx_pdu_range_wraparound) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; uint32_t sn_start = cardinality(to_number(sn_size)) - 2; uint32_t nack_sn = sn_start + 1; @@ -1550,7 +1689,7 @@ TEST_P(rlc_tx_am_test, retx_pdu_range_wraparound) pdu_buf.resize(sdu_size + header_min_size); pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); - byte_buffer_chain retx_pdu{byte_buffer{pdu_buf}}; + byte_buffer_chain retx_pdu = byte_buffer_chain::create(byte_buffer::create(pdu_buf).value()).value(); logger.debug(retx_pdu.begin(), retx_pdu.end(), "retx_pdu:"); logger.debug(pdus[i - sn_start].begin(), pdus[i - sn_start].end(), "pdus[{}]:", i - sn_start); ASSERT_EQ(retx_pdu.length(), pdus[i - sn_start].length()); @@ -1712,8 +1851,12 @@ TEST_P(rlc_tx_am_test, status_report_trim) TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_triggers_retx) { - const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = 5; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; const uint32_t sdu_size = 10; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; @@ -1745,7 +1888,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_triggers_retx) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_TRUE(pdu_hdr.p); EXPECT_EQ(tester->bsr, pdu_size); EXPECT_EQ(tester->bsr_count, n_bsr); @@ -1760,7 +1904,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_triggers_retx) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_FALSE(pdu_hdr.p); EXPECT_EQ(tester->bsr, pdu_size); EXPECT_EQ(tester->bsr_count, n_bsr); @@ -1775,7 +1920,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_triggers_retx) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_TRUE(pdu_hdr.p); EXPECT_EQ(tester->bsr, pdu_size); EXPECT_EQ(tester->bsr_count, n_bsr); @@ -1784,8 +1930,14 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_triggers_retx) TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) { - const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = 5; + byte_buffer_chain pdus[n_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; const uint32_t sdu_size = 10; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; @@ -1796,7 +1948,7 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) // push SDU to SDU queue so that it is not empty uint32_t n_bsr = tester->bsr_count; byte_buffer sdu_buf = create_sdu(sdu_size, 7); - rlc_sdu sdu = {sdu_buf.deep_copy(), /* pdcp_sn = */ 7}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_buf.deep_copy().value(), /* pdcp_sn = */ 7}; // no std::move - keep local copy for later comparison rlc->handle_sdu(std::move(sdu)); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc->get_buffer_state(), pdu_size); @@ -1812,7 +1964,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_FALSE(pdu_hdr.p); } @@ -1839,7 +1992,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_TRUE(pdu_hdr.p); } @@ -1852,7 +2006,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_FALSE(pdu_hdr.p); } @@ -1865,15 +2020,20 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_timer_sets_polling_bit) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_TRUE(pdu_hdr.p); } } TEST_P(rlc_tx_am_test, expired_poll_retransmit_increments_retx_counter) { - const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + const uint32_t n_pdus = 5; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; const uint32_t sdu_size = 10; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; @@ -1910,7 +2070,8 @@ TEST_P(rlc_tx_am_test, expired_poll_retransmit_increments_retx_counter) pdu_len = rlc->pull_pdu(pdu_buf); pdu_buf.resize(pdu_len); rlc_am_pdu_header pdu_hdr = {}; - ASSERT_TRUE(rlc_am_read_data_pdu_header(byte_buffer(pdu_buf.begin(), pdu_buf.end()), sn_size, &pdu_hdr)); + ASSERT_TRUE( + rlc_am_read_data_pdu_header(byte_buffer::create(pdu_buf.begin(), pdu_buf.end()).value(), sn_size, &pdu_hdr)); EXPECT_TRUE(pdu_hdr.p); EXPECT_EQ(tester->bsr, pdu_size); EXPECT_EQ(tester->bsr_count, n_bsr); @@ -1926,7 +2087,11 @@ TEST_P(rlc_tx_am_test, retx_count_ignores_pending_retx) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; @@ -1963,7 +2128,11 @@ TEST_P(rlc_tx_am_test, retx_count_trigger_max_retx_without_segmentation) const uint32_t sdu_size = 3; const uint32_t header_min_size = sn_size == rlc_am_sn_size::size12bits ? 2 : 3; const uint32_t n_pdus = 5; - byte_buffer_chain pdus[n_pdus]; + byte_buffer_chain pdus[n_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; tx_full_pdus(pdus, n_pdus, sdu_size); uint32_t n_bsr = tester->bsr_count; diff --git a/tests/unittests/rlc/rlc_tx_tm_test.cpp b/tests/unittests/rlc/rlc_tx_tm_test.cpp index 41e1688ef3..781709968d 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -116,7 +116,8 @@ TEST_F(rlc_tx_tm_test, test_tx) EXPECT_EQ(rlc->get_buffer_state(), 0); byte_buffer sdu_buf = create_sdu(sdu_size, count); - rlc_sdu sdu = {sdu_buf.deep_copy(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_buf.deep_copy().value(), + /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison // write SDU into upper end rlc->handle_sdu(std::move(sdu)); @@ -125,12 +126,11 @@ TEST_F(rlc_tx_tm_test, test_tx) EXPECT_EQ(tester->bsr, sdu_size); EXPECT_EQ(tester->bsr_count, 1); - byte_buffer_chain pdu; - // read PDU from lower end std::vector tx_pdu(sdu_size); unsigned nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + byte_buffer_chain pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), sdu_size); EXPECT_EQ(pdu, sdu_buf); pcell_worker.run_pending_tasks(); @@ -141,7 +141,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // read another PDU from lower end but there is nothing to read tx_pdu.resize(sdu_size); nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), 0); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc->get_buffer_state(), 0); @@ -151,7 +151,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // write another SDU into upper end count++; sdu_buf = create_sdu(sdu_size, count); - sdu = {sdu_buf.deep_copy(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison + sdu = {sdu_buf.deep_copy().value(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison rlc->handle_sdu(std::move(sdu)); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc->get_buffer_state(), sdu_size); @@ -161,7 +161,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // read PDU from lower end with insufficient space for the whole SDU tx_pdu.resize(sdu_size - 1); nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), 0); pcell_worker.run_pending_tasks(); EXPECT_EQ(rlc->get_buffer_state(), sdu_size); @@ -171,7 +171,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // write another SDU into upper end count++; byte_buffer sdu_buf2 = create_sdu(sdu_size, count); - sdu = {sdu_buf2.deep_copy(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison + sdu = {sdu_buf2.deep_copy().value(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison // write SDU into upper end rlc->handle_sdu(std::move(sdu)); @@ -183,7 +183,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // read first PDU from lower end with oversized space tx_pdu.resize(3 * sdu_size); nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), sdu_size); EXPECT_EQ(pdu, sdu_buf); pcell_worker.run_pending_tasks(); @@ -194,7 +194,7 @@ TEST_F(rlc_tx_tm_test, test_tx) // read second PDU from lower end with oversized space tx_pdu.resize(3 * sdu_size); nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), sdu_size); EXPECT_EQ(pdu, sdu_buf2); pcell_worker.run_pending_tasks(); @@ -211,7 +211,8 @@ TEST_F(rlc_tx_tm_test, discard_sdu_increments_discard_failure_counter) EXPECT_EQ(rlc->get_buffer_state(), 0); byte_buffer sdu_buf = create_sdu(sdu_size, count); - rlc_sdu sdu = {sdu_buf.deep_copy(), /* pdcp_sn = */ count}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_buf.deep_copy().value(), + /* pdcp_sn = */ count}; // no std::move - keep local copy for later comparison // write SDU into upper end rlc->handle_sdu(std::move(sdu)); @@ -228,12 +229,11 @@ TEST_F(rlc_tx_tm_test, discard_sdu_increments_discard_failure_counter) EXPECT_EQ(rlc->get_metrics().num_discarded_sdus, 0); EXPECT_EQ(rlc->get_metrics().num_discard_failures, 1); - byte_buffer_chain pdu; - // read PDU from lower end std::vector tx_pdu(sdu_size); unsigned nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + byte_buffer_chain pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span(tx_pdu.data(), nwritten)).value()).value(); EXPECT_EQ(pdu.length(), sdu_size); EXPECT_EQ(pdu, sdu_buf); pcell_worker.run_pending_tasks(); @@ -250,7 +250,8 @@ TEST_F(rlc_tx_tm_test, test_tx_metrics) EXPECT_EQ(rlc->get_buffer_state(), 0); byte_buffer sdu_buf = create_sdu(sdu_size, count); - rlc_sdu sdu = {sdu_buf.deep_copy(), /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_buf.deep_copy().value(), + /* pdcp_sn = */ {}}; // no std::move - keep local copy for later comparison // write SDU into upper end rlc->handle_sdu(std::move(sdu)); @@ -260,10 +261,10 @@ TEST_F(rlc_tx_tm_test, test_tx_metrics) EXPECT_EQ(tester->bsr_count, 1); // read PDU from lower end - byte_buffer_chain pdu; std::vector tx_pdu(sdu_size - 1); unsigned nwritten = rlc->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + byte_buffer_chain pdu = + 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); diff --git a/tests/unittests/rlc/rlc_um_test.cpp b/tests/unittests/rlc/rlc_um_test.cpp index 6ae85b44a4..0d80cd3221 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -173,23 +173,33 @@ class rlc_um_test : public ::testing::Test, public ::testing::WithParamInterface } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } buffer_state = rlc1_tx_lower->get_buffer_state(); EXPECT_EQ(num_sdus * (sdu_size + 1), buffer_state); // Read PDUs from RLC1 with grant of 25 Bytes each - const uint32_t payload_len = 25; - const uint32_t max_num_pdus = 10; - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 25; + const uint32_t max_num_pdus = 10; + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; buffer_state = rlc1_tx_lower->get_buffer_state(); std::vector tx_pdu(payload_len); while (buffer_state > 0 && num_pdus < max_num_pdus) { - unsigned n = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu_bufs[num_pdus] = byte_buffer_slice{span{tx_pdu.data(), n}}; + unsigned n = rlc1_tx_lower->pull_pdu(tx_pdu); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), n}).value()).value(); if (pdu_bufs[num_pdus].empty()) { break; @@ -342,7 +352,7 @@ TEST_P(rlc_um_test, tx_without_segmentation) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i + 13}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i + 13}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -351,12 +361,17 @@ TEST_P(rlc_um_test, tx_without_segmentation) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 - byte_buffer_chain pdu_bufs[num_pdus]; - const int payload_len = 1 + sdu_size; // 1 bytes for header + payload + byte_buffer_chain pdu_bufs[num_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; + const int payload_len = 1 + sdu_size; // 1 bytes for header + payload std::vector tx_pdu(payload_len); for (uint32_t i = 0; i < num_pdus; i++) { unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu_bufs[i] = byte_buffer_slice{span{tx_pdu.data(), nwritten}}; + pdu_bufs[i] = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); EXPECT_EQ(payload_len, pdu_bufs[i].length()); EXPECT_EQ(i, pdu_bufs[i][payload_len - 1]); // check if last payload item corresponds with index @@ -411,7 +426,7 @@ TEST_P(rlc_um_test, tx_with_segmentation) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -420,15 +435,25 @@ TEST_P(rlc_um_test, tx_with_segmentation) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 with grant of 25 Bytes each - const uint32_t payload_len = 25; - const uint32_t max_num_pdus = 10; - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 25; + const uint32_t max_num_pdus = 10; + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; std::vector tx_pdu(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { - unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu_bufs[num_pdus] = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); if (num_pdus % ((sdu_size / payload_len) + 1) == 0) { // Verify transmit notification @@ -490,7 +515,7 @@ TEST_P(rlc_um_test, sdu_discard) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } @@ -532,7 +557,8 @@ TEST_P(rlc_um_test, sdu_discard) // Transmit full PDU std::vector tx_pdu(data_pdu_size); unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - byte_buffer_chain pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + byte_buffer_chain pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); EXPECT_FALSE(pdu.empty()); EXPECT_TRUE(std::equal(pdu.begin() + header_size, pdu.end(), sdu_bufs[1].begin())); expect_buffer_state = (num_sdus - 4) * data_pdu_size; @@ -554,7 +580,7 @@ TEST_P(rlc_um_test, sdu_discard) // Transmit full PDU tx_pdu.resize(data_pdu_size); nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); EXPECT_FALSE(pdu.empty()); EXPECT_TRUE(std::equal(pdu.begin() + header_size, pdu.end(), sdu_bufs[2].begin())); expect_buffer_state = (num_sdus - 5) * data_pdu_size; @@ -594,7 +620,7 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), /* pdcp_sn = */ (pdcp_sn_start + i) % pdcp_sn_mod}; // no std::move, keep copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } @@ -637,7 +663,8 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) // Transmit full PDU std::vector tx_pdu(data_pdu_size); unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - byte_buffer_chain pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + byte_buffer_chain pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); EXPECT_FALSE(pdu.empty()); EXPECT_TRUE(std::equal(pdu.begin() + header_size, pdu.end(), sdu_bufs[1].begin())); expect_buffer_state = (num_sdus - 4) * data_pdu_size; @@ -658,7 +685,7 @@ TEST_P(rlc_um_test, sdu_discard_with_pdcp_sn_wraparound) // Transmit full PDU nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + pdu = byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); EXPECT_FALSE(pdu.empty()); EXPECT_TRUE(std::equal(pdu.begin() + header_size, pdu.end(), sdu_bufs[2].begin())); expect_buffer_state = (num_sdus - 5) * data_pdu_size; @@ -695,7 +722,7 @@ TEST_P(rlc_um_test, tx_with_segmentation_reverse_rx) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -704,15 +731,25 @@ TEST_P(rlc_um_test, tx_with_segmentation_reverse_rx) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 with grant of 25 Bytes each - const uint32_t payload_len = 25; - const uint32_t max_num_pdus = 10; - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 25; + const uint32_t max_num_pdus = 10; + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = {byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value()}; std::vector tx_pdu(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { - unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu_bufs[num_pdus] = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); if (num_pdus % ((sdu_size / payload_len) + 1) == 0) { // Verify transmit notification @@ -775,7 +812,7 @@ TEST_P(rlc_um_test, tx_multiple_SDUs_with_segmentation) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -784,15 +821,24 @@ TEST_P(rlc_um_test, tx_multiple_SDUs_with_segmentation) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 with grant of 25 Bytes each - const uint32_t payload_len = 25; - const uint32_t max_num_pdus = 20; - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 25; + const uint32_t max_num_pdus = 20; + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = { + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + }; std::vector tx_pdu(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { - unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); - pdu_bufs[num_pdus] = byte_buffer_slice{span(tx_pdu.data(), nwritten)}; + unsigned nwritten = rlc1_tx_lower->pull_pdu(tx_pdu); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{tx_pdu.data(), nwritten}).value()).value(); if (pdu_bufs[num_pdus].empty()) { break; @@ -901,7 +947,8 @@ TEST_P(rlc_um_test, reassembly_window_wrap_around) std::vector pdu_tmp(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); - byte_buffer_chain tx_pdu = byte_buffer_slice{span(pdu_tmp.data(), nwritten)}; + byte_buffer_chain tx_pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span{pdu_tmp.data(), nwritten}).value()).value(); if (tx_pdu.empty()) { break; } @@ -964,7 +1011,8 @@ TEST_P(rlc_um_test, lost_PDU_outside_reassembly_window) std::vector pdu_tmp(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); - byte_buffer_chain tx_pdu = byte_buffer_slice{span(pdu_tmp.data(), nwritten)}; + byte_buffer_chain tx_pdu = + byte_buffer_chain::create(byte_buffer_slice::create(span{pdu_tmp.data(), nwritten}).value()).value(); if (tx_pdu.empty()) { break; } @@ -1027,7 +1075,7 @@ TEST_P(rlc_um_test, lost_segment_outside_reassembly_window) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -1036,15 +1084,24 @@ TEST_P(rlc_um_test, lost_segment_outside_reassembly_window) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 with grant of 8 Bytes each - const uint32_t payload_len = 8; - const uint32_t max_num_pdus = num_sdus * 2; // we need 2 PDUs for each SDU - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 8; + const uint32_t max_num_pdus = num_sdus * 2; // we need 2 PDUs for each SDU + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = { + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), byte_buffer_chain::create().value(), + }; std::vector pdu_tmp(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { - unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); - pdu_bufs[num_pdus] = byte_buffer_slice{span(pdu_tmp.data(), nwritten)}; + unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{pdu_tmp.data(), nwritten}).value()).value(); if (pdu_bufs[num_pdus].empty()) { break; @@ -1106,7 +1163,7 @@ TEST_P(rlc_um_test, out_of_order_segments_across_SDUs) } // write SDU into upper end - rlc_sdu sdu = {sdu_bufs[i].deep_copy(), i}; // no std::move - keep local copy for later comparison + rlc_sdu sdu = {sdu_bufs[i].deep_copy().value(), i}; // no std::move - keep local copy for later comparison rlc1_tx_upper->handle_sdu(std::move(sdu)); } pcell_worker.run_pending_tasks(); @@ -1115,15 +1172,27 @@ TEST_P(rlc_um_test, out_of_order_segments_across_SDUs) EXPECT_EQ(tester1.bsr_count, 1); // Read PDUs from RLC1 with grant smaller than SDU size - const uint32_t payload_len = 10; - const uint32_t max_num_pdus = 10; - uint32_t num_pdus = 0; - byte_buffer_chain pdu_bufs[max_num_pdus]; + const uint32_t payload_len = 10; + const uint32_t max_num_pdus = 10; + uint32_t num_pdus = 0; + byte_buffer_chain pdu_bufs[max_num_pdus] = { + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + byte_buffer_chain::create().value(), + }; std::vector pdu_tmp(payload_len); while (rlc1_tx_lower->get_buffer_state() > 0 && num_pdus < max_num_pdus) { - unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); - pdu_bufs[num_pdus] = byte_buffer_slice{span(pdu_tmp.data(), nwritten)}; + unsigned nwritten = rlc1_tx_lower->pull_pdu(pdu_tmp); + pdu_bufs[num_pdus] = + byte_buffer_chain::create(byte_buffer_slice::create(span{pdu_tmp.data(), nwritten}).value()).value(); if (pdu_bufs[num_pdus].empty()) { break; diff --git a/tests/unittests/rrc/rrc_ue_dl_info_transfer_proc_test.cpp b/tests/unittests/rrc/rrc_ue_dl_info_transfer_proc_test.cpp index 3a66bbaf3d..d29ded73d8 100644 --- a/tests/unittests/rrc/rrc_ue_dl_info_transfer_proc_test.cpp +++ b/tests/unittests/rrc/rrc_ue_dl_info_transfer_proc_test.cpp @@ -65,7 +65,7 @@ class rrc_ue_dl_info_transfer : public rrc_ue_test_helper, public ::testing::Tes /// Test the RRC setup with connected AMF TEST_F(rrc_ue_dl_info_transfer, when_srb2_missing_dl_info_tranfer_goes_over_srb1) { - send_dl_info_transfer({0x00, 0x01, 0x02, 0x03}); + send_dl_info_transfer(byte_buffer::create({0x00, 0x01, 0x02, 0x03}).value()); ASSERT_EQ(get_last_srb(), srb_id_t::srb1); } @@ -73,6 +73,6 @@ TEST_F(rrc_ue_dl_info_transfer, when_srb2_missing_dl_info_tranfer_goes_over_srb1 TEST_F(rrc_ue_dl_info_transfer, when_srb2_present_dl_info_tranfer_goes_over_srb2) { create_srb2(); - send_dl_info_transfer({0x00, 0x01, 0x02, 0x03}); + send_dl_info_transfer(byte_buffer::create({0x00, 0x01, 0x02, 0x03}).value()); ASSERT_EQ(get_last_srb(), srb_id_t::srb2); } diff --git a/tests/unittests/rrc/rrc_ue_test_helpers.h b/tests/unittests/rrc/rrc_ue_test_helpers.h index 1173bd83e7..37051e0b78 100644 --- a/tests/unittests/rrc/rrc_ue_test_helpers.h +++ b/tests/unittests/rrc/rrc_ue_test_helpers.h @@ -131,8 +131,9 @@ class rrc_ue_test_helper EXPECT_EQ(rrc_ue_f1ap_notifier.last_srb_id, srb_id_t::srb0); // Unpack received PDU - byte_buffer rx_pdu{rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()}; - asn1::cbit_ref bref(rx_pdu); + byte_buffer rx_pdu = + byte_buffer::create(rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()).value(); + asn1::cbit_ref bref(rx_pdu); asn1::rrc_nr::dl_ccch_msg_s dl_ccch; EXPECT_EQ(dl_ccch.unpack(bref), asn1::SRSASN_SUCCESS); return dl_ccch; @@ -157,7 +158,8 @@ class rrc_ue_test_helper EXPECT_GT(rrc_ue_f1ap_notifier.last_rrc_pdu.length(), 0); EXPECT_EQ(rrc_ue_f1ap_notifier.last_srb_id, srb_id_t::srb1); - return {rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()}; + return byte_buffer::create(rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()) + .value(); } byte_buffer get_srb2_pdu() @@ -166,7 +168,8 @@ class rrc_ue_test_helper EXPECT_GT(rrc_ue_f1ap_notifier.last_rrc_pdu.length(), 0); EXPECT_EQ(rrc_ue_f1ap_notifier.last_srb_id, srb_id_t::srb2); - return {rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()}; + return byte_buffer::create(rrc_ue_f1ap_notifier.last_rrc_pdu.begin(), rrc_ue_f1ap_notifier.last_rrc_pdu.end()) + .value(); } rrc_ue_init_security_context_handler* get_rrc_ue_security_handler() @@ -209,13 +212,14 @@ class rrc_ue_test_helper void receive_setup_request() { // inject RRC setup into UE object - rrc_ue->get_ul_ccch_pdu_handler().handle_ul_ccch_pdu(byte_buffer{rrc_setup_pdu}); + rrc_ue->get_ul_ccch_pdu_handler().handle_ul_ccch_pdu(byte_buffer::create(rrc_setup_pdu).value()); } void receive_invalid_setup_request() { // inject corrupted RRC setup into UE object - rrc_ue->get_ul_ccch_pdu_handler().handle_ul_ccch_pdu(byte_buffer{{0x9d, 0xec, 0x89, 0xde, 0x57, 0x66}}); + rrc_ue->get_ul_ccch_pdu_handler().handle_ul_ccch_pdu( + byte_buffer::create({0x9d, 0xec, 0x89, 0xde, 0x57, 0x66}).value()); } void receive_invalid_reestablishment_request(pci_t pci, rnti_t c_rnti) @@ -240,19 +244,22 @@ class rrc_ue_test_helper void receive_reestablishment_complete() { // inject RRC Reestablishment complete - rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, byte_buffer{rrc_reest_complete_pdu}); + rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, + byte_buffer::create(rrc_reest_complete_pdu).value()); } void receive_setup_complete() { // inject RRC setup complete - rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, byte_buffer{rrc_setup_complete_pdu}); + rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, + byte_buffer::create(rrc_setup_complete_pdu).value()); } void receive_corrupted_setup_complete() { // inject corrupted RRC setup complete - rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, byte_buffer{corrupted_rrc_setup_complete_pdu}); + rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, + byte_buffer::create(corrupted_rrc_setup_complete_pdu).value()); } void send_dl_info_transfer(byte_buffer nas_pdu) @@ -296,23 +303,24 @@ class rrc_ue_test_helper void receive_smc_complete() { // inject RRC SMC complete into UE object - rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, byte_buffer{rrc_smc_complete_pdu}); + rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, + byte_buffer::create(rrc_smc_complete_pdu).value()); } - void check_smc_pdu() { ASSERT_EQ(rrc_ue_f1ap_notifier.last_rrc_pdu, byte_buffer{rrc_smc_pdu}); } + void check_smc_pdu() { ASSERT_EQ(rrc_ue_f1ap_notifier.last_rrc_pdu, byte_buffer::create(rrc_smc_pdu).value()); } void check_initial_ue_message_sent() const { ASSERT_TRUE(rrc_ue_ngap_notifier.initial_ue_msg_received); } void check_rrc_ue_enquiry_pdu(uint8_t transaction_id) { - byte_buffer dl_dcch_msg_pdu(span{rrc_ue_capability_enquiry_pdu}); + byte_buffer dl_dcch_msg_pdu = byte_buffer::create(span{rrc_ue_capability_enquiry_pdu}).value(); ASSERT_EQ(rrc_ue_f1ap_notifier.last_rrc_pdu, byte_buffer_slice{dl_dcch_msg_pdu}); } void receive_ue_capability_information(uint8_t transaction_id) { - byte_buffer ul_dcch_msg_pdu(span{rrc_ue_capability_information_pdu}); + byte_buffer ul_dcch_msg_pdu = byte_buffer::create(span{rrc_ue_capability_information_pdu}).value(); // inject RRC UE capability information into UE object rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, std::move(ul_dcch_msg_pdu)); @@ -323,7 +331,8 @@ class rrc_ue_test_helper void receive_reconfig_complete() { // inject RRC Reconfiguration complete into UE object - rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, byte_buffer{rrc_reconfig_complete_pdu}); + rrc_ue->get_ul_dcch_pdu_handler().handle_ul_dcch_pdu(srb_id_t::srb1, + byte_buffer::create(rrc_reconfig_complete_pdu).value()); } void add_ue_reestablishment_context(ue_index_t ue_index) diff --git a/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp b/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp index 542b61f68c..e64105a393 100644 --- a/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp +++ b/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp @@ -24,7 +24,7 @@ #include "lib/scheduler/pdcch_scheduling/pdcch_resource_allocator_impl.h" #include "lib/scheduler/scheduler_impl.h" #include "lib/scheduler/ue_scheduling/ue_cell_grid_allocator.h" -#include "lib/scheduler/ue_scheduling/ue_srb0_scheduler.h" +#include "lib/scheduler/ue_scheduling/ue_fallback_scheduler.h" #include "tests/unittests/scheduler/test_utils/config_generators.h" #include "tests/unittests/scheduler/test_utils/scheduler_test_suite.h" #include "srsran/ran/duplex_mode.h" diff --git a/tests/unittests/scheduler/multiple_ue_sched_test.cpp b/tests/unittests/scheduler/multiple_ue_sched_test.cpp index d143bd42e6..bee31110d7 100644 --- a/tests/unittests/scheduler/multiple_ue_sched_test.cpp +++ b/tests/unittests/scheduler/multiple_ue_sched_test.cpp @@ -22,7 +22,7 @@ #include "lib/scheduler/scheduler_impl.h" #include "lib/scheduler/ue_scheduling/ue_cell_grid_allocator.h" -#include "lib/scheduler/ue_scheduling/ue_srb0_scheduler.h" +#include "lib/scheduler/ue_scheduling/ue_fallback_scheduler.h" #include "test_utils/dummy_test_components.h" #include "tests/unittests/scheduler/test_utils/config_generators.h" #include "tests/unittests/scheduler/test_utils/scheduler_test_suite.h" diff --git a/tests/unittests/scheduler/scheduler_retx_test.cpp b/tests/unittests/scheduler/scheduler_retx_test.cpp index 97748351d7..f694f291ab 100644 --- a/tests/unittests/scheduler/scheduler_retx_test.cpp +++ b/tests/unittests/scheduler/scheduler_retx_test.cpp @@ -178,7 +178,7 @@ TEST_F(scheduler_missing_ack_tester, when_no_harq_ack_arrives_then_harq_eventual ASSERT_NE(pdcch, nullptr) << "Failed to allocate DL HARQ newtxs"; } - // Set buffer state to zero, so that no newtxs get allocated once the current harqs become empty. + // Set buffer state to zero, so that no newtxs get allocated once the current latest_harq_states become empty. srslog::fetch_basic_logger("TEST").info("-- Setting DL BS=0, which will stop new DL grants --"); bench.push_dl_buffer_state(dl_buffer_state_indication_message{ue_create_req.ue_index, LCID_SRB1, 0}); bench.run_slot(to_du_cell_index(0)); @@ -222,7 +222,7 @@ TEST_F(scheduler_missing_ack_tester, when_no_crc_arrives_then_ul_harq_eventually ASSERT_NE(pdcch, nullptr) << "Failed to allocate UL HARQ newtxs"; } - // Set buffer state to zero, so that no newtxs get allocated once the current harqs become empty. + // Set buffer state to zero, so that no newtxs get allocated once the current latest_harq_states become empty. srslog::fetch_basic_logger("TEST").info("-- Setting BSR=0, which will stop new UL grants --"); bsr.reported_lcgs[0].nof_bytes = 0; bench.push_bsr(bsr); diff --git a/tests/unittests/scheduler/scheduler_ue_removal_test.cpp b/tests/unittests/scheduler/scheduler_ue_removal_test.cpp index c183df7b44..93650f169d 100644 --- a/tests/unittests/scheduler/scheduler_ue_removal_test.cpp +++ b/tests/unittests/scheduler/scheduler_ue_removal_test.cpp @@ -23,6 +23,7 @@ /// \file /// \brief In this file, we test the correct behaviour of the scheduler when removing UEs. +#include "lib/scheduler/cell/resource_grid_util.h" #include "test_utils/config_generators.h" #include "test_utils/result_test_helpers.h" #include "test_utils/scheduler_test_bench.h" @@ -30,6 +31,8 @@ using namespace srsran; +const unsigned MAX_UCI_SLOT_DELAY = get_max_slot_ul_alloc_delay(0); + // Setup the log spy to intercept error and warning log entries when removing a UE. srsran::log_sink_spy& test_spy = []() -> srsran::log_sink_spy& { if (!srslog::install_custom_sink( @@ -60,10 +63,31 @@ class sched_ue_removal_test : public scheduler_test_bench, public ::testing::Tes scheduler_test_bench::add_ue(ue_cfg, true); } + bool is_rnti_scheduled(rnti_t rnti) const + { + if (srsran::find_ue_dl_pdcch(rnti, *last_sched_res_list[0]) != nullptr) { + return true; + } + if (srsran::find_ue_ul_pdcch(rnti, *last_sched_res_list[0]) != nullptr) { + return true; + } + if (find_ue_pdsch(rnti, *last_sched_res_list[0]) != nullptr) { + return true; + } + if (find_ue_pucch(rnti, *last_sched_res_list[0]) != nullptr) { + return true; + } + if (find_ue_pusch(rnti, *last_sched_res_list[0]) != nullptr) { + return true; + } + return false; + } + static const lcid_t test_lcid_drb = LCID_MIN_DRB; }; -TEST_F(sched_ue_removal_test, when_ue_has_no_pending_txs_then_ue_removal_is_immediate) +TEST_F(sched_ue_removal_test, + when_ue_has_no_pending_txs_then_ue_removal_waits_for_all_pending_csi_and_sr_to_be_scheduled) { // Create UE. du_ue_index_t ue_index = (du_ue_index_t)test_rgen::uniform_int(0, MAX_DU_UE_INDEX); @@ -71,14 +95,27 @@ TEST_F(sched_ue_removal_test, when_ue_has_no_pending_txs_then_ue_removal_is_imme add_ue(ue_index, rnti); ASSERT_FALSE(notif.last_ue_index_deleted.has_value()); - // Remove UE. + // Schedule UE removal. rem_ue(ue_index); - const unsigned REM_TIMEOUT = 1; - for (unsigned i = 0; not notif.last_ue_index_deleted.has_value() and i != REM_TIMEOUT; ++i) { + // All pending UCI for this UE should be scheduled within this window. + for (unsigned i = 0; i != MAX_UCI_SLOT_DELAY; ++i) { run_slot(); + ASSERT_FALSE(notif.last_ue_index_deleted.has_value()); } + + // UE is finally removed. + run_slot(); + ASSERT_TRUE(notif.last_ue_index_deleted.has_value()); ASSERT_TRUE(notif.last_ue_index_deleted == ue_index); + ASSERT_FALSE(this->is_rnti_scheduled(rnti)); + + // No more allocations for this UE are possible. + const unsigned MAX_COUNT = 100; + for (unsigned i = 0; i != MAX_COUNT; ++i) { + run_slot(); + ASSERT_FALSE(this->is_rnti_scheduled(rnti)); + } } TEST_F(sched_ue_removal_test, when_ue_has_pending_harqs_then_scheduler_waits_for_harq_clear_before_deleting_ue) @@ -104,6 +141,7 @@ TEST_F(sched_ue_removal_test, when_ue_has_pending_harqs_then_scheduler_waits_for ASSERT_NE(alloc, nullptr); // Schedule UE removal. + slot_point rem_slot = next_slot; rem_ue(ue_index); // Wait for the right slot for ACK. @@ -137,12 +175,22 @@ TEST_F(sched_ue_removal_test, when_ue_has_pending_harqs_then_scheduler_waits_for } this->sched->handle_uci_indication(uci); - // The UE should be removed at this point. - const unsigned REM_TIMEOUT = 1; + // Wait for all pendign UCI PDUs to be sent to the PHY. + const unsigned REM_TIMEOUT = MAX_UCI_SLOT_DELAY - (next_slot - rem_slot) + 1; for (unsigned i = 0; not notif.last_ue_index_deleted.has_value() and i != REM_TIMEOUT; ++i) { run_slot(); } + + // The UE should be removed at this point. ASSERT_EQ(notif.last_ue_index_deleted, ue_index); + ASSERT_FALSE(this->is_rnti_scheduled(rnti)); + + // No more allocations for this RNTI are possible. + const unsigned MAX_COUNT = 100; + for (unsigned i = 0; i != MAX_COUNT; ++i) { + run_slot(); + ASSERT_FALSE(this->is_rnti_scheduled(rnti)); + } } TEST_F(sched_ue_removal_test, when_ue_is_removed_then_any_pending_uci_does_not_cause_log_warnings) @@ -157,10 +205,11 @@ TEST_F(sched_ue_removal_test, when_ue_is_removed_then_any_pending_uci_does_not_c // Remove UE. rem_ue(ue_index); - const unsigned REM_TIMEOUT = 1; - for (unsigned i = 0; not notif.last_ue_index_deleted.has_value() and i != REM_TIMEOUT; ++i) { + for (unsigned i = 0; i != MAX_UCI_SLOT_DELAY; ++i) { run_slot(); + ASSERT_FALSE(notif.last_ue_index_deleted.has_value()); } + run_slot(); ASSERT_TRUE(notif.last_ue_index_deleted == ue_index); // CSI arrives to Scheduler for the removed UE. diff --git a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp index a29ad28ac8..57d41fbafe 100644 --- a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp +++ b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp @@ -55,7 +55,8 @@ class dl_mcs_tbs_calculator_test_bench : public ::testing::TestWithParam test = - compute_dl_mcs_tbs(pdsch_cfg, ue_cell_cfg, sch_mcs_index(test_entry.max_mcs), test_entry.nof_prbs, false); + compute_dl_mcs_tbs(pdsch_cfg, sch_mcs_index(test_entry.max_mcs), test_entry.nof_prbs, false); ASSERT_TRUE(test.has_value()); ASSERT_EQ(GetParam().final_mcs, test.value().mcs); diff --git a/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp index bffd1e9cf2..8436ed4fbf 100644 --- a/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp +++ b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp @@ -126,6 +126,11 @@ void srsran::assert_pdcch_pdsch_common_consistency(const cell_configuration& c N_rb_dl_bwp = pdcch.dci.tc_rnti_f1_0.N_rb_dl_bwp; TESTASSERT_EQ(N_rb_dl_bwp, cs_zero_crbs.length()); } break; + case dci_dl_rnti_config_type::c_rnti_f1_0: { + time_assignment = pdcch.dci.c_rnti_f1_0.time_resource; + freq_assignment = pdcch.dci.c_rnti_f1_0.frequency_resource; + N_rb_dl_bwp = cs_zero_crbs.length(); + } break; case dci_dl_rnti_config_type::p_rnti_f1_0: { time_assignment = pdcch.dci.p_rnti_f1_0.time_resource; freq_assignment = pdcch.dci.p_rnti_f1_0.frequency_resource; @@ -168,6 +173,16 @@ void srsran::assert_pdcch_pdsch_common_consistency(const cell_configuration& TESTASSERT(it != rars.end()); linked_pdsch = &it->pdsch_cfg; } break; + case dci_dl_rnti_config_type::c_rnti_f1_0: { + uint8_t k0 = + cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdcch.dci.c_rnti_f1_0.time_resource].k0; + const auto& ue_grants = cell_res_grid[k0].result.dl.ue_grants; + auto it = std::find_if(ue_grants.begin(), ue_grants.end(), [&pdcch](const auto& grant) { + return grant.pdsch_cfg.rnti == pdcch.ctx.rnti; + }); + TESTASSERT(it != ue_grants.end()); + linked_pdsch = &it->pdsch_cfg; + } break; case dci_dl_rnti_config_type::tc_rnti_f1_0: { uint8_t k0 = cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdcch.dci.tc_rnti_f1_0.time_resource] diff --git a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_common_harq_test.cpp b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_common_harq_test.cpp index a39b1bffe6..2007412bef 100644 --- a/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_common_harq_test.cpp +++ b/tests/unittests/scheduler/uci_and_pucch/pucch_alloc_common_harq_test.cpp @@ -265,20 +265,22 @@ TEST_F(test_pucch_harq_common_multiple_allocation, test_pucch_double_alloc) t_bench.res_grid, t_bench.get_main_ue().crnti, t_bench.k0, t_bench.k1, t_bench.dci_info); ASSERT_TRUE(pucch_res_indicator.has_value()); - // If we allocate the same UE twice, the scheduler is expected to allocate a different PUCCH common resource. + // If we allocate the same UE twice, the scheduler is expected to fail, as we don't support PUCCH multiplexing on + // PUCCH common resources. optional pucch_res_indicator_1 = t_bench.pucch_alloc.alloc_common_pucch_harq_ack_ue( t_bench.res_grid, t_bench.get_main_ue().crnti, t_bench.k0, t_bench.k1, t_bench.dci_info); - ASSERT_TRUE(pucch_res_indicator_1.has_value()); - ASSERT_NE(pucch_res_indicator_1.value(), pucch_res_indicator.value()); + ASSERT_FALSE(pucch_res_indicator_1.has_value()); } TEST_F(test_pucch_harq_common_multiple_allocation, test_pucch_out_of_resources) { // For this specific n_cce value (1) and for d_pri = {0,...,7}, we get 8 r_pucch values. This is the maximum number of // UEs we can allocate. - for (unsigned n_ue = 0; n_ue != 8; ++n_ue) { + for (uint16_t n_ue = 0; n_ue != 8; ++n_ue) { + t_bench.add_ue(); + du_ue_index_t ue_idx = to_du_ue_index(static_cast(t_bench.get_main_ue().ue_index) + n_ue); const optional pucch_res_indicator = t_bench.pucch_alloc.alloc_common_pucch_harq_ack_ue( - t_bench.res_grid, t_bench.get_main_ue().crnti, t_bench.k0, t_bench.k1, t_bench.dci_info); + t_bench.res_grid, t_bench.get_ue(ue_idx).crnti, t_bench.k0, t_bench.k1, t_bench.dci_info); ASSERT_TRUE(pucch_res_indicator.has_value()); } diff --git a/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt b/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt index 9a8ed973de..9ee5279bf5 100644 --- a/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt +++ b/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt @@ -22,7 +22,7 @@ add_executable(ue_scheduler_test logical_channel_test.cpp harq_entity_test.cpp harq_process_test.cpp - srb0_scheduler_test.cpp + fallback_scheduler_test.cpp ue_configuration_test.cpp ue_grid_allocator_test.cpp ul_logical_channel_test.cpp diff --git a/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp new file mode 100644 index 0000000000..b58b899e0f --- /dev/null +++ b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp @@ -0,0 +1,1024 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "lib/scheduler/common_scheduling/csi_rs_scheduler.h" +#include "lib/scheduler/config/sched_config_manager.h" +#include "lib/scheduler/logging/scheduler_result_logger.h" +#include "lib/scheduler/pdcch_scheduling/pdcch_resource_allocator_impl.h" +#include "lib/scheduler/pucch_scheduling/pucch_allocator_impl.h" +#include "lib/scheduler/support/csi_rs_helpers.h" +#include "lib/scheduler/uci_scheduling/uci_allocator_impl.h" +#include "lib/scheduler/ue_scheduling/ue_cell_grid_allocator.h" +#include "lib/scheduler/ue_scheduling/ue_fallback_scheduler.h" +#include "tests/unittests/scheduler/test_utils/config_generators.h" +#include "tests/unittests/scheduler/test_utils/dummy_test_components.h" +#include "tests/unittests/scheduler/test_utils/scheduler_test_suite.h" +#include "srsran/ran/duplex_mode.h" +#include +#include + +using namespace srsran; + +std::random_device rd; +std::mt19937 g(rd()); + +unsigned get_random_uint(unsigned min, unsigned max) +{ + return std::uniform_int_distribution{min, max}(g); +} + +static cell_config_builder_params test_builder_params(duplex_mode duplx_mode) +{ + cell_config_builder_params builder_params{}; + if (duplx_mode == duplex_mode::TDD) { + // Band 40. + builder_params.dl_arfcn = 474000; + builder_params.scs_common = srsran::subcarrier_spacing::kHz30; + builder_params.band = band_helper::get_band_from_dl_arfcn(builder_params.dl_arfcn); + builder_params.channel_bw_mhz = bs_channel_bandwidth_fr1::MHz20; + + const unsigned nof_crbs = band_helper::get_n_rbs_from_bw( + builder_params.channel_bw_mhz, + builder_params.scs_common, + builder_params.band.has_value() ? band_helper::get_freq_range(builder_params.band.value()) + : frequency_range::FR1); + + optional ssb_freq_loc = + band_helper::get_ssb_coreset0_freq_location(builder_params.dl_arfcn, + *builder_params.band, + nof_crbs, + builder_params.scs_common, + builder_params.scs_common, + builder_params.search_space0_index, + builder_params.max_coreset0_duration); + builder_params.offset_to_point_a = ssb_freq_loc->offset_to_point_A; + builder_params.k_ssb = ssb_freq_loc->k_ssb; + builder_params.coreset0_index = ssb_freq_loc->coreset0_idx; + } else { + builder_params.band = band_helper::get_band_from_dl_arfcn(builder_params.dl_arfcn); + } + + return builder_params; +} + +/// Helper class to initialize and store relevant objects for the test and provide helper methods. +struct test_bench { + // Maximum number of slots to run per UE in order to validate the results of scheduler. Implementation defined. + static constexpr unsigned max_test_run_slots_per_ue = 40; + + const scheduler_expert_config sched_cfg; + const scheduler_ue_expert_config& expert_cfg{sched_cfg.ue}; + sched_cfg_dummy_notifier dummy_notif; + scheduler_ue_metrics_dummy_notifier metrics_notif; + scheduler_harq_timeout_dummy_handler harq_timeout_handler; + scheduler_ue_metrics_dummy_configurator metrics_ue_handler; + cell_config_builder_params builder_params; + + sched_config_manager cfg_mng{scheduler_config{sched_cfg, dummy_notif, metrics_notif}, metrics_ue_handler}; + const cell_configuration& cell_cfg; + + cell_resource_allocator res_grid{cell_cfg}; + pdcch_resource_allocator_impl pdcch_sch{cell_cfg}; + pucch_allocator_impl pucch_alloc{cell_cfg, 31U, 32U}; + uci_allocator_impl uci_alloc{pucch_alloc}; + ue_repository ue_db; + ue_cell_grid_allocator ue_alloc; + ue_fallback_scheduler fallback_sched; + csi_rs_scheduler csi_rs_sched; + + explicit test_bench(const scheduler_expert_config& sched_cfg_, + const cell_config_builder_params& builder_params_, + const sched_cell_configuration_request_message& cell_req) : + sched_cfg{sched_cfg_}, + builder_params{builder_params_}, + cell_cfg{*[&]() { return cfg_mng.add_cell(cell_req); }()}, + ue_alloc(expert_cfg, ue_db, srslog::fetch_basic_logger("SCHED", true)), + fallback_sched(expert_cfg, cell_cfg, pdcch_sch, pucch_alloc, ue_db), + csi_rs_sched(cell_cfg) + { + ue_alloc.add_cell(cell_cfg.cell_index, pdcch_sch, uci_alloc, res_grid); + } + + bool add_ue(const sched_ue_creation_request_message& create_req) + { + auto ev = cfg_mng.add_ue(create_req); + if (not ev.valid()) { + return false; + } + + // Add UE to UE DB. + auto u = std::make_unique( + ue_creation_command{ev.next_config(), create_req.starts_in_fallback, harq_timeout_handler}); + if (ue_db.contains(create_req.ue_index)) { + // UE already exists. + ev.abort(); + return false; + } + ue_db.add_ue(std::move(u)); + return true; + } +}; + +class base_fallback_tester +{ +protected: + slot_point current_slot{0, 0}; + srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("SCHED", true); + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST", true); + scheduler_result_logger result_logger{false, 0}; + optional bench; + duplex_mode duplx_mode; + cell_config_builder_params builder_params; + // We use this value to account for the case when the PDSCH or PUSCH is allocated several slots in advance. + unsigned max_k_value = 0; + + base_fallback_tester(duplex_mode duplx_mode_) : + duplx_mode(duplx_mode_), builder_params(test_builder_params(duplx_mode)) + { + } + + ~base_fallback_tester() + { + // Log pending allocations before finishing test. + for (unsigned i = 0; i != max_k_value; ++i) { + run_slot(); + } + srslog::flush(); + } + + void setup_sched(const scheduler_expert_config& sched_cfg, const sched_cell_configuration_request_message& msg) + { + current_slot = slot_point{to_numerology_value(msg.scs_common), 0}; + + bench.emplace(sched_cfg, builder_params, msg); + + const auto& dl_lst = bench->cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list; + for (const auto& pdsch : dl_lst) { + if (pdsch.k0 > max_k_value) { + max_k_value = pdsch.k0; + } + } + const auto& ul_lst = bench->cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common->pusch_td_alloc_list; + for (const auto& pusch : ul_lst) { + if (pusch.k2 > max_k_value) { + max_k_value = pusch.k2; + } + } + + mac_logger.set_context(current_slot.sfn(), current_slot.slot_index()); + test_logger.set_context(current_slot.sfn(), current_slot.slot_index()); + + bench->res_grid.slot_indication(current_slot); + bench->pdcch_sch.slot_indication(current_slot); + bench->pucch_alloc.slot_indication(current_slot); + } + + void run_slot() + { + ++current_slot; + + mac_logger.set_context(current_slot.sfn(), current_slot.slot_index()); + test_logger.set_context(current_slot.sfn(), current_slot.slot_index()); + result_logger.on_slot_start(); + + bench->res_grid.slot_indication(current_slot); + bench->pdcch_sch.slot_indication(current_slot); + bench->pucch_alloc.slot_indication(current_slot); + + bench->csi_rs_sched.run_slot(bench->res_grid[0]); + + bench->fallback_sched.run_slot(bench->res_grid); + + result_logger.on_scheduler_result(bench->res_grid[0].result); + + // Check sched result consistency. + test_scheduler_result_consistency(bench->cell_cfg, bench->res_grid); + } + + static scheduler_expert_config create_expert_config(sch_mcs_index max_msg4_mcs_index) + { + scheduler_expert_config cfg = config_helpers::make_default_scheduler_expert_config(); + scheduler_ue_expert_config& uecfg = cfg.ue; + uecfg.dl_mcs = {10, 10}; + uecfg.ul_mcs = {10, 10}; + uecfg.max_nof_harq_retxs = 4; + uecfg.max_msg4_mcs = max_msg4_mcs_index; + return cfg; + } + + sched_cell_configuration_request_message + create_custom_cell_config_request(unsigned k0, const optional& tdd_cfg = {}) + { + if (duplx_mode == srsran::duplex_mode::TDD and tdd_cfg.has_value()) { + builder_params.tdd_ul_dl_cfg_common = *tdd_cfg; + } + sched_cell_configuration_request_message msg = + test_helpers::make_default_sched_cell_configuration_request(builder_params); + msg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[0].k0 = k0; + return msg; + } + + bool ue_is_allocated_pdcch(const ue& u) + { + return std::any_of(bench->res_grid[0].result.dl.dl_pdcchs.begin(), + bench->res_grid[0].result.dl.dl_pdcchs.end(), + [&u](const auto& pdcch) { return pdcch.ctx.rnti == u.crnti; }); + } + + bool ue_is_allocated_pdsch(const ue& u) + { + return std::any_of(bench->res_grid[0].result.dl.ue_grants.begin(), + bench->res_grid[0].result.dl.ue_grants.end(), + [&u](const auto& grant) { return grant.pdsch_cfg.rnti == u.crnti; }); + } + + bool ue_is_allocated_pucch(const ue& u) + { + return std::any_of(bench->res_grid[0].result.ul.pucchs.begin(), + bench->res_grid[0].result.ul.pucchs.end(), + [&u](const auto& pucch) { return pucch.crnti == u.crnti; }); + } + + bool tbs_scheduled_bytes_matches_given_size(const ue& u, unsigned exp_size) + { + unsigned total_cw_tb_size_bytes = 0; + + // Fetch PDSCH resource grid allocators. + const cell_slot_resource_allocator& pdsch_alloc = bench->res_grid[0]; + // Search for PDSCH UE grant. + for (const auto& grant : pdsch_alloc.result.dl.ue_grants) { + if (grant.pdsch_cfg.rnti != u.crnti) { + continue; + } + for (const auto& cw : grant.pdsch_cfg.codewords) { + total_cw_tb_size_bytes += cw.tb_size_bytes; + } + } + return total_cw_tb_size_bytes >= exp_size; + } + + bool add_ue(rnti_t tc_rnti, du_ue_index_t ue_index) + { + // Add cell to UE cell grid allocator. + auto ue_create_req = test_helpers::create_default_sched_ue_creation_request(bench->builder_params); + ue_create_req.crnti = tc_rnti; + ue_create_req.ue_index = ue_index; + return bench->add_ue(ue_create_req); + } + + void push_buffer_state_to_dl_ue(du_ue_index_t ue_idx, unsigned buffer_size, bool is_srb0 = true) + { + // Notification from upper layers of DL buffer state. + const dl_buffer_state_indication_message msg{ue_idx, is_srb0 ? LCID_SRB0 : LCID_SRB1, buffer_size}; + bench->ue_db[ue_idx].handle_dl_buffer_state_indication(msg); + bench->ue_db[ue_idx].handle_dl_mac_ce_indication(dl_mac_ce_indication{ue_idx, lcid_dl_sch_t::UE_CON_RES_ID}); + + // Notify scheduler of DL buffer state. + bench->fallback_sched.handle_dl_buffer_state_indication_srb(ue_idx, is_srb0); + } + + unsigned get_pending_bytes(du_ue_index_t ue_idx) + { + return bench->ue_db[ue_idx].pending_dl_srb0_or_srb1_newtx_bytes(true); + } + + ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } +}; + +// Parameters to be passed to test. +struct srb0_test_params { + uint8_t k0; + duplex_mode duplx_mode; +}; + +// Parameters to be passed to test. +struct fallback_sched_test_params { + bool is_srb0; + duplex_mode duplx_mode; +}; + +class fallback_scheduler_tester : public base_fallback_tester, public ::testing::TestWithParam +{ +protected: + fallback_scheduler_tester() : base_fallback_tester(GetParam().duplx_mode), params{GetParam()} {} + + srb0_test_params params; +}; + +TEST_P(fallback_scheduler_tester, successfully_allocated_resources) +{ + setup_sched(create_expert_config(2), create_custom_cell_config_request(params.k0)); + // Add UE. + const du_ue_index_t ue_idx = to_du_ue_index(0); + add_ue(to_rnti(0x4601), ue_idx); + // Notify about SRB0 message in DL of size 101 bytes. + const unsigned mac_srb0_sdu_size = 101; + push_buffer_state_to_dl_ue(ue_idx, mac_srb0_sdu_size); + + const unsigned exp_size = get_pending_bytes(ue_idx); + + // Test the following: + // 1. Check for DCI_1_0 allocation for SRB0 on PDCCH. + // 2. Check for PDSCH allocation. + // 3. Check whether CW TB bytes matches with pending bytes to be sent. + const auto& test_ue = get_ue(ue_idx); + bool is_ue_allocated_pdcch{false}; + bool is_ue_allocated_pdsch{false}; + for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { + run_slot(); + if (ue_is_allocated_pdcch(test_ue)) { + is_ue_allocated_pdcch = true; + } + if (ue_is_allocated_pdsch(test_ue)) { + is_ue_allocated_pdsch = true; + ASSERT_TRUE(tbs_scheduled_bytes_matches_given_size(test_ue, exp_size)); + } + } + ASSERT_TRUE(is_ue_allocated_pdcch); + ASSERT_TRUE(is_ue_allocated_pdsch); + ASSERT_FALSE(test_ue.has_pending_dl_newtx_bytes(LCID_SRB0)); +} + +TEST_P(fallback_scheduler_tester, failed_allocating_resources) +{ + setup_sched(create_expert_config(0), create_custom_cell_config_request(params.k0)); + + // Add UE 1. + add_ue(to_rnti(0x4601), to_du_ue_index(0)); + // Notify about SRB0 message in DL of size 101 bytes. + unsigned ue1_mac_srb0_sdu_size = 101; + push_buffer_state_to_dl_ue(to_du_ue_index(0), ue1_mac_srb0_sdu_size); + + // Add UE 2. + add_ue(to_rnti(0x4602), to_du_ue_index(1)); + // Notify about SRB0 message in DL of size 350 bytes. i.e. big enough to not get allocated with the max. mcs chosen. + unsigned ue2_mac_srb0_sdu_size = 350; + push_buffer_state_to_dl_ue(to_du_ue_index(1), ue2_mac_srb0_sdu_size); + + run_slot(); + + // Allocation for UE2 should fail. + const auto& test_ue = get_ue(to_du_ue_index(1)); + for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { + run_slot(); + ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); + ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); + } +} + +TEST_P(fallback_scheduler_tester, test_large_srb0_buffer_size) +{ + setup_sched(create_expert_config(27), create_custom_cell_config_request(params.k0)); + // Add UE. + const du_ue_index_t ue_idx = to_du_ue_index(0); + add_ue(to_rnti(0x4601), ue_idx); + // Notify about SRB0 message in DL of size 458 bytes. + const unsigned mac_srb0_sdu_size = 458; + push_buffer_state_to_dl_ue(ue_idx, mac_srb0_sdu_size); + + const unsigned exp_size = get_pending_bytes(ue_idx); + + const auto& test_ue = get_ue(ue_idx); + bool is_ue_allocated_pdcch{false}; + bool is_ue_allocated_pdsch{false}; + for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { + run_slot(); + if (ue_is_allocated_pdcch(test_ue)) { + is_ue_allocated_pdcch = true; + } + if (ue_is_allocated_pdsch(test_ue)) { + is_ue_allocated_pdsch = true; + ASSERT_TRUE(tbs_scheduled_bytes_matches_given_size(test_ue, exp_size)); + } + } + ASSERT_TRUE(is_ue_allocated_pdcch); + ASSERT_TRUE(is_ue_allocated_pdsch); + + ASSERT_FALSE(test_ue.has_pending_dl_newtx_bytes(LCID_SRB0)); +} + +TEST_P(fallback_scheduler_tester, test_srb0_buffer_size_exceeding_max_msg4_mcs_index) +{ + setup_sched(create_expert_config(3), create_custom_cell_config_request(params.k0)); + // Add UE. + add_ue(to_rnti(0x4601), to_du_ue_index(0)); + // Notify about SRB0 message in DL of size 360 bytes which requires MCS index > 3. + const unsigned mac_srb0_sdu_size = 360; + push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); + + // Allocation for UE should fail. + const auto& test_ue = get_ue(to_du_ue_index(0)); + for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { + run_slot(); + ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); + ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); + } +} + +TEST_P(fallback_scheduler_tester, sanity_check_with_random_max_mcs_and_payload_size) +{ + const sch_mcs_index max_msg4_mcs = get_random_uint(0, 27); + setup_sched(create_expert_config(max_msg4_mcs), create_custom_cell_config_request(params.k0)); + // Add UE. + const du_ue_index_t ue_idx = to_du_ue_index(0); + add_ue(to_rnti(0x4601), ue_idx); + // Random payload size. + const unsigned mac_srb0_sdu_size = get_random_uint(1, 458); + push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); + + srslog::basic_logger& logger(srslog::fetch_basic_logger("TEST")); + logger.info("SRB0 scheduler sanity test params PDU size ({}), max msg4 mcs ({}).", mac_srb0_sdu_size, max_msg4_mcs); + + run_slot(); +} + +class fallback_scheduler_tdd_tester : public base_fallback_tester, public ::testing::Test +{ +protected: + fallback_scheduler_tdd_tester() : base_fallback_tester(srsran::duplex_mode::TDD) {} +}; + +TEST_F(fallback_scheduler_tdd_tester, test_allocation_in_appropriate_slots_in_tdd) +{ + const unsigned k0 = 0; + const sch_mcs_index max_msg4_mcs_index = 5; + auto cell_cfg = create_custom_cell_config_request(k0); + setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); + + const unsigned MAX_UES = 4; + const unsigned MAX_TEST_RUN_SLOTS = 40; + const unsigned MAC_SRB0_SDU_SIZE = 129; + + // Add UEs. + for (unsigned idx = 0; idx < MAX_UES; idx++) { + add_ue(to_rnti(0x4601 + idx), to_du_ue_index(idx)); + // Notify about SRB0 message in DL. + push_buffer_state_to_dl_ue(to_du_ue_index(idx), MAC_SRB0_SDU_SIZE); + } + + for (unsigned idx = 0; idx < MAX_UES * MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + run_slot(); + if (not bench->cell_cfg.is_dl_enabled(current_slot)) { + // Check whether PDCCH/PDSCH is not scheduled in UL slots for any of the UEs. + for (unsigned ue_idx = 0; ue_idx < MAX_UES; ue_idx++) { + const auto& test_ue = get_ue(to_du_ue_index(ue_idx)); + ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); + ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); + } + } + if (not bench->cell_cfg.is_ul_enabled(current_slot)) { + // Check whether PUCCH HARQ is not scheduled in DL slots for any of the UEs. + for (unsigned ue_idx = 0; ue_idx < MAX_UES; ue_idx++) { + const auto& test_ue = get_ue(to_du_ue_index(ue_idx)); + ASSERT_FALSE(ue_is_allocated_pucch(test_ue)); + } + } + } + + for (unsigned ue_idx = 0; ue_idx < MAX_UES; ue_idx++) { + const auto& test_ue = get_ue(to_du_ue_index(ue_idx)); + ASSERT_FALSE(test_ue.has_pending_dl_newtx_bytes(LCID_SRB0)) << "UE " << ue_idx << " has still pending DL bytes"; + } +} + +TEST_F(fallback_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) +{ + const unsigned k0 = 0; + const sch_mcs_index max_msg4_mcs_index = 8; + const tdd_ul_dl_config_common tdd_cfg{.ref_scs = subcarrier_spacing::kHz30, + .pattern1 = {.dl_ul_tx_period_nof_slots = 5, + .nof_dl_slots = 2, + .nof_dl_symbols = 8, + .nof_ul_slots = 2, + .nof_ul_symbols = 0}}; + sched_cell_configuration_request_message cell_cfg = create_custom_cell_config_request(k0, tdd_cfg); + // Generate PDSCH Time domain allocation based on the partial slot TDD configuration. + cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list = config_helpers::make_pdsch_time_domain_resource( + cell_cfg.searchspace0, cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common, nullopt, cell_cfg.tdd_ul_dl_cfg_common); + // Disabled CSI-RS resources, as this test uses a TDD configuration that is not compatible with CSI-RS scheduling. + cell_cfg.nzp_csi_rs_res_list.clear(); + cell_cfg.zp_csi_rs_list.clear(); + setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); + + const unsigned MAX_TEST_RUN_SLOTS = 40; + const unsigned MAC_SRB0_SDU_SIZE = 129; + + // Add a single UE. + add_ue(to_rnti(0x4601), to_du_ue_index(0)); + + for (unsigned idx = 0; idx < MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + run_slot(); + // Notify about SRB0 message in DL one slot before partial slot in order for it to be scheduled in the next + // (partial) slot. + if (bench->cell_cfg.is_dl_enabled(current_slot + 1) and + (not bench->cell_cfg.is_fully_dl_enabled(current_slot + 1))) { + push_buffer_state_to_dl_ue(to_du_ue_index(0), MAC_SRB0_SDU_SIZE); + } + // Check SRB0 allocation in partial slot. + if (bench->cell_cfg.is_dl_enabled(current_slot) and (not bench->cell_cfg.is_fully_dl_enabled(current_slot))) { + const auto& test_ue = get_ue(to_du_ue_index(0)); + ASSERT_TRUE(ue_is_allocated_pdcch(test_ue)); + ASSERT_TRUE(ue_is_allocated_pdsch(test_ue)); + break; + } + } +} + +INSTANTIATE_TEST_SUITE_P(fallback_scheduler, + fallback_scheduler_tester, + testing::Values(srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::FDD}, + srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::TDD})); + +class fallback_scheduler_head_scheduling : public base_fallback_tester, + public ::testing::TestWithParam +{ +protected: + const unsigned MAX_NOF_SLOTS_GRID_IS_BUSY = 4; + const unsigned MAX_TEST_RUN_SLOTS = 2100; + const unsigned MAC_SRB0_SDU_SIZE = 128; + + fallback_scheduler_head_scheduling() : base_fallback_tester(GetParam().duplx_mode) + { + const unsigned k0 = 0; + const sch_mcs_index max_msg4_mcs_index = 8; + auto cell_cfg = create_custom_cell_config_request(k0); + setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); + } + + // Helper that generates the slot for the SRB0 buffer update. + static unsigned generate_srb0_traffic_slot() { return test_rgen::uniform_int(20U, 30U); } + + // Helper that generates the number of slot during the scheduler res grid is fully used. + unsigned generate_nof_slot_grid_occupancy() const + { + return test_rgen::uniform_int(1U, MAX_NOF_SLOTS_GRID_IS_BUSY + 1); + } + + // Returns the next DL slot starting from the input slot. + slot_point get_next_dl_slot(slot_point sl) const + { + while (not bench->cell_cfg.is_dl_enabled(sl)) { + sl++; + } + return sl; + } + + // Returns the next candidate slot at which the SRB0 scheduler is expected to allocate a grant. + slot_point get_next_candidate_alloc_slot(slot_point sched_slot, unsigned nof_slot_grid_occupancy) const + { + if (nof_slot_grid_occupancy == 0) { + return sched_slot; + } + + unsigned occupy_grid_slot_cnt = 0; + + // The allocation must be on a DL slot. + do { + sched_slot++; + if (bench->cell_cfg.is_dl_enabled(sched_slot)) { + occupy_grid_slot_cnt++; + } + } while (occupy_grid_slot_cnt != nof_slot_grid_occupancy); + + auto k1_falls_on_ul = [&cfg = bench->cell_cfg](slot_point pdsch_slot) { + static const std::array dci_1_0_k1_values = {4, 5, 6, 7, 8}; + return std::any_of(dci_1_0_k1_values.begin(), dci_1_0_k1_values.end(), [&cfg, pdsch_slot](uint8_t k1) { + return cfg.is_ul_enabled(pdsch_slot + k1); + }); + }; + + // Make sure the final slot for the SRB0/SRB1 PDSCH is such that the corresponding PUCCH is in falls on a UL slot. + while ((not k1_falls_on_ul(sched_slot)) or (not bench->cell_cfg.is_dl_enabled(sched_slot)) or + csi_helper::is_csi_rs_slot(bench->cell_cfg, sched_slot)) { + sched_slot++; + } + + return sched_slot; + } +}; + +TEST_P(fallback_scheduler_head_scheduling, test_ahead_scheduling_for_srb_allocation_1_ue) +{ + // In this test, we check if the SRB0/SRB1 allocation can schedule ahead with respect to the reference slot, which is + // given by the slot_indication in the scheduler. Every time we generate SRB0 buffer bytes, we set the resource grid + // as occupied for a random number of slots. This forces the scheduler to try the allocation in next slot(s). + // The test assumes every HARQ process is acked positively. + + unsigned du_idx = 0; + add_ue(to_rnti(0x4601 + du_idx), to_du_ue_index(du_idx)); + + auto& test_ue = get_ue(to_du_ue_index(du_idx)); + + // The slots at which we generate traffic and the number of slots the grid is occupied are generated randomly. + slot_point slot_update_srb_traffic{current_slot.numerology(), generate_srb0_traffic_slot()}; + unsigned nof_slots_grid_is_busy = generate_nof_slot_grid_occupancy(); + slot_point candidate_srb_slot = get_next_dl_slot(slot_update_srb_traffic); + slot_point check_alloc_slot = get_next_candidate_alloc_slot(candidate_srb_slot, nof_slots_grid_is_busy); + + for (unsigned idx = 1; idx < MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + run_slot(); + + if (current_slot != check_alloc_slot) { + ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); + ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); + } else { + ASSERT_TRUE(ue_is_allocated_pdcch(test_ue)); + ASSERT_TRUE(ue_is_allocated_pdsch(test_ue)); + + check_alloc_slot = get_next_candidate_alloc_slot(candidate_srb_slot, nof_slots_grid_is_busy); + } + + // Allocate buffer and occupy the grid to test the scheduler in advance scheduling. + if (current_slot == slot_update_srb_traffic) { + push_buffer_state_to_dl_ue(to_du_ue_index(du_idx), MAC_SRB0_SDU_SIZE, GetParam().is_srb0); + + auto fill_bw_grant = grant_info{bench->cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs, + ofdm_symbol_range{0, 14}, + bench->cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.crbs}; + + slot_point occupy_grid_slot = slot_update_srb_traffic; + unsigned occupy_grid_slot_cnt = 0; + while (occupy_grid_slot_cnt < nof_slots_grid_is_busy) { + // Only set the grid busy in the DL slots. + if (bench->cell_cfg.is_dl_enabled(occupy_grid_slot)) { + bench->res_grid[occupy_grid_slot].dl_res_grid.fill(fill_bw_grant); + occupy_grid_slot_cnt++; + } + occupy_grid_slot++; + } + + slot_update_srb_traffic = current_slot + generate_srb0_traffic_slot(); + nof_slots_grid_is_busy = generate_nof_slot_grid_occupancy(); + candidate_srb_slot = get_next_dl_slot(slot_update_srb_traffic); + } + + // Ack the HARQ processes that are waiting for ACK, otherwise the scheduler runs out of empty HARQs. + const unsigned bit_index_1_harq_only = 0U; + dl_harq_process* dl_harq = + test_ue.get_pcell().harqs.find_dl_harq_waiting_ack_slot(current_slot, bit_index_1_harq_only); + if (dl_harq != nullptr) { + static constexpr unsigned tb_idx = 0U; + dl_harq->ack_info(tb_idx, mac_harq_ack_report_status::ack, {}); + } + } +} + +INSTANTIATE_TEST_SUITE_P(fallback_scheduler, + fallback_scheduler_head_scheduling, + testing::Values(fallback_sched_test_params{.is_srb0 = true, .duplx_mode = duplex_mode::FDD}, + fallback_sched_test_params{.is_srb0 = true, .duplx_mode = duplex_mode::TDD}, + fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::FDD}, + fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::TDD})); + +class fallback_scheduler_retx : public base_fallback_tester, public ::testing::TestWithParam +{ +protected: + fallback_scheduler_retx() : base_fallback_tester(GetParam().duplx_mode) + { + const unsigned k0 = 0; + const sch_mcs_index max_msg4_mcs_index = 8; + auto cell_cfg = create_custom_cell_config_request(k0); + setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); + ues_testers.reserve(MAX_UES); + } + + // Class that implements a state-machine for the UE, to keep track of acks and retransmissions. + class ue_retx_tester + { + public: + enum class ue_state { idle, waiting_for_tx, waiting_for_ack, waiting_for_retx, reset_harq }; + + ue_retx_tester(const cell_configuration& cell_cfg_, ue& test_ue_, fallback_scheduler_retx* parent_) : + cell_cfg(cell_cfg_), test_ue(test_ue_), parent(parent_) + { + slot_update_srb_traffic = generate_srb1_next_update_delay(); + nof_packet_to_tx = parent->SRB_PACKETS_TOT_TX; + } + + void slot_indication(slot_point sl) + { + switch (state) { + // Wait until the slot to update the SRB0 traffic. + case ue_state::idle: { + if (sl == slot_update_srb_traffic and nof_packet_to_tx > 0) { + // Notify about SRB0 message in DL. + parent->push_buffer_state_to_dl_ue(test_ue.ue_index, parent->MAC_SRB0_SDU_SIZE, GetParam().is_srb0); + state = ue_state::waiting_for_tx; + } + break; + } + // Wait until the UE transmits the PDSCH with SRB0 or SRB1. + case ue_state::waiting_for_tx: { + for (harq_id_t h_id = to_harq_id(0); h_id != MAX_HARQ_ID; + h_id = to_harq_id(std::underlying_type_t(h_id) + 1)) { + if (test_ue.get_pcell().harqs.dl_harq(h_id).is_waiting_ack() == true) { + ongoing_h_id = h_id; + break; + } + } + + if (ongoing_h_id != INVALID_HARQ_ID) { + --nof_packet_to_tx; + state = ue_state::waiting_for_ack; + } + break; + } + // Wait until the slot at which the ACK is expected and update successful and unsuccessful TX counters. + case ue_state::waiting_for_ack: { + const dl_harq_process& h_dl = test_ue.get_pcell().harqs.dl_harq(ongoing_h_id); + + if (h_dl.slot_ack() == sl) { + static constexpr double ack_probability = 0.5f; + ack_outcome = test_rgen::bernoulli(ack_probability); + if (ack_outcome == true) { + ++successful_tx_cnt; + state = ue_state::reset_harq; + } else { + const unsigned tb_index_only_1_tb_supported = 0U; + if (h_dl.tb(tb_index_only_1_tb_supported).nof_retxs != + h_dl.tb(tb_index_only_1_tb_supported).max_nof_harq_retxs) { + state = ue_state::waiting_for_retx; + } else { + ++unsuccessful_tx_cnt; + state = ue_state::reset_harq; + } + } + } + break; + } + // Wait for UE to re-transmit the SRBO / SRB1 related PDSCH + case ue_state::waiting_for_retx: { + const dl_harq_process& h_dl = test_ue.get_pcell().harqs.dl_harq(ongoing_h_id); + if (h_dl.empty()) { + ++missed_srb_cnt; + state = ue_state::reset_harq; + } else if (h_dl.is_waiting_ack()) { + state = ue_state::waiting_for_ack; + } + break; + } + // This state in necessary to set a delay in the reset of the HARQ-ID, which is needed by the + // ack_harq_process() function. + case ue_state::reset_harq: { + // Notify about SRB0 message in DL. + slot_update_srb_traffic = sl.to_uint() + generate_srb1_next_update_delay(); + ongoing_h_id = INVALID_HARQ_ID; + state = ue_state::idle; + + break; + } + } + } + + void ack_harq_process(slot_point sl) + { + // Ack the HARQ processes that are waiting for ACK, otherwise the scheduler runs out of empty HARQs. + const unsigned bit_index_1_harq_only = 0U; + dl_harq_process* dl_harq = test_ue.get_pcell().harqs.find_dl_harq_waiting_ack_slot(sl, bit_index_1_harq_only); + if (dl_harq != nullptr) { + srsran_assert(dl_harq->id == ongoing_h_id, "HARQ process mismatch"); + static constexpr unsigned tb_idx = 0U; + dl_harq->ack_info(tb_idx, ack_outcome ? mac_harq_ack_report_status::ack : mac_harq_ack_report_status::nack, {}); + } + } + + slot_point generate_srb1_next_update_delay() + { + // Generate a random number of slots to wait until the next SRB1 buffer update. + return slot_point{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), + test_rgen::uniform_int(20U, 40U)}; + } + + const cell_configuration& cell_cfg; + ue& test_ue; + ue_state state = ue_state::idle; + slot_point slot_update_srb_traffic; + unsigned nof_packet_to_tx; + harq_id_t ongoing_h_id = INVALID_HARQ_ID; + fallback_scheduler_retx* parent; + bool ack_outcome = false; + // Counter of TXs that terminate with ACK before reaching max_nof_harq_retxs. + unsigned successful_tx_cnt = 0; + // Counter of a TX that terminates with all NACKs until max_nof_harq_retxs is reached. + unsigned unsuccessful_tx_cnt = 0; + // Counter of a TX that require HARQ re-tx, but are not served by the scheduler. + unsigned missed_srb_cnt = 0; + }; + + const unsigned SRB_PACKETS_TOT_TX = 20; + const unsigned MAX_UES = 1; + const unsigned MAX_TEST_RUN_SLOTS = 2100; + const unsigned MAC_SRB0_SDU_SIZE = 128; + + std::vector ues_testers; +}; + +TEST_P(fallback_scheduler_retx, test_scheduling_for_srb_retransmissions_multi_ue) +{ + // In this test, we check if the SRB0/SRB1 scheduler handles re-transmissions. Each time a SRB0/SRB1 buffer is updated + // for a given UE, the GNB is expected to schedule a PDSCH grant, or multiple grants (for retransmissions) in case of + // NACKs. Every time the SRB0/SRB1 buffer is updated, the scheduler is expected serve this SRB, which can result in a + // successful transmission (at least 1 ACK before reaching max_nof_harq_retxs) or an unsuccessful tx (all NACKs until + // max_nof_harq_retxs). + // The test fails if: (i) the tot. number of successful transmissions plus unsuccessful transmissions is less + // than the SRB0/SRB1 buffer updates; (ii) if any NACKed re-transmissions are left unserved (unless it reaches the + // max_nof_harq_retxs). + + for (unsigned du_idx = 0; du_idx < MAX_UES; du_idx++) { + add_ue(to_rnti(0x4601 + du_idx), to_du_ue_index(du_idx)); + ues_testers.emplace_back(ue_retx_tester(bench->cell_cfg, get_ue(to_du_ue_index(du_idx)), this)); + } + + for (unsigned idx = 1; idx < MAX_UES * MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + run_slot(); + + for (auto& tester : ues_testers) { + tester.slot_indication(current_slot); + tester.ack_harq_process(current_slot); + } + } + + for (auto& tester : ues_testers) { + ASSERT_EQ(0U, tester.missed_srb_cnt); + ASSERT_EQ(SRB_PACKETS_TOT_TX, tester.successful_tx_cnt + tester.unsuccessful_tx_cnt); + } +} + +INSTANTIATE_TEST_SUITE_P(fallback_scheduler, + fallback_scheduler_retx, + testing::Values(fallback_sched_test_params{.is_srb0 = true, .duplx_mode = duplex_mode::FDD}, + fallback_sched_test_params{.is_srb0 = true, .duplx_mode = duplex_mode::TDD}, + fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::FDD}, + fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::TDD})); + +class fallback_scheduler_srb1_segmentation : public base_fallback_tester, + public ::testing::TestWithParam +{ +protected: + fallback_scheduler_srb1_segmentation() : base_fallback_tester(GetParam().duplx_mode) + { + const unsigned k0 = 0; + const sch_mcs_index max_msg4_mcs_index = 8; + auto cell_cfg = create_custom_cell_config_request(k0); + setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); + ues_testers.reserve(MAX_UES); + } + + // Class that implements a state-machine for the UE, to keep track of acks and retransmissions. + class ue_retx_tester + { + public: + ue_retx_tester(const cell_configuration& cell_cfg_, ue& test_ue_, fallback_scheduler_srb1_segmentation* parent_) : + cell_cfg(cell_cfg_), test_ue(test_ue_), parent(parent_) + { + slot_update_srb_traffic = generate_srb1_next_update_delay(); + nof_packet_to_tx = parent->SRB_PACKETS_TOT_TX; + test_logger.set_level(srslog::basic_levels::debug); + + latest_harq_states.reserve(MAX_NOF_HARQS); + for (uint8_t h_id_idx = 0; h_id_idx != std::underlying_type_t(MAX_HARQ_ID); ++h_id_idx) { + latest_harq_states.emplace_back(h_state::empty); + } + } + + void slot_indication(slot_point sl) + { + // Wait until the slot to update the SRB1 traffic. + if (sl == slot_update_srb_traffic and nof_packet_to_tx > 0) { + // Notify about SRB1 message in DL. + parent->push_buffer_state_to_dl_ue(test_ue.ue_index, generate_srb1_buffer_size(), GetParam().is_srb0); + --nof_packet_to_tx; + slot_update_srb_traffic = sl.to_uint() + generate_srb1_next_update_delay(); + test_logger.debug("rnti={}, slot={}: pushing SRB1 traffic", test_ue.crnti, sl); + } + + for (uint8_t h_id_idx = 0; h_id_idx != std::underlying_type_t(MAX_HARQ_ID); ++h_id_idx) { + harq_id_t h_id = to_harq_id(h_id_idx); + + // Check if any HARQ process with pending transmissions is re-set by the scheduler. + if (latest_harq_states[h_id_idx] == h_state::pending_retx and test_ue.get_pcell().harqs.dl_harq(h_id).empty()) { + ++missing_retx; + } + + // Save HARQ process latest. + if (test_ue.get_pcell().harqs.dl_harq(h_id).empty()) { + latest_harq_states[h_id_idx] = h_state::empty; + } else if (test_ue.get_pcell().harqs.dl_harq(h_id).is_waiting_ack()) { + latest_harq_states[h_id_idx] = h_state::waiting_ack; + } else { + latest_harq_states[h_id_idx] = h_state::pending_retx; + } + } + + // Update HARQ process. + ack_harq_process(sl); + } + + void ack_harq_process(slot_point sl) + { + // Ack the HARQ processes that are waiting for ACK, otherwise the scheduler runs out of empty HARQs. + const unsigned bit_index_1_harq_only = 0U; + dl_harq_process* dl_harq = test_ue.get_pcell().harqs.find_dl_harq_waiting_ack_slot(sl, bit_index_1_harq_only); + if (dl_harq != nullptr) { + static constexpr unsigned tb_idx = 0U; + static constexpr double ack_probability = 0.5f; + const bool ack = test_rgen::bernoulli(ack_probability); + dl_harq->ack_info(tb_idx, ack ? mac_harq_ack_report_status::ack : mac_harq_ack_report_status::nack, {}); + test_logger.debug("Slot={}, rnti={}: acking process h_id={} with {}", + sl, + test_ue.crnti, + to_harq_id(dl_harq->id), + ack ? "ACK" : "NACK"); + } + } + + unsigned generate_srb1_buffer_size() { return test_rgen::uniform_int(128U, parent->MAX_MAC_SRB0_SDU_SIZE); } + slot_point generate_srb1_next_update_delay() + { + // Generate a random number of slots to wait until the next SRB1 buffer update. + return slot_point{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), + test_rgen::uniform_int(20U, 40U)}; + } + + const cell_configuration& cell_cfg; + ue& test_ue; + slot_point slot_update_srb_traffic; + unsigned nof_packet_to_tx; + fallback_scheduler_srb1_segmentation* parent; + srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); + unsigned missing_retx = 0; + + using h_state = srsran::dl_harq_process::harq_process::transport_block::state_t; + std::vector latest_harq_states; + }; + + const unsigned SRB_PACKETS_TOT_TX = 10; + const unsigned MAX_UES = 10; + const unsigned MAX_TEST_RUN_SLOTS = 500; + const unsigned MAX_MAC_SRB0_SDU_SIZE = 1600; + + std::vector ues_testers; +}; + +TEST_P(fallback_scheduler_srb1_segmentation, test_scheduling_srb1_segmentation) +{ + // In this test, we check if the SRB0/SRB1 scheduler handles segmentation for the SRB1. Each time a SRB1 buffer is + // updated, the GNB is to sends one or more grants, until the UE's SRB1 buffer is emptied. + // The test fails if: (i) at the end of the test, the SRB1 buffer is not empty; (ii) if any NACKed re-transmissions + // are left unserved (unless it reaches the max_nof_harq_retxs). + + for (unsigned du_idx = 0; du_idx < MAX_UES; du_idx++) { + add_ue(to_rnti(0x4601 + du_idx), to_du_ue_index(du_idx)); + ues_testers.emplace_back(ue_retx_tester(bench->cell_cfg, get_ue(to_du_ue_index(du_idx)), this)); + } + + for (unsigned idx = 1; idx < MAX_UES * MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + run_slot(); + + for (auto& tester : ues_testers) { + tester.slot_indication(current_slot); + } + } + + for (auto& tester : ues_testers) { + ASSERT_EQ(0, tester.missing_retx); + ASSERT_FALSE(tester.test_ue.has_pending_dl_newtx_bytes(LCID_SRB1)); + } +} + +INSTANTIATE_TEST_SUITE_P(fallback_scheduler, + fallback_scheduler_srb1_segmentation, + testing::Values(fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::FDD}, + fallback_sched_test_params{.is_srb0 = false, .duplx_mode = duplex_mode::TDD})); + +int main(int argc, char** argv) +{ + srslog::fetch_basic_logger("SCHED", true).set_level(srslog::basic_levels::debug); + srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::info); + srslog::init(); + + ::testing::InitGoogleTest(&argc, argv); + + (void)(::testing::GTEST_FLAG(death_test_style) = "fast"); + + return RUN_ALL_TESTS(); +} diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp deleted file mode 100644 index 412a006ad1..0000000000 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* - * - * Copyright 2021-2024 Software Radio Systems Limited - * - * This file is part of srsRAN. - * - * srsRAN is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsRAN is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "lib/scheduler/config/sched_config_manager.h" -#include "lib/scheduler/logging/scheduler_result_logger.h" -#include "lib/scheduler/pdcch_scheduling/pdcch_resource_allocator_impl.h" -#include "lib/scheduler/pucch_scheduling/pucch_allocator_impl.h" -#include "lib/scheduler/uci_scheduling/uci_allocator_impl.h" -#include "lib/scheduler/ue_scheduling/ue_cell_grid_allocator.h" -#include "lib/scheduler/ue_scheduling/ue_srb0_scheduler.h" -#include "tests/unittests/scheduler/test_utils/config_generators.h" -#include "tests/unittests/scheduler/test_utils/dummy_test_components.h" -#include "tests/unittests/scheduler/test_utils/scheduler_test_suite.h" -#include "srsran/ran/duplex_mode.h" -#include -#include - -using namespace srsran; - -std::random_device rd; -std::mt19937 g(rd()); - -unsigned get_random_uint(unsigned min, unsigned max) -{ - return std::uniform_int_distribution{min, max}(g); -} - -static cell_config_builder_params test_builder_params(duplex_mode duplx_mode) -{ - cell_config_builder_params builder_params{}; - if (duplx_mode == duplex_mode::TDD) { - // Band 40. - builder_params.dl_arfcn = 474000; - builder_params.scs_common = srsran::subcarrier_spacing::kHz30; - builder_params.band = band_helper::get_band_from_dl_arfcn(builder_params.dl_arfcn); - builder_params.channel_bw_mhz = bs_channel_bandwidth_fr1::MHz20; - - const unsigned nof_crbs = band_helper::get_n_rbs_from_bw( - builder_params.channel_bw_mhz, - builder_params.scs_common, - builder_params.band.has_value() ? band_helper::get_freq_range(builder_params.band.value()) - : frequency_range::FR1); - - optional ssb_freq_loc = - band_helper::get_ssb_coreset0_freq_location(builder_params.dl_arfcn, - *builder_params.band, - nof_crbs, - builder_params.scs_common, - builder_params.scs_common, - builder_params.search_space0_index, - builder_params.max_coreset0_duration); - builder_params.offset_to_point_a = ssb_freq_loc->offset_to_point_A; - builder_params.k_ssb = ssb_freq_loc->k_ssb; - builder_params.coreset0_index = ssb_freq_loc->coreset0_idx; - } else { - builder_params.band = band_helper::get_band_from_dl_arfcn(builder_params.dl_arfcn); - } - - return builder_params; -} - -/// Helper class to initialize and store relevant objects for the test and provide helper methods. -struct test_bench { - // Maximum number of slots to run per UE in order to validate the results of scheduler. Implementation defined. - static constexpr unsigned max_test_run_slots_per_ue = 40; - - const scheduler_expert_config sched_cfg; - const scheduler_ue_expert_config& expert_cfg{sched_cfg.ue}; - sched_cfg_dummy_notifier dummy_notif; - scheduler_ue_metrics_dummy_notifier metrics_notif; - scheduler_harq_timeout_dummy_handler harq_timeout_handler; - scheduler_ue_metrics_dummy_configurator metrics_ue_handler; - cell_config_builder_params builder_params; - - sched_config_manager cfg_mng{scheduler_config{sched_cfg, dummy_notif, metrics_notif}, metrics_ue_handler}; - const cell_configuration& cell_cfg; - - cell_resource_allocator res_grid{cell_cfg}; - pdcch_resource_allocator_impl pdcch_sch{cell_cfg}; - pucch_allocator_impl pucch_alloc{cell_cfg, 31U, 32U}; - uci_allocator_impl uci_alloc{pucch_alloc}; - ue_repository ue_db; - ue_cell_grid_allocator ue_alloc; - ue_srb0_scheduler srb0_sched; - - explicit test_bench(const scheduler_expert_config& sched_cfg_, - const cell_config_builder_params& builder_params_, - const sched_cell_configuration_request_message& cell_req) : - sched_cfg{sched_cfg_}, - builder_params{builder_params_}, - cell_cfg{*[&]() { return cfg_mng.add_cell(cell_req); }()}, - ue_alloc(expert_cfg, ue_db, srslog::fetch_basic_logger("SCHED", true)), - srb0_sched(expert_cfg, cell_cfg, pdcch_sch, pucch_alloc, ue_db) - { - ue_alloc.add_cell(cell_cfg.cell_index, pdcch_sch, uci_alloc, res_grid); - } - - bool add_ue(const sched_ue_creation_request_message create_req) - { - auto ev = cfg_mng.add_ue(create_req); - if (not ev.valid()) { - return false; - } - - // Add UE to UE DB. - auto u = std::make_unique( - ue_creation_command{ev.next_config(), create_req.starts_in_fallback, harq_timeout_handler}); - if (ue_db.contains(create_req.ue_index)) { - // UE already exists. - ev.abort(); - return false; - } - ue_db.add_ue(std::move(u)); - return true; - } -}; - -class base_srb0_scheduler_tester -{ -protected: - slot_point current_slot{0, 0}; - srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("SCHED", true); - srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST", true); - scheduler_result_logger result_logger{false, 0}; - optional bench; - duplex_mode duplx_mode; - cell_config_builder_params builder_params; - // We use this value to account for the case when the PDSCH or PUSCH is allocated several slots in advance. - unsigned max_k_value = 0; - - base_srb0_scheduler_tester(duplex_mode duplx_mode_) : - duplx_mode(duplx_mode_), builder_params(test_builder_params(duplx_mode)) - { - } - - ~base_srb0_scheduler_tester() - { - // Log pending allocations before finishing test. - for (unsigned i = 0; i != max_k_value; ++i) { - run_slot(); - } - srslog::flush(); - } - - void setup_sched(const scheduler_expert_config& sched_cfg, const sched_cell_configuration_request_message& msg) - { - current_slot = slot_point{to_numerology_value(msg.scs_common), 0}; - - bench.emplace(sched_cfg, builder_params, msg); - - const auto& dl_lst = bench->cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list; - for (const auto& pdsch : dl_lst) { - if (pdsch.k0 > max_k_value) { - max_k_value = pdsch.k0; - } - } - const auto& ul_lst = bench->cell_cfg.ul_cfg_common.init_ul_bwp.pusch_cfg_common->pusch_td_alloc_list; - for (const auto& pusch : ul_lst) { - if (pusch.k2 > max_k_value) { - max_k_value = pusch.k2; - } - } - - mac_logger.set_context(current_slot.sfn(), current_slot.slot_index()); - test_logger.set_context(current_slot.sfn(), current_slot.slot_index()); - - bench->res_grid.slot_indication(current_slot); - bench->pdcch_sch.slot_indication(current_slot); - bench->pucch_alloc.slot_indication(current_slot); - } - - void run_slot() - { - current_slot++; - - mac_logger.set_context(current_slot.sfn(), current_slot.slot_index()); - test_logger.set_context(current_slot.sfn(), current_slot.slot_index()); - result_logger.on_slot_start(); - - bench->res_grid.slot_indication(current_slot); - bench->pdcch_sch.slot_indication(current_slot); - - bench->srb0_sched.run_slot(bench->res_grid); - - result_logger.on_scheduler_result(bench->res_grid[0].result); - - // Check sched result consistency. - test_scheduler_result_consistency(bench->cell_cfg, bench->res_grid); - } - - scheduler_expert_config create_expert_config(sch_mcs_index max_msg4_mcs_index) const - { - scheduler_expert_config cfg = config_helpers::make_default_scheduler_expert_config(); - scheduler_ue_expert_config& uecfg = cfg.ue; - uecfg.dl_mcs = {10, 10}; - uecfg.ul_mcs = {10, 10}; - uecfg.max_nof_harq_retxs = 4; - uecfg.max_msg4_mcs = max_msg4_mcs_index; - return cfg; - } - - sched_cell_configuration_request_message - create_custom_cell_config_request(unsigned k0, const optional& tdd_cfg = {}) - { - if (duplx_mode == srsran::duplex_mode::TDD and tdd_cfg.has_value()) { - builder_params.tdd_ul_dl_cfg_common = *tdd_cfg; - } - sched_cell_configuration_request_message msg = - test_helpers::make_default_sched_cell_configuration_request(builder_params); - msg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[0].k0 = k0; - return msg; - } - - bool ue_is_allocated_pdcch(const ue& u) - { - return std::any_of(bench->res_grid[0].result.dl.dl_pdcchs.begin(), - bench->res_grid[0].result.dl.dl_pdcchs.end(), - [&u](const auto& pdcch) { return pdcch.ctx.rnti == u.crnti; }); - } - - bool ue_is_allocated_pdsch(const ue& u) - { - return std::any_of(bench->res_grid[0].result.dl.ue_grants.begin(), - bench->res_grid[0].result.dl.ue_grants.end(), - [&u](const auto& grant) { return grant.pdsch_cfg.rnti == u.crnti; }); - } - - bool ue_is_allocated_pucch(const ue& u) - { - return std::any_of(bench->res_grid[0].result.ul.pucchs.begin(), - bench->res_grid[0].result.ul.pucchs.end(), - [&u](const auto& pucch) { return pucch.crnti == u.crnti; }); - } - - bool tbs_scheduled_bytes_matches_given_size(const ue& u, unsigned exp_size) - { - unsigned total_cw_tb_size_bytes = 0; - - // Fetch PDSCH resource grid allocators. - const cell_slot_resource_allocator& pdsch_alloc = bench->res_grid[0]; - // Search for PDSCH UE grant. - for (const auto& grant : pdsch_alloc.result.dl.ue_grants) { - if (grant.pdsch_cfg.rnti != u.crnti) { - continue; - } - for (const auto& cw : grant.pdsch_cfg.codewords) { - total_cw_tb_size_bytes += cw.tb_size_bytes; - } - } - return total_cw_tb_size_bytes >= exp_size; - } - - bool add_ue(rnti_t tc_rnti, du_ue_index_t ue_index) - { - // Add cell to UE cell grid allocator. - auto ue_create_req = test_helpers::create_default_sched_ue_creation_request(bench->builder_params); - ue_create_req.crnti = tc_rnti; - ue_create_req.ue_index = ue_index; - return bench->add_ue(ue_create_req); - } - - void push_buffer_state_to_dl_ue(du_ue_index_t ue_idx, unsigned buffer_size) - { - // Notification from upper layers of DL buffer state. - const dl_buffer_state_indication_message msg{ue_idx, LCID_SRB0, buffer_size}; - bench->ue_db[ue_idx].handle_dl_buffer_state_indication(msg); - - // Notify scheduler of DL buffer state. - bench->srb0_sched.handle_dl_buffer_state_indication(ue_idx); - } - - unsigned get_pending_bytes(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx].pending_dl_srb0_newtx_bytes(); } - - const ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } -}; - -// Parameters to be passed to test. -struct srb0_test_params { - uint8_t k0; - duplex_mode duplx_mode; -}; - -class srb0_scheduler_tester : public base_srb0_scheduler_tester, public ::testing::TestWithParam -{ -protected: - srb0_scheduler_tester() : base_srb0_scheduler_tester(GetParam().duplx_mode), params{GetParam()} {} - - srb0_test_params params; -}; - -TEST_P(srb0_scheduler_tester, successfully_allocated_resources) -{ - setup_sched(create_expert_config(2), create_custom_cell_config_request(params.k0)); - // Add UE. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - // Notify about SRB0 message in DL of size 101 bytes. - const unsigned mac_srb0_sdu_size = 101; - push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); - - const unsigned exp_size = get_pending_bytes(to_du_ue_index(0)); - - // Test the following: - // 1. Check for DCI_1_0 allocation for SRB0 on PDCCH. - // 2. Check for PDSCH allocation. - // 3. Check whether CW TB bytes matches with pending bytes to be sent. - const auto& test_ue = get_ue(to_du_ue_index(0)); - bool is_ue_allocated_pdcch{false}; - bool is_ue_allocated_pdsch{false}; - for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { - run_slot(); - if (ue_is_allocated_pdcch(test_ue)) { - is_ue_allocated_pdcch = true; - } - if (ue_is_allocated_pdsch(test_ue)) { - is_ue_allocated_pdsch = true; - ASSERT_TRUE(tbs_scheduled_bytes_matches_given_size(test_ue, exp_size)); - } - } - ASSERT_TRUE(is_ue_allocated_pdcch); - ASSERT_TRUE(is_ue_allocated_pdsch); -} - -TEST_P(srb0_scheduler_tester, failed_allocating_resources) -{ - setup_sched(create_expert_config(0), create_custom_cell_config_request(params.k0)); - - // Add UE 1. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - // Notify about SRB0 message in DL of size 101 bytes. - unsigned ue1_mac_srb0_sdu_size = 101; - push_buffer_state_to_dl_ue(to_du_ue_index(0), ue1_mac_srb0_sdu_size); - - // Add UE 2. - add_ue(to_rnti(0x4602), to_du_ue_index(1)); - // Notify about SRB0 message in DL of size 350 bytes. i.e. big enough to not get allocated with the max. mcs chosen. - unsigned ue2_mac_srb0_sdu_size = 350; - push_buffer_state_to_dl_ue(to_du_ue_index(1), ue2_mac_srb0_sdu_size); - - run_slot(); - - // Allocation for UE2 should fail. - const auto& test_ue = get_ue(to_du_ue_index(1)); - for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { - run_slot(); - ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); - ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); - } -} - -TEST_P(srb0_scheduler_tester, test_large_srb0_buffer_size) -{ - setup_sched(create_expert_config(27), create_custom_cell_config_request(params.k0)); - // Add UE. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - // Notify about SRB0 message in DL of size 458 bytes. - const unsigned mac_srb0_sdu_size = 458; - push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); - - const unsigned exp_size = get_pending_bytes(to_du_ue_index(0)); - - const auto& test_ue = get_ue(to_du_ue_index(0)); - bool is_ue_allocated_pdcch{false}; - bool is_ue_allocated_pdsch{false}; - for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { - run_slot(); - if (ue_is_allocated_pdcch(test_ue)) { - is_ue_allocated_pdcch = true; - } - if (ue_is_allocated_pdsch(test_ue)) { - is_ue_allocated_pdsch = true; - ASSERT_TRUE(tbs_scheduled_bytes_matches_given_size(test_ue, exp_size)); - } - } - ASSERT_TRUE(is_ue_allocated_pdcch); - ASSERT_TRUE(is_ue_allocated_pdsch); -} - -TEST_P(srb0_scheduler_tester, test_srb0_buffer_size_exceeding_max_msg4_mcs_index) -{ - setup_sched(create_expert_config(3), create_custom_cell_config_request(params.k0)); - // Add UE. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - // Notify about SRB0 message in DL of size 360 bytes which requires MCS index > 3. - const unsigned mac_srb0_sdu_size = 360; - push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); - - // Allocation for UE should fail. - const auto& test_ue = get_ue(to_du_ue_index(0)); - for (unsigned sl_idx = 0; sl_idx < bench->max_test_run_slots_per_ue * (1U << current_slot.numerology()); sl_idx++) { - run_slot(); - ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); - ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); - } -} - -TEST_P(srb0_scheduler_tester, sanity_check_with_random_max_mcs_and_payload_size) -{ - const sch_mcs_index max_msg4_mcs = get_random_uint(0, 27); - setup_sched(create_expert_config(max_msg4_mcs), create_custom_cell_config_request(params.k0)); - // Add UE. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - // Random payload size. - const unsigned mac_srb0_sdu_size = get_random_uint(1, 458); - push_buffer_state_to_dl_ue(to_du_ue_index(0), mac_srb0_sdu_size); - - srslog::basic_logger& logger(srslog::fetch_basic_logger("TEST")); - logger.info("SRB0 scheduler sanity test params PDU size ({}), max msg4 mcs ({}).", mac_srb0_sdu_size, max_msg4_mcs); - - run_slot(); -} - -class srb0_scheduler_tdd_tester : public base_srb0_scheduler_tester, public ::testing::Test -{ -protected: - srb0_scheduler_tdd_tester() : base_srb0_scheduler_tester(srsran::duplex_mode::TDD) {} -}; - -TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_appropriate_slots_in_tdd) -{ - const unsigned k0 = 0; - const sch_mcs_index max_msg4_mcs_index = 1; - auto cell_cfg = create_custom_cell_config_request(k0); - setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); - - const unsigned MAX_UES = 4; - const unsigned MAX_TEST_RUN_SLOTS = 40; - const unsigned MAC_SRB0_SDU_SIZE = 129; - - // Add UEs. - for (unsigned idx = 0; idx < MAX_UES; idx++) { - add_ue(to_rnti(0x4601 + idx), to_du_ue_index(idx)); - // Notify about SRB0 message in DL. - push_buffer_state_to_dl_ue(to_du_ue_index(idx), MAC_SRB0_SDU_SIZE); - } - - for (unsigned idx = 0; idx < MAX_UES * MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { - run_slot(); - if (not bench->cell_cfg.is_dl_enabled(current_slot)) { - // Check whether PDCCH/PDSCH is not scheduled in UL slots for any of the UEs. - for (unsigned ue_idx = 0; ue_idx < MAX_UES; ue_idx++) { - const auto& test_ue = get_ue(to_du_ue_index(ue_idx)); - ASSERT_FALSE(ue_is_allocated_pdcch(test_ue)); - ASSERT_FALSE(ue_is_allocated_pdsch(test_ue)); - } - } - if (not bench->cell_cfg.is_ul_enabled(current_slot)) { - // Check whether PUCCH HARQ is not scheduled in DL slots for any of the UEs. - for (unsigned ue_idx = 0; ue_idx < MAX_UES; ue_idx++) { - const auto& test_ue = get_ue(to_du_ue_index(ue_idx)); - ASSERT_FALSE(ue_is_allocated_pucch(test_ue)); - } - } - } -} - -TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) -{ - const unsigned k0 = 0; - const sch_mcs_index max_msg4_mcs_index = 8; - const tdd_ul_dl_config_common tdd_cfg{.ref_scs = subcarrier_spacing::kHz30, - .pattern1 = {.dl_ul_tx_period_nof_slots = 5, - .nof_dl_slots = 2, - .nof_dl_symbols = 8, - .nof_ul_slots = 2, - .nof_ul_symbols = 0}}; - sched_cell_configuration_request_message cell_cfg = create_custom_cell_config_request(k0, tdd_cfg); - // Generate PDSCH Time domain allocation based on the partial slot TDD configuration. - cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list = config_helpers::make_pdsch_time_domain_resource( - cell_cfg.searchspace0, cell_cfg.dl_cfg_common.init_dl_bwp.pdcch_common, nullopt, cell_cfg.tdd_ul_dl_cfg_common); - setup_sched(create_expert_config(max_msg4_mcs_index), cell_cfg); - - const unsigned MAX_TEST_RUN_SLOTS = 40; - const unsigned MAC_SRB0_SDU_SIZE = 129; - - // Add a single UE. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); - - for (unsigned idx = 0; idx < MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { - run_slot(); - // Notify about SRB0 message in DL one slot before partial slot in order for it to be scheduled in the next - // (partial) slot. - if (bench->cell_cfg.is_dl_enabled(current_slot + 1) and - (not bench->cell_cfg.is_fully_dl_enabled(current_slot + 1))) { - push_buffer_state_to_dl_ue(to_du_ue_index(0), MAC_SRB0_SDU_SIZE); - } - // Check SRB0 allocation in partial slot. - if (bench->cell_cfg.is_dl_enabled(current_slot) and (not bench->cell_cfg.is_fully_dl_enabled(current_slot))) { - const auto& test_ue = get_ue(to_du_ue_index(0)); - ASSERT_TRUE(ue_is_allocated_pdcch(test_ue)); - ASSERT_TRUE(ue_is_allocated_pdsch(test_ue)); - break; - } - } -} - -INSTANTIATE_TEST_SUITE_P(srb0_scheduler, - srb0_scheduler_tester, - testing::Values(srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::FDD}, - srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::TDD})); - -int main(int argc, char** argv) -{ - srslog::fetch_basic_logger("SCHED", true).set_level(srslog::basic_levels::debug); - srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::info); - srslog::init(); - - ::testing::InitGoogleTest(&argc, argv); - - (void)(::testing::GTEST_FLAG(death_test_style) = "fast"); - - return RUN_ALL_TESTS(); -} diff --git a/tests/unittests/sdap/sdap_rx_test.cpp b/tests/unittests/sdap/sdap_rx_test.cpp index b4ee1ad8b7..8e4760f6f2 100644 --- a/tests/unittests/sdap/sdap_rx_test.cpp +++ b/tests/unittests/sdap/sdap_rx_test.cpp @@ -82,9 +82,9 @@ TEST_F(sdap_rx_test, create_new_entity) TEST_F(sdap_rx_test, test_rx) { const std::array pdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer pdu{pdu_buf}; + byte_buffer pdu = byte_buffer::create(pdu_buf).value(); - sdap->handle_pdu(pdu.deep_copy()); + sdap->handle_pdu(pdu.deep_copy().value()); ASSERT_FALSE(tester->sdu_queue.empty()); EXPECT_EQ(tester->sdu_queue.front(), pdu); diff --git a/tests/unittests/sdap/sdap_test.cpp b/tests/unittests/sdap/sdap_test.cpp index 56b1025755..5d9307aa14 100644 --- a/tests/unittests/sdap/sdap_test.cpp +++ b/tests/unittests/sdap/sdap_test.cpp @@ -35,9 +35,9 @@ TEST_F(sdap_test, create_new_entity) TEST_F(sdap_test, test_tx_no_mapping) { const std::array sdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer sdu{sdu_buf}; + byte_buffer sdu = byte_buffer::create(sdu_buf).value(); - sdap->handle_sdu(sdu.deep_copy(), qos_flow_id_t::min); + sdap->handle_sdu(sdu.deep_copy().value(), qos_flow_id_t::min); EXPECT_TRUE(dl_sink1->pdu_queue.empty()); EXPECT_TRUE(dl_sink2->pdu_queue.empty()); @@ -48,14 +48,14 @@ TEST_F(sdap_test, test_tx_no_mapping) TEST_F(sdap_test, test_tx_unknown_mapping) { const std::array sdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer sdu{sdu_buf}; + byte_buffer sdu = byte_buffer::create(sdu_buf).value(); sdap_config sdap_cfg = {}; // add different mapping sdap->add_mapping(qos_flow_id_t::min, drb_id_t::drb1, sdap_cfg, *dl_sink1); - sdap->handle_sdu(sdu.deep_copy(), qos_flow_id_t::max); // different QFI + sdap->handle_sdu(sdu.deep_copy().value(), qos_flow_id_t::max); // different QFI EXPECT_TRUE(dl_sink1->pdu_queue.empty()); EXPECT_TRUE(dl_sink2->pdu_queue.empty()); @@ -65,14 +65,14 @@ TEST_F(sdap_test, test_tx_unknown_mapping) TEST_F(sdap_test, test_tx_known_mapping) { const std::array sdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer sdu{sdu_buf}; + byte_buffer sdu = byte_buffer::create(sdu_buf).value(); sdap_config sdap_cfg = {}; // add mapping sdap->add_mapping(qos_flow_id_t::min, drb_id_t::drb1, sdap_cfg, *dl_sink1); - sdap->handle_sdu(sdu.deep_copy(), qos_flow_id_t::min); + sdap->handle_sdu(sdu.deep_copy().value(), qos_flow_id_t::min); ASSERT_FALSE(dl_sink1->pdu_queue.empty()); EXPECT_TRUE(dl_sink2->pdu_queue.empty()); @@ -85,13 +85,13 @@ TEST_F(sdap_test, test_tx_known_mapping) TEST_F(sdap_test, test_tx_removed_mapping) { const std::array sdu_buf1 = {0x00, 0x01, 0x02, 0x03}; - byte_buffer sdu1{sdu_buf1}; + byte_buffer sdu1 = byte_buffer::create(sdu_buf1).value(); const std::array sdu_buf2 = {0x01, 0x02, 0x03, 0x04}; - byte_buffer sdu2{sdu_buf2}; + byte_buffer sdu2 = byte_buffer::create(sdu_buf2).value(); const std::array sdu_buf3 = {0x02, 0x03, 0x04, 0x05}; - byte_buffer sdu3{sdu_buf3}; + byte_buffer sdu3 = byte_buffer::create(sdu_buf3).value(); const std::array sdu_buf4 = {0x03, 0x04, 0x05, 0x06}; - byte_buffer sdu4{sdu_buf4}; + byte_buffer sdu4 = byte_buffer::create(sdu_buf4).value(); sdap_config sdap_cfg = {}; @@ -99,8 +99,8 @@ TEST_F(sdap_test, test_tx_removed_mapping) sdap->add_mapping(qos_flow_id_t::min, drb_id_t::drb1, sdap_cfg, *dl_sink1); sdap->add_mapping(qos_flow_id_t::max, drb_id_t::drb2, sdap_cfg, *dl_sink2); - sdap->handle_sdu(sdu1.deep_copy(), qos_flow_id_t::min); - sdap->handle_sdu(sdu2.deep_copy(), qos_flow_id_t::max); + sdap->handle_sdu(sdu1.deep_copy().value(), qos_flow_id_t::min); + sdap->handle_sdu(sdu2.deep_copy().value(), qos_flow_id_t::max); ASSERT_FALSE(dl_sink1->pdu_queue.empty()); EXPECT_EQ(dl_sink1->pdu_queue.front(), sdu1); @@ -114,8 +114,8 @@ TEST_F(sdap_test, test_tx_removed_mapping) sdap->remove_mapping(drb_id_t::drb1); - sdap->handle_sdu(sdu3.deep_copy(), qos_flow_id_t::min); - sdap->handle_sdu(sdu4.deep_copy(), qos_flow_id_t::max); + sdap->handle_sdu(sdu3.deep_copy().value(), qos_flow_id_t::min); + sdap->handle_sdu(sdu4.deep_copy().value(), qos_flow_id_t::max); EXPECT_TRUE(dl_sink1->pdu_queue.empty()); @@ -155,14 +155,14 @@ TEST_F(sdap_test, test_rx_unknown_mapping) TEST_F(sdap_test, test_rx_known_mapping) { const std::array pdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer pdu{pdu_buf}; + byte_buffer pdu = byte_buffer::create(pdu_buf).value(); sdap_config sdap_cfg = {}; // add mapping sdap->add_mapping(qos_flow_id_t::min, drb_id_t::drb1, sdap_cfg, *dl_sink1); - sdap->get_sdap_rx_pdu_handler(drb_id_t::drb1).handle_pdu(pdu.deep_copy()); + sdap->get_sdap_rx_pdu_handler(drb_id_t::drb1).handle_pdu(pdu.deep_copy().value()); ASSERT_FALSE(ul_sink->sdu_queue.empty()); EXPECT_EQ(ul_sink->sdu_queue.front(), pdu); diff --git a/tests/unittests/sdap/sdap_tx_test.cpp b/tests/unittests/sdap/sdap_tx_test.cpp index abdd047f60..3089a1aecf 100644 --- a/tests/unittests/sdap/sdap_tx_test.cpp +++ b/tests/unittests/sdap/sdap_tx_test.cpp @@ -82,9 +82,9 @@ TEST_F(sdap_tx_test, create_new_entity) TEST_F(sdap_tx_test, test_tx) { const std::array sdu_buf = {0x00, 0x01, 0x02, 0x03}; - byte_buffer sdu{sdu_buf}; + byte_buffer sdu = byte_buffer::create(sdu_buf).value(); - sdap->handle_sdu(sdu.deep_copy()); + sdap->handle_sdu(sdu.deep_copy().value()); ASSERT_FALSE(tester->pdu_queue.empty()); EXPECT_EQ(tester->pdu_queue.front(), sdu); diff --git a/tests/unittests/security/security_test.cpp b/tests/unittests/security/security_test.cpp index 93560ba026..8941245464 100644 --- a/tests/unittests/security/security_test.cpp +++ b/tests/unittests/security/security_test.cpp @@ -277,7 +277,7 @@ TEST(security_nia1_test, testset1) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 2 @@ -303,7 +303,7 @@ TEST(security_nia1_test, testset2) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 3 @@ -330,7 +330,7 @@ TEST(security_nia1_test, testset3) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 4 @@ -358,7 +358,7 @@ TEST(security_nia1_test, testset4) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 5 @@ -385,7 +385,7 @@ TEST(security_nia1_test, testset5) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 6 @@ -417,7 +417,7 @@ TEST(security_nia1_test, testset6) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA1 Test Set 7 @@ -480,7 +480,7 @@ TEST(security_nia1_test, testset7) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia1(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NEA2 Test Set 1 @@ -691,7 +691,7 @@ TEST(security_nia2_test, testset1) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA2 Test Set 2 @@ -720,7 +720,7 @@ TEST(security_nia2_test, testset2) sec_mac mact_out = {}; security_nia2_cmac(mact_out, key, count_i, bearer, dir, message_view); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); #endif } { @@ -728,7 +728,7 @@ TEST(security_nia2_test, testset2) sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } } @@ -758,7 +758,7 @@ TEST(security_nia2_test, testset3) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA2 Test Set 4 @@ -788,7 +788,7 @@ TEST(security_nia2_test, testset4) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA2 Test Set 5 @@ -819,7 +819,7 @@ TEST(security_nia2_test, testset5) sec_mac mact_out = {}; security_nia2_cmac(mact_out, key, count_i, bearer, dir, message_view); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); #endif } { @@ -827,7 +827,7 @@ TEST(security_nia2_test, testset5) sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } } @@ -858,7 +858,7 @@ TEST(security_nia2_test, testset6) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA2 Test Set 7 @@ -893,7 +893,7 @@ TEST(security_nia2_test, testset7) byte_buffer_view message_view{message}; sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } /// 128-NIA2 Test Set 8 @@ -959,7 +959,7 @@ TEST(security_nia2_test, testset8) sec_mac mact_out = {}; security_nia2_cmac(mact_out, key, count_i, bearer, dir, message_view); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); #endif } { @@ -967,7 +967,7 @@ TEST(security_nia2_test, testset8) sec_mac mact_out = {}; security_nia2_non_cmac(mact_out, key, count_i, bearer, dir, message_view, length); EXPECT_EQ(message_view.length(), length / 8); - EXPECT_EQ(byte_buffer(mact_out), mact_buf); + EXPECT_EQ(byte_buffer::create(mact_out).value(), mact_buf); } } @@ -1175,7 +1175,7 @@ TEST(security_nia3_test, testset1) byte_buffer_view message_view{message}; sec_mac mac_out = {}; security_nia3(mac_out, key, count, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mac_out), mac_buf); + EXPECT_EQ(byte_buffer::create(mac_out).value(), mac_buf); } /// 128-NIA3 Test Set 2 @@ -1203,7 +1203,7 @@ TEST(security_nia3_test, testset2) byte_buffer_view message_view{message}; sec_mac mac_out = {}; security_nia3(mac_out, key, count, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mac_out), mac_buf); + EXPECT_EQ(byte_buffer::create(mac_out).value(), mac_buf); } /// 128-NIA3 Test Set 3 @@ -1232,7 +1232,7 @@ TEST(security_nia3_test, testset3) byte_buffer_view message_view{message}; sec_mac mac_out = {}; security_nia3(mac_out, key, count, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mac_out), mac_buf); + EXPECT_EQ(byte_buffer::create(mac_out).value(), mac_buf); } /// 128-NIA3 Test Set 4 @@ -1265,7 +1265,7 @@ TEST(security_nia3_test, testset4) byte_buffer_view message_view{message}; sec_mac mac_out = {}; security_nia3(mac_out, key, count, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mac_out), mac_buf); + EXPECT_EQ(byte_buffer::create(mac_out).value(), mac_buf); } /// 128-NIA3 Test Set 5 @@ -1306,7 +1306,7 @@ TEST(security_nia3_test, testset5) byte_buffer_view message_view{message}; sec_mac mac_out = {}; security_nia3(mac_out, key, count, bearer, dir, message_view, length); - EXPECT_EQ(byte_buffer(mac_out), mac_buf); + EXPECT_EQ(byte_buffer::create(mac_out).value(), mac_buf); } /// Generation of k_rrc_end and k_rrc_int @@ -1475,9 +1475,10 @@ TEST(short_mac, short_mac_valid) sec_config.integ_algo = integrity_algorithm::nia2; sec_config.k_int = make_sec_key(k_int_cstr); - sec_short_mac_i short_mac = {0xc2, 0x18}; - byte_buffer var_short_mac_input_packed = {0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x18, 0x04}; - bool valid = verify_short_mac(short_mac, var_short_mac_input_packed, sec_config); + sec_short_mac_i short_mac = {0xc2, 0x18}; + byte_buffer var_short_mac_input_packed = + byte_buffer::create({0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x18, 0x04}).value(); + bool valid = verify_short_mac(short_mac, var_short_mac_input_packed, sec_config); ASSERT_EQ(true, valid); } diff --git a/tests/unittests/srsvec/CMakeLists.txt b/tests/unittests/srsvec/CMakeLists.txt index ee7098a7a0..ae762afec5 100644 --- a/tests/unittests/srsvec/CMakeLists.txt +++ b/tests/unittests/srsvec/CMakeLists.txt @@ -69,3 +69,7 @@ add_test(srsvec_clipping_test srsvec_clipping_test) add_executable(srsvec_convolution_test srsvec_convolution_test.cpp) target_link_libraries(srsvec_convolution_test srsvec srslog gtest gtest_main) add_test(srsvec_convolution_test srsvec_convolution_test) + +add_executable(srsvec_unwrap_test srsvec_unwrap_test.cpp) +target_link_libraries(srsvec_unwrap_test srsvec srslog gtest gtest_main) +add_test(srsvec_unwrap_test srsvec_unwrap_test) diff --git a/tests/unittests/srsvec/srsvec_unwrap_test.cpp b/tests/unittests/srsvec/srsvec_unwrap_test.cpp new file mode 100644 index 0000000000..38e16144a0 --- /dev/null +++ b/tests/unittests/srsvec/srsvec_unwrap_test.cpp @@ -0,0 +1,92 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * This file is part of srsRAN. + * + * srsRAN is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsRAN is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/// \file +/// \brief Unwrap test. +/// +/// The test takes an array of complex numbers and checks that the output of the \c unwrap_arguments function returns +/// the unwrapped phase angles. + +#include "srsran/adt/complex.h" +#include "srsran/srsvec/sc_prod.h" +#include "srsran/srsvec/unwrap.h" +#include "fmt/ostream.h" +#include +#include + +using namespace srsran; +using namespace srsvec; + +static constexpr float tolerance = 1.0e-6; + +namespace srsran { + +bool operator==(span lhs, span rhs) +{ + return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](float lhs_val, float rhs_val) { + return (std::abs(lhs_val - rhs_val) < tolerance); + }); +} + +std::ostream& operator<<(std::ostream& os, span data) +{ + fmt::print(os, "{}", data); + return os; +} + +} // namespace srsran + +TEST(UnwrapTest, RampUp) +{ + constexpr unsigned length = 10; + std::array phases = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + srsvec::sc_prod(phases, M_PI / 4, phases); + + std::array c_numbers; + + std::transform(phases.cbegin(), phases.cend(), c_numbers.begin(), [](float a) { return std::polar(1.0F, a); }); + + std::array out; + + unwrap_arguments(out, c_numbers); + + ASSERT_EQ(span(phases), span(out)); +} + +TEST(UnwrapTest, RampDown) +{ + constexpr unsigned length = 10; + std::array phases = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + srsvec::sc_prod(phases, -M_PI / 4, phases); + + std::array c_numbers; + + std::transform(phases.cbegin(), phases.cend(), c_numbers.begin(), [](float a) { return std::polar(1.0F, a); }); + + std::array out; + + unwrap_arguments(out, c_numbers); + + ASSERT_EQ(span(phases), span(out)); +} diff --git a/tests/unittests/support/bit_encoding_test.cpp b/tests/unittests/support/bit_encoding_test.cpp index 022a73c9b9..82ca3b36cf 100644 --- a/tests/unittests/support/bit_encoding_test.cpp +++ b/tests/unittests/support/bit_encoding_test.cpp @@ -74,12 +74,12 @@ void test_bit_encoder() // byte_buffer: [10101000][00001 000][00010 000][00011___] // Written bits: [000 00001][000 00010][000 00011] - byte_buffer vec = {0b1, 0b10, 0b11}; + byte_buffer vec = byte_buffer::create({0b1, 0b10, 0b11}).value(); enc.pack_bytes(vec); TESTASSERT_EQ(4, enc.nof_bytes()); TESTASSERT_EQ(5 + 3 * 8, enc.nof_bits()); TESTASSERT_EQ(5, enc.next_bit_offset()); - byte_buffer vec2 = {0b10101000, 0b00001000, 0b00010000, 0b00011000}; + byte_buffer vec2 = byte_buffer::create({0b10101000, 0b00001000, 0b00010000, 0b00011000}).value(); TESTASSERT(bytes == vec2); // TEST: alignment padding. @@ -136,7 +136,7 @@ void test_bit_encoder() 0x40, // two MSBs contain LSBs of 0x01 }; - TESTASSERT(bytes == byte_buffer{packed_vec}); + TESTASSERT(bytes == byte_buffer::create(packed_vec).value()); } void test_bit_encoder_bool() @@ -146,7 +146,7 @@ void test_bit_encoder_bool() uint8_t dummy = 0; bool bit1 = true; bool bit0 = false; - byte_buffer expected_bytes = {0x02}; + byte_buffer expected_bytes = byte_buffer::create({0x02}).value(); enc.pack(dummy, 6); enc.pack(bit1, 1); @@ -160,7 +160,7 @@ void test_bit_encoder_uint64_aligned() byte_buffer bytes; bit_encoder enc(bytes); uint64_t val64 = 0xc00f00000000f001; - byte_buffer expected_bytes = {0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01}; + byte_buffer expected_bytes = byte_buffer::create({0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01}).value(); TESTASSERT_EQ(0, enc.nof_bytes()); TESTASSERT_EQ(0, enc.nof_bits()); @@ -179,7 +179,7 @@ void test_bit_encoder_uint64_offset() bit_encoder enc(bytes); uint8_t val1 = 1; uint64_t val64 = 0xc00f00000000f001; - byte_buffer expected_bytes = {0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x78, 0x00, 0x80}; + byte_buffer expected_bytes = byte_buffer::create({0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x78, 0x00, 0x80}).value(); TESTASSERT_EQ(0, enc.nof_bytes()); TESTASSERT_EQ(0, enc.nof_bits()); @@ -232,7 +232,7 @@ void test_bit_decoder_empty_buffer() void test_bit_decoder() { - byte_buffer bytes = {0b1, 0b10, 0b11, 0b100}; + byte_buffer bytes = byte_buffer::create({0b1, 0b10, 0b11, 0b100}).value(); bit_decoder dec(bytes); uint32_t val; std::vector vec; @@ -308,9 +308,48 @@ void test_bit_decoder() TESTASSERT_EQ(4 * 8, dec.nof_bits()); } +void test_bit_decoder_bytes() +{ + byte_buffer bytes = byte_buffer::create({0b1, 0b10, 0b11, 0b100}).value(); + bit_decoder dec(bytes); + std::vector vec; + + TESTASSERT_EQ(0, dec.nof_bytes()); + TESTASSERT_EQ(0, dec.nof_bits()); + TESTASSERT(bytes == dec.data()); + + // byte_buffer: [00000001][00000010][00000011][00000100] + // Read bits: [00000001] + vec.resize(1); + TESTASSERT(dec.unpack_bytes(vec)); + TESTASSERT_EQ(1, dec.nof_bytes()); + TESTASSERT_EQ(8, dec.nof_bits()); + TESTASSERT_EQ(0, dec.next_bit_offset()); + TESTASSERT_EQ(0b1, vec[0]); + + // byte_buffer: [00000001][00000010][00000011][00000100] + // Read bits: [00000010][00000011] + vec.resize(2); + TESTASSERT(dec.unpack_bytes(vec)); + TESTASSERT_EQ(3, dec.nof_bytes()); + TESTASSERT_EQ(24, dec.nof_bits()); + TESTASSERT_EQ(0, dec.next_bit_offset()); + TESTASSERT_EQ(0b10, vec[0]); + TESTASSERT_EQ(0b11, vec[1]); + + // byte_buffer: [00000001][00000010][00000011][00000100] + // Read bits: [00000100] + vec.resize(1); + TESTASSERT(dec.unpack_bytes(vec)); + TESTASSERT_EQ(4, dec.nof_bytes()); + TESTASSERT_EQ(32, dec.nof_bits()); + TESTASSERT_EQ(0, dec.next_bit_offset()); + TESTASSERT_EQ(0b100, vec[0]); +} + void test_bit_decoder_bool() { - byte_buffer bytes = {0x02}; + byte_buffer bytes = byte_buffer::create({0x02}).value(); bit_decoder dec(bytes); uint8_t dummy; bool bit1, bit0; @@ -325,7 +364,7 @@ void test_bit_decoder_bool() void test_bit_decoder_uint64_aligned() { - byte_buffer bytes = {0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01}; + byte_buffer bytes = byte_buffer::create({0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01}).value(); bit_decoder dec(bytes); uint64_t val; @@ -342,7 +381,7 @@ void test_bit_decoder_uint64_aligned() void test_bit_decoder_uint64_offset() { - byte_buffer bytes = {0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x78, 0x00, 0x80}; + byte_buffer bytes = byte_buffer::create({0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x78, 0x00, 0x80}).value(); bit_decoder dec(bytes); uint64_t val; @@ -371,6 +410,7 @@ int main() test_bit_encoder_uint64_offset(); test_bit_decoder_empty_buffer(); test_bit_decoder(); + test_bit_decoder_bytes(); test_bit_decoder_bool(); test_bit_decoder_uint64_aligned(); test_bit_decoder_uint64_offset();