From 701482990a3fb602c5e3d1bbbe4f454c182bd28a Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Fri, 8 Mar 2024 09:43:00 +0100 Subject: [PATCH 01/77] mac: add separator in SDU log --- lib/mac/mac_dl/dl_sch_pdu_assembler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp b/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp index 0f71b2d96e..1bd91f64c2 100644 --- a/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp +++ b/lib/mac/mac_dl/dl_sch_pdu_assembler.cpp @@ -192,7 +192,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; @@ -227,10 +228,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: From f4c61373c3f3470f5e21de6300ba52ea55830cf8 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 8 Mar 2024 17:42:15 +0100 Subject: [PATCH 02/77] du-high: extend du_high_test to account for ue context setup --- .../integrationtests/du_high/du_high_test.cpp | 85 +++++++++++-- .../du_high/test_utils/du_high_test_bench.cpp | 115 +++++++++++++++++- .../du_high/test_utils/du_high_test_bench.h | 21 +++- .../f1ap/f1ap_test_message_validators.cpp | 26 ++++ .../f1ap/f1ap_test_message_validators.h | 8 +- tests/test_doubles/f1u/dummy_f1u_du_gateway.h | 7 +- tests/test_doubles/mac/mac_test_messages.cpp | 72 +++++++++++ tests/test_doubles/mac/mac_test_messages.h | 12 ++ .../f1ap/du/f1ap_du_test_helpers.cpp | 18 +++ .../unittests/f1ap/du/f1ap_du_test_helpers.h | 6 + 10 files changed, 353 insertions(+), 17 deletions(-) diff --git a/tests/integrationtests/du_high/du_high_test.cpp b/tests/integrationtests/du_high/du_high_test.cpp index df45559dc9..c99a1bf299 100644 --- a/tests/integrationtests/du_high/du_high_test.cpp +++ b/tests/integrationtests/du_high/du_high_test.cpp @@ -62,6 +62,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. @@ -77,19 +112,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; @@ -101,6 +123,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 d9f62048b4..6bd04f9158 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 @@ -203,6 +203,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. @@ -211,7 +215,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() @@ -233,4 +329,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 ba7d525e0e..a7a0f9ce92 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 @@ -44,14 +44,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; @@ -64,6 +72,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/test_doubles/f1ap/f1ap_test_message_validators.cpp b/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp index 467fd18461..41a82ba0b6 100644 --- a/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp +++ b/tests/test_doubles/f1ap/f1ap_test_message_validators.cpp @@ -24,3 +24,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 9b78394941..72cd242781 100644 --- a/tests/test_doubles/f1ap/f1ap_test_message_validators.h +++ b/tests/test_doubles/f1ap/f1ap_test_message_validators.h @@ -10,6 +10,8 @@ #pragma once +#include "srsran/f1ap/common/f1ap_ue_id.h" +#include "srsran/ran/lcid.h" #include "srsran/ran/rnti.h" namespace srsran { @@ -20,5 +22,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 79c8d34a12..f688105a89 100644 --- a/tests/test_doubles/f1u/dummy_f1u_du_gateway.h +++ b/tests/test_doubles/f1u/dummy_f1u_du_gateway.h @@ -39,6 +39,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, @@ -48,7 +51,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 18c765ef0d..784f0187bb 100644 --- a/tests/test_doubles/mac/mac_test_messages.cpp +++ b/tests/test_doubles/mac/mac_test_messages.cpp @@ -9,6 +9,7 @@ */ #include "mac_test_messages.h" +#include "srsran/scheduler/scheduler_slot_handler.h" using namespace srsran; @@ -19,3 +20,74 @@ mac_rx_data_indication srsran::test_helpers::create_ccch_message(slot_point sl_r to_du_cell_index(0), {mac_rx_pdu{rnti, 0, 0, {0x34, 0x1e, 0x4f, 0xc0, 0x4f, 0xa6, 0x06, 0x3f, 0x00, 0x00, 0x00}}}}; } + +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, {(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}}}}; +} + +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 876b80e64e..739ae7d380 100644 --- a/tests/test_doubles/mac/mac_test_messages.h +++ b/tests/test_doubles/mac/mac_test_messages.h @@ -10,13 +10,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/f1ap/du/f1ap_du_test_helpers.cpp b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp index 73e06c273c..4f2f09d879 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp @@ -170,6 +170,24 @@ f1ap_message srsran::srs_du::generate_ue_context_release_command() 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; +} + namespace { class dummy_f1ap_tx_pdu_notifier : public f1ap_message_notifier diff --git a/tests/unittests/f1ap/du/f1ap_du_test_helpers.h b/tests/unittests/f1ap/du/f1ap_du_test_helpers.h index 278fe80c4c..417dafb823 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.h +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.h @@ -142,6 +142,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: From 2ca39d5257c90a391a21058d611a6e744126f3b5 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 8 Mar 2024 18:37:28 +0100 Subject: [PATCH 03/77] du-high: disable mac TX sdu builder during UE context release --- lib/du_manager/du_ue/du_bearer.cpp | 1 + lib/du_manager/du_ue/du_ue_adapters.h | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/du_manager/du_ue/du_bearer.cpp b/lib/du_manager/du_ue/du_bearer.cpp index 0d974e00e3..6d2e001708 100644 --- a/lib/du_manager/du_ue/du_bearer.cpp +++ b/lib/du_manager/du_ue/du_bearer.cpp @@ -95,6 +95,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() diff --git a/lib/du_manager/du_ue/du_ue_adapters.h b/lib/du_manager/du_ue/du_ue_adapters.h index db6e7076c0..f7be0a59a2 100644 --- a/lib/du_manager/du_ue/du_ue_adapters.h +++ b/lib/du_manager/du_ue/du_ue_adapters.h @@ -220,19 +220,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; }; From 9489d6db6fefa2215f87c3ff683d0313e241eb28 Mon Sep 17 00:00:00 2001 From: sauka Date: Mon, 11 Mar 2024 15:40:48 +0200 Subject: [PATCH 04/77] gnb: fix cpu manager --- lib/support/cpu_architecture_info.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/support/cpu_architecture_info.cpp b/lib/support/cpu_architecture_info.cpp index 214dffcf68..c9b79a879d 100644 --- a/lib/support/cpu_architecture_info.cpp +++ b/lib/support/cpu_architecture_info.cpp @@ -104,9 +104,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; @@ -131,7 +145,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()) { From 26a236dad0ebfb97423acb89f30f34e34a8de8b0 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Wed, 6 Mar 2024 11:02:19 +0100 Subject: [PATCH 05/77] sched: add ue id and rnti to cell grid allocator logs --- .../ue_scheduling/ue_cell_grid_allocator.cpp | 122 ++++++++++++------ 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp index d4f83a8033..3b8adb2c4e 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -80,11 +80,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; @@ -106,14 +107,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; } @@ -127,30 +133,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; @@ -471,13 +491,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; @@ -496,18 +519,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; } @@ -517,29 +543,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; } @@ -561,8 +594,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; @@ -585,7 +619,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; } @@ -593,6 +629,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); @@ -601,19 +638,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; } @@ -623,7 +662,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; } @@ -671,9 +710,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, From f78b5a2bd80c563b885d3ff989bdae3b5eb44e26 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Tue, 6 Feb 2024 12:15:29 +0100 Subject: [PATCH 06/77] f1ap: capture DRB QoS information when setting up DRBs --- .../f1ap/du/f1ap_du_ue_context_update.h | 29 ++++++++++++++++--- .../du/procedures/f1ap_du_ue_context_common.h | 25 ++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) 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 b7f6235697..012332c2d2 100644 --- a/include/srsran/f1ap/du/f1ap_du_ue_context_update.h +++ b/include/srsran/f1ap/du/f1ap_du_ue_context_update.h @@ -37,12 +37,33 @@ struct f1ap_ue_context_creation_response { rnti_t crnti; }; +/// \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 f1ap_gbr_qos_flow_info { + /// 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; +}; + /// \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/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h index 7ec2aa15fb..dbc817fc0d 100644 --- a/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h +++ b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h @@ -52,6 +52,31 @@ f1ap_drb_to_setup make_drb_to_setup(const Asn1Type& drb_item) 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; } From f5fabee611015f15d96ffb9016e5d38cd2c6e076 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Fri, 16 Feb 2024 09:35:32 +0100 Subject: [PATCH 07/77] ran: add mapping of 5QI to QoS characteristics --- include/srsran/ran/qos/five_qi_qos_mapping.h | 51 ++++++++++++++ lib/ran/CMakeLists.txt | 1 + lib/ran/qos/five_qi_qos_mapping.cpp | 74 ++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 include/srsran/ran/qos/five_qi_qos_mapping.h create mode 100644 lib/ran/qos/five_qi_qos_mapping.cpp 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..e0f9e03548 --- /dev/null +++ b/include/srsran/ran/qos/five_qi_qos_mapping.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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/lib/ran/CMakeLists.txt b/lib/ran/CMakeLists.txt index db2a3b793a..167bed187d 100644 --- a/lib/ran/CMakeLists.txt +++ b/lib/ran/CMakeLists.txt @@ -36,6 +36,7 @@ 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 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..4e9aad199e --- /dev/null +++ b/lib/ran/qos/five_qi_qos_mapping.cpp @@ -0,0 +1,74 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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 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(), "5QI={} to QoS characteristics mapping not defined.", five_qi); + return qos_char->second; +} From 1d73914d98bbdc73048ec06e3e10726d60bfe070 Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Tue, 20 Feb 2024 13:24:01 +0100 Subject: [PATCH 08/77] du_mgr: pass QoS information based on 5QI while creating a DRB --- .../f1ap/du/f1ap_du_ue_context_update.h | 21 ++---------- include/srsran/ran/qos/qos_info.h | 33 +++++++++++++++++++ lib/du_manager/du_ue/du_bearer.cpp | 16 +++++---- lib/du_manager/du_ue/du_bearer.h | 10 +++++- .../procedures/ue_configuration_procedure.cpp | 7 +++- lib/ran/qos/five_qi_qos_mapping.cpp | 5 ++- .../du_manager/du_ue/du_bearer_test.cpp | 4 ++- 7 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 include/srsran/ran/qos/qos_info.h 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 012332c2d2..be42b35851 100644 --- a/include/srsran/f1ap/du/f1ap_du_ue_context_update.h +++ b/include/srsran/f1ap/du/f1ap_du_ue_context_update.h @@ -15,6 +15,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 { @@ -37,24 +38,6 @@ struct f1ap_ue_context_creation_response { rnti_t crnti; }; -/// \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 f1ap_gbr_qos_flow_info { - /// 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; -}; - /// \brief DRB to be setup in the UE context. struct f1ap_drb_to_setup { drb_id_t drb_id; @@ -63,7 +46,7 @@ struct f1ap_drb_to_setup { 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; + optional gbr_flow_info; std::vector uluptnl_info_list; }; diff --git a/include/srsran/ran/qos/qos_info.h b/include/srsran/ran/qos/qos_info.h new file mode 100644 index 0000000000..77422d27bc --- /dev/null +++ b/include/srsran/ran/qos/qos_info.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +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/lib/du_manager/du_ue/du_bearer.cpp b/lib/du_manager/du_ue/du_bearer.cpp index 6d2e001708..1256c42d04 100644 --- a/lib/du_manager/du_ue/du_bearer.cpp +++ b/lib/du_manager/du_ue/du_bearer.cpp @@ -114,7 +114,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"); @@ -133,11 +135,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 1d6ffcf16b..9bf33275e1 100644 --- a/lib/du_manager/du_ue/du_bearer.h +++ b/lib/du_manager/du_ue/du_bearer.h @@ -16,6 +16,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" @@ -98,6 +100,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(); @@ -114,7 +120,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/procedures/ue_configuration_procedure.cpp b/lib/du_manager/procedures/ue_configuration_procedure.cpp index 1ce434d58d..0bb516314e 100644 --- a/lib/du_manager/procedures/ue_configuration_procedure.cpp +++ b/lib/du_manager/procedures/ue_configuration_procedure.cpp @@ -146,6 +146,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, @@ -157,7 +160,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/ran/qos/five_qi_qos_mapping.cpp b/lib/ran/qos/five_qi_qos_mapping.cpp index 4e9aad199e..4c4ca17f4f 100644 --- a/lib/ran/qos/five_qi_qos_mapping.cpp +++ b/lib/ran/qos/five_qi_qos_mapping.cpp @@ -65,10 +65,9 @@ static const std::unordered_map five_qi_to_qos_m // clang-format on }; -qos_characteristics get_5qi_to_qos_characteristics_mapping(five_qi_t five_qi) +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(), "5QI={} to QoS characteristics mapping not defined.", 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/tests/unittests/du_manager/du_ue/du_bearer_test.cpp b/tests/unittests/du_manager/du_ue/du_bearer_test.cpp index f42586f768..7255f0be79 100644 --- a/tests/unittests/du_manager/du_ue/du_bearer_test.cpp +++ b/tests/unittests/du_manager/du_ue/du_bearer_test.cpp @@ -50,7 +50,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) From 486376c0f4730e17ba69b958c0a2f1392fd0ac5c Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Thu, 7 Mar 2024 15:58:44 +0100 Subject: [PATCH 09/77] f1ap,du_mgr,sched: propagate QoS information associated with DRB to scheduler --- include/srsran/scheduler/scheduler_configurator.h | 14 ++++++++++++++ .../converters/scheduler_configuration_helpers.cpp | 3 +++ lib/f1ap/du/procedures/f1ap_du_ue_context_common.h | 6 ++---- lib/scheduler/config/ue_configuration.cpp | 4 ++++ lib/scheduler/config/ue_configuration.h | 3 +++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/srsran/scheduler/scheduler_configurator.h b/include/srsran/scheduler/scheduler_configurator.h index f492c351ae..c021c97c12 100644 --- a/include/srsran/scheduler/scheduler_configurator.h +++ b/include/srsran/scheduler/scheduler_configurator.h @@ -18,6 +18,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" @@ -102,6 +104,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. @@ -112,6 +124,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/lib/du_manager/converters/scheduler_configuration_helpers.cpp b/lib/du_manager/converters/scheduler_configuration_helpers.cpp index 0477d7f86e..0e52b7599d 100644 --- a/lib/du_manager/converters/scheduler_configuration_helpers.cpp +++ b/lib/du_manager/converters/scheduler_configuration_helpers.cpp @@ -98,6 +98,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/f1ap/du/procedures/f1ap_du_ue_context_common.h b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h index dbc817fc0d..fcc33ff543 100644 --- a/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h +++ b/lib/f1ap/du/procedures/f1ap_du_ue_context_common.h @@ -43,10 +43,8 @@ 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)); diff --git a/lib/scheduler/config/ue_configuration.cpp b/lib/scheduler/config/ue_configuration.cpp index c7d8bb5ac9..f8ea8eed72 100644 --- a/lib/scheduler/config/ue_configuration.cpp +++ b/lib/scheduler/config/ue_configuration.cpp @@ -766,6 +766,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 6bca03e3ca..0e68b52010 100644 --- a/lib/scheduler/config/ue_configuration.h +++ b/lib/scheduler/config/ue_configuration.h @@ -233,6 +233,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; From 2a4724c50b30f4c1361b927e49059a86cf189f84 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Fri, 8 Mar 2024 23:05:17 +0100 Subject: [PATCH 10/77] support: unpack_bytes from current position --- lib/support/bit_encoding.cpp | 2 +- tests/unittests/support/bit_encoding_test.cpp | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/support/bit_encoding.cpp b/lib/support/bit_encoding.cpp index 257976a985..6882ecb5df 100644 --- a/lib/support/bit_encoding.cpp +++ b/lib/support/bit_encoding.cpp @@ -149,7 +149,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/tests/unittests/support/bit_encoding_test.cpp b/tests/unittests/support/bit_encoding_test.cpp index a809ffdd8d..84616ddbc5 100644 --- a/tests/unittests/support/bit_encoding_test.cpp +++ b/tests/unittests/support/bit_encoding_test.cpp @@ -296,6 +296,45 @@ void test_bit_decoder() TESTASSERT_EQ(4 * 8, dec.nof_bits()); } +void test_bit_decoder_bytes() +{ + byte_buffer bytes = {0b1, 0b10, 0b11, 0b100}; + 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}; @@ -359,6 +398,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(); From d41ab770ded8093520e61ad70e7036964015f97d Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Fri, 8 Mar 2024 23:20:15 +0100 Subject: [PATCH 11/77] gtpu: unpack information elements of error indication message --- lib/gtpu/gtpu_echo_rx_impl.h | 14 +- lib/gtpu/gtpu_pdu.cpp | 71 +++++++++- lib/gtpu/gtpu_pdu.h | 122 +++++++++++++++++- lib/gtpu/gtpu_tunnel_ngu_rx.h | 4 +- tests/unittests/gtpu/gtpu_echo_test.cpp | 19 +++ tests/unittests/gtpu/gtpu_test.cpp | 4 +- tests/unittests/gtpu/gtpu_test_shared.h | 3 + tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp | 2 +- 8 files changed, 224 insertions(+), 15 deletions(-) diff --git a/lib/gtpu/gtpu_echo_rx_impl.h b/lib/gtpu/gtpu_echo_rx_impl.h index 16eabebb89..f1dd4a4b48 100644 --- a/lib/gtpu/gtpu_echo_rx_impl.h +++ b/lib/gtpu/gtpu_echo_rx_impl.h @@ -61,15 +61,23 @@ 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"); + 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: // 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. 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 1881f1e943..d74f1ff963 100644 --- a/lib/gtpu/gtpu_pdu.cpp +++ b/lib/gtpu/gtpu_pdu.cpp @@ -140,6 +140,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) { @@ -388,12 +428,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 35fa4df1b7..15d83ebf99 100644 --- a/lib/gtpu/gtpu_pdu.h +++ b/lib/gtpu/gtpu_pdu.h @@ -13,6 +13,7 @@ #include "srsran/adt/byte_buffer.h" #include "srsran/adt/optional.h" #include "srsran/adt/static_vector.h" +#include "srsran/support/io/transport_layer_address.h" #include "fmt/format.h" #include @@ -156,13 +157,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 { @@ -253,11 +276,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 @@ -317,4 +355,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_ngu_rx.h b/lib/gtpu/gtpu_tunnel_ngu_rx.h index 0016100db6..951135e2b9 100644 --- a/lib/gtpu/gtpu_tunnel_ngu_rx.h +++ b/lib/gtpu/gtpu_tunnel_ngu_rx.h @@ -109,14 +109,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/tests/unittests/gtpu/gtpu_echo_test.cpp b/tests/unittests/gtpu/gtpu_echo_test.cpp index eda8a0be20..67e79eef99 100644 --- a/tests/unittests/gtpu/gtpu_echo_test.cpp +++ b/tests/unittests/gtpu/gtpu_echo_test.cpp @@ -134,6 +134,25 @@ TEST_F(gtpu_echo_test, rx_echo_req_tx_echo_rep) 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 = {gtpu_error_indication}; + + 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 551cdc979c..29dce17826 100644 --- a/tests/unittests/gtpu/gtpu_test.cpp +++ b/tests/unittests/gtpu/gtpu_test.cpp @@ -104,7 +104,7 @@ 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); @@ -180,7 +180,7 @@ TEST_F(gtpu_test, pack_unpack_ext_hdr) 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); diff --git a/tests/unittests/gtpu/gtpu_test_shared.h b/tests/unittests/gtpu/gtpu_test_shared.h index 4473c8170e..68b79c8a47 100644 --- a/tests/unittests/gtpu/gtpu_test_shared.h +++ b/tests/unittests/gtpu/gtpu_test_shared.h @@ -73,4 +73,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_test.cpp b/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp index f5b210f0de..e9ef2de96d 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp @@ -148,7 +148,7 @@ TEST_F(gtpu_tunnel_ngu_test, rx_sdu) 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); }; From 74403ec43e53ac3434d2899f4817f416d212adc6 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Mon, 11 Mar 2024 13:06:19 +0100 Subject: [PATCH 12/77] gtpu: remove unused includes --- lib/gtpu/gtpu_pdu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/gtpu/gtpu_pdu.h b/lib/gtpu/gtpu_pdu.h index 15d83ebf99..635e4adf9f 100644 --- a/lib/gtpu/gtpu_pdu.h +++ b/lib/gtpu/gtpu_pdu.h @@ -11,9 +11,7 @@ #include "gtpu_tunnel_logger.h" #include "srsran/adt/byte_buffer.h" -#include "srsran/adt/optional.h" #include "srsran/adt/static_vector.h" -#include "srsran/support/io/transport_layer_address.h" #include "fmt/format.h" #include From 52c76f8650c5c9a8f36bfab058842a2496b8a283 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Mon, 11 Mar 2024 13:27:44 +0100 Subject: [PATCH 13/77] gtpu: Update comment on handling of error indications --- lib/gtpu/gtpu_echo_rx_impl.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/gtpu/gtpu_echo_rx_impl.h b/lib/gtpu/gtpu_echo_rx_impl.h index f1dd4a4b48..7474492888 100644 --- a/lib/gtpu/gtpu_echo_rx_impl.h +++ b/lib/gtpu/gtpu_echo_rx_impl.h @@ -70,12 +70,15 @@ class gtpu_echo_rx : public gtpu_tunnel_base_rx return; } logger.log_info("Received error indication from peer. {}", err_ind); - // TODO: implement handling: - // 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. + // 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: From d65d62f71f3d6c6c0676a50da4f4e0b84378ec46 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 12 Mar 2024 12:12:07 +0100 Subject: [PATCH 14/77] phy: fix concurrency issue in PUSCH processor phy: review doc --- .../pusch/pusch_decoder_impl.cpp | 62 +++++++++++++++++++ .../pusch/pusch_decoder_impl.h | 46 ++++++++++++++ 2 files changed, 108 insertions(+) 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 1930acb0de..40f5aa9c1c 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.cpp @@ -79,6 +79,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; @@ -121,6 +127,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 " @@ -134,6 +146,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); @@ -176,6 +194,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. @@ -201,6 +225,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, @@ -219,9 +244,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."); @@ -323,6 +371,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(); @@ -373,6 +427,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 1622928655..d4d09a4a29 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_decoder_impl.h @@ -18,6 +18,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 { @@ -96,6 +97,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. From 511725e724ada7d57ed0895a085b035b241fa298 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 11 Mar 2024 17:23:11 +0100 Subject: [PATCH 15/77] phy: fix PUSCH processor benchmark --- .../channel_processors/pusch/factories.h | 3 +- .../channel_processors/pusch/factories.cpp | 17 ++-- .../pusch/pusch_processor_pool.h | 21 ++++- .../pusch/pusch_processor_benchmark.cpp | 77 ++++++------------- 4 files changed, 56 insertions(+), 62 deletions(-) diff --git a/include/srsran/phy/upper/channel_processors/pusch/factories.h b/include/srsran/phy/upper/channel_processors/pusch/factories.h index 428f80d3bf..dca267e02c 100644 --- a/include/srsran/phy/upper/channel_processors/pusch/factories.h +++ b/include/srsran/phy/upper/channel_processors/pusch/factories.h @@ -98,7 +98,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/lib/phy/upper/channel_processors/pusch/factories.cpp b/lib/phy/upper/channel_processors/pusch/factories.cpp index 4a28eccf04..1ec7baeb51 100644 --- a/lib/phy/upper/channel_processors/pusch/factories.cpp +++ b/lib/phy/upper/channel_processors/pusch/factories.cpp @@ -215,8 +215,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."); } @@ -232,7 +234,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 @@ -246,7 +248,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(); } @@ -254,6 +256,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 @@ -297,9 +300,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_processor_pool.h b/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h index f6be8e0b7e..38dc1d0993 100644 --- a/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pusch/pusch_processor_pool.h @@ -97,7 +97,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_) { @@ -113,11 +114,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; } @@ -129,6 +143,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/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp index f89381d193..76170ffa9d 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 @@ -29,9 +29,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; @@ -124,12 +122,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; @@ -150,7 +145,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. @@ -625,7 +620,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; @@ -652,8 +647,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); @@ -674,34 +667,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); @@ -709,11 +695,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; } } @@ -822,8 +804,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); @@ -838,11 +821,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. @@ -860,21 +840,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)); } }); From 8aedae5245b68f88159f681a44249bb046697de2 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 11 Mar 2024 17:47:02 +0100 Subject: [PATCH 16/77] phy: fix PDSCH benchmark --- .../channel_processor_factories.h | 3 ++- .../channel_processor_factories.cpp | 16 ++++++++++------ .../channel_processors/pdsch_processor_pool.h | 10 ++++++++-- .../pdsch_processor_benchmark.cpp | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) 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 9b962f1d25..d444fbf3e6 100644 --- a/include/srsran/phy/upper/channel_processors/channel_processor_factories.h +++ b/include/srsran/phy/upper/channel_processors/channel_processor_factories.h @@ -173,7 +173,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/lib/phy/upper/channel_processors/channel_processor_factories.cpp b/lib/phy/upper/channel_processors/channel_processor_factories.cpp index 0a674b9f76..0970ff5270 100644 --- a/lib/phy/upper/channel_processors/channel_processor_factories.cpp +++ b/lib/phy/upper/channel_processors/channel_processor_factories.cpp @@ -454,8 +454,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, @@ -471,7 +473,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 @@ -482,7 +484,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(); } @@ -490,6 +492,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 @@ -943,9 +946,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_processor_pool.h b/lib/phy/upper/channel_processors/pdsch_processor_pool.h index 142a7aa92e..0eaa2d6dd8 100644 --- a/lib/phy/upper/channel_processors/pdsch_processor_pool.h +++ b/lib/phy/upper/channel_processors/pdsch_processor_pool.h @@ -88,7 +88,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_) { @@ -103,7 +104,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()) { @@ -119,6 +124,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/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp index 89f0fab04d..033fec463d 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pdsch_processor_benchmark.cpp @@ -627,7 +627,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; From 1e1c4a18e2d7c6c6f59fb9aedcc4cd64e4e29548 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 7 Mar 2024 15:26:28 +0100 Subject: [PATCH 17/77] phy: abstract TA estimator in different component --- .../time_alignment_estimator.h | 45 ++++++++++++++ .../time_alignment_estimator_factories.h | 34 +++++++++++ .../time_alignment_measurement.h | 27 ++++++++ .../signal_processor_factories.h | 3 +- lib/phy/support/CMakeLists.txt | 2 + .../time_alignment_estimator_dft_impl.cpp | 61 +++++++++++++++++++ .../time_alignment_estimator_dft_impl.h | 46 ++++++++++++++ .../time_alignment_estimator_factories.cpp | 50 +++++++++++++++ .../port_channel_estimator_average_impl.cpp | 36 ++++------- .../port_channel_estimator_average_impl.h | 18 +++--- .../signal_processor_factories.cpp | 20 +++--- lib/phy/upper/upper_phy_factories.cpp | 8 ++- .../pusch/pusch_processor_benchmark.cpp | 6 +- .../pucch_processor_format1_vectortest.cpp | 6 +- .../pucch_processor_format2_vectortest.cpp | 6 +- ...pucch_processor_validator_format1_test.cpp | 6 +- ...pucch_processor_validator_format2_test.cpp | 6 +- .../pusch/pusch_processor_validator_test.cpp | 6 +- .../pusch/pusch_processor_vectortest.cpp | 8 ++- .../dmrs_pucch_processor_test.cpp | 6 +- .../dmrs_pusch_estimator_test.cpp | 6 +- .../port_channel_estimator_test.cpp | 6 +- 22 files changed, 353 insertions(+), 59 deletions(-) create mode 100644 include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h create mode 100644 include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h create mode 100644 include/srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h create mode 100644 lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.cpp create mode 100644 lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.h create mode 100644 lib/phy/support/time_alignment_estimator/time_alignment_estimator_factories.cpp 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..a0750435b5 --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator.h @@ -0,0 +1,45 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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..b08642437b --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_estimator_factories.h @@ -0,0 +1,34 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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..7e00b47dec --- /dev/null +++ b/include/srsran/phy/support/time_alignment_estimator/time_alignment_measurement.h @@ -0,0 +1,27 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +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/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/lib/phy/support/CMakeLists.txt b/lib/phy/support/CMakeLists.txt index c5fa28becc..01968a373a 100644 --- a/lib/phy/support/CMakeLists.txt +++ b/lib/phy/support/CMakeLists.txt @@ -8,6 +8,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..4bdbddc298 --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.cpp @@ -0,0 +1,61 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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..1008f3147d --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_dft_impl.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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..d148e164b7 --- /dev/null +++ b/lib/phy/support/time_alignment_estimator/time_alignment_estimator_factories.cpp @@ -0,0 +1,50 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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/signal_processors/port_channel_estimator_average_impl.cpp b/lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp index 0801bbbcf8..e8beca6f4d 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 @@ -160,16 +160,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) @@ -211,7 +213,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); @@ -302,7 +303,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); @@ -396,7 +397,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; @@ -413,19 +415,5 @@ 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++]; - }); - - 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)); - if (observed_max_delay.second >= observed_max_advance.second) { - return static_cast(observed_max_delay.first); - } - return -static_cast(HALF_CP_LENGTH - observed_max_advance.first); + return ta_estimator.estimate(pilots_lse, re_mask, scs).time_alignment; } 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 05a821c3a8..56b9cda03d 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 @@ -12,6 +12,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" @@ -37,17 +38,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. @@ -76,8 +74,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 7b93d8ffdf..a85e308a2b 100644 --- a/lib/phy/upper/signal_processors/signal_processor_factories.cpp +++ b/lib/phy/upper/signal_processors/signal_processor_factories.cpp @@ -22,6 +22,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; @@ -223,10 +224,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 @@ -234,17 +235,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 @@ -308,9 +304,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/upper_phy_factories.cpp b/lib/phy/upper/upper_phy_factories.cpp index 3ae8c4d0e4..052b29c901 100644 --- a/lib/phy/upper/upper_phy_factories.cpp +++ b/lib/phy/upper/upper_phy_factories.cpp @@ -335,9 +335,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(); @@ -411,7 +415,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/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pusch/pusch_processor_benchmark.cpp index 76170ffa9d..7cd9f7d230 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 @@ -559,9 +559,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. 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 63042c0fa1..10b7cb9336 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 @@ -81,9 +81,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 10d1872b89..dd9fad53af 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 @@ -77,9 +77,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 09f01fc831..d7ceb49e59 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 @@ -208,9 +208,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 332f363fae..9b8d293292 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 @@ -264,9 +264,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 6950f17c44..77163dde4a 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 @@ -190,9 +190,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 7132e5b809..7db3ca3b73 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 @@ -217,9 +217,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/dmrs_pucch_processor_test.cpp b/tests/unittests/phy/upper/signal_processors/dmrs_pucch_processor_test.cpp index 01b8a115f9..f58aed6e38 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 @@ -63,9 +63,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 ac8ceb665d..5b737a9511 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 @@ -80,9 +80,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/port_channel_estimator_test.cpp b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test.cpp index fd5444ad5b..fd31e3a6be 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 @@ -55,7 +55,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); } } From 059c75c2f87fe3719659b09efef31a07eba97350 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 23 Feb 2024 20:14:58 +0100 Subject: [PATCH 18/77] phy: initial SRS estimator phy: more SRS estimator development phy: more SRS development phy: more SRS development phy: more SRS development phy: more SRS development phy: more SRS development phy: update test vectors and fix issues --- .../upper/signal_processors/srs/formatters.h | 47 +++++++ .../signal_processors/srs/srs_estimator.h | 35 +++++ .../srs/srs_estimator_configuration.h | 35 +++++ .../srs/srs_estimator_factory.h | 35 +++++ .../srs/srs_estimator_result.h | 28 ++++ include/srsran/ran/srs/srs_channel_matrix.h | 17 ++- include/srsran/ran/srs/srs_information.h | 45 +++++++ .../ran/srs/srs_resource_configuration.h | 122 ++++++++++++++++++ .../srsran/ran/srs/srs_resource_formatter.h | 61 +++++++++ .../upper/signal_processors/CMakeLists.txt | 6 +- .../srs/srs_estimator_factory.cpp | 45 +++++++ .../srs/srs_estimator_generic_impl.cpp | 84 ++++++++++++ .../srs/srs_estimator_generic_impl.h | 65 ++++++++++ lib/ran/CMakeLists.txt | 1 + lib/ran/srs/srs_information.cpp | 95 ++++++++++++++ .../upper/signal_processors/CMakeLists.txt | 4 + .../srs/srs_estimator_test_data.h | 109 ++++++++++++++++ .../srs/srs_estimator_test_data.tar.gz | 3 + .../srs/srs_estimator_vectortest.cpp | 79 ++++++++++++ 19 files changed, 905 insertions(+), 11 deletions(-) create mode 100644 include/srsran/phy/upper/signal_processors/srs/formatters.h create mode 100644 include/srsran/phy/upper/signal_processors/srs/srs_estimator.h create mode 100644 include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h create mode 100644 include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h create mode 100644 include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h create mode 100644 include/srsran/ran/srs/srs_information.h create mode 100644 include/srsran/ran/srs/srs_resource_configuration.h create mode 100644 include/srsran/ran/srs/srs_resource_formatter.h create mode 100644 lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp create mode 100644 lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp create mode 100644 lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h create mode 100644 lib/ran/srs/srs_information.cpp create mode 100644 tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.h create mode 100644 tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz create mode 100644 tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp 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..299c81f343 --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/formatters.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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..e4bdabf29e --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2021-2023 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +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..fa86a1cf4c --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/adt/optional.h" +#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 { + +/// \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_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..d2574c94e6 --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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; + + /// \brief Creates a sounding reference signal based propagation channel estimator. + /// \return + 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..4386210426 --- /dev/null +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h @@ -0,0 +1,28 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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/srs/srs_channel_matrix.h b/include/srsran/ran/srs/srs_channel_matrix.h index be50419024..a1fc69bf82 100644 --- a/include/srsran/ran/srs/srs_channel_matrix.h +++ b/include/srsran/ran/srs/srs_channel_matrix.h @@ -124,10 +124,11 @@ class srs_channel_matrix return *this; } - /// \brief Overload equality comparison operator. - /// \param[in] other Channel matrix to compare against. + /// \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 both channel matrices are exactly the same, \c false otherwise. - bool operator==(const srs_channel_matrix& other) const + bool is_near_equal_to(const srs_channel_matrix& other, float tolerance) const { unsigned nof_rx_ports = get_nof_rx_ports(); unsigned nof_tx_ports = get_nof_tx_ports(); @@ -139,9 +140,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; } } @@ -150,9 +152,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..6be7e04c24 --- /dev/null +++ b/include/srsran/ran/srs/srs_information.h @@ -0,0 +1,45 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srs_resource_configuration.h" +namespace srsran { + +/// \brief Collects Sounding Reference Signal information. +/// +/// Calculates derived parameters that are used for the SRS sequence generation and mapping in TS38.211 Sections +/// 6.4.1.4.2 and 6.4.1.4.3. +/// +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 0-based antenna port index. +/// \param i_symbol OFDM symbol index within the slot. +/// \return SRS information if the parameters are valid. +/// \remark An assertion is triggered if any resource parameter is invalid. +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..ec3808fd0c --- /dev/null +++ b/include/srsran/ran/srs/srs_resource_configuration.h @@ -0,0 +1,122 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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 { + /// Enum 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 }; + + /// 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. + uint8_t 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). + uint8_t 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). + uint16_t 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). + uint8_t 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. + uint8_t 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$). + uint8_t 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$. + uint8_t 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). + uint8_t 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). + uint16_t 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). + uint8_t 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..cb03732f99 --- /dev/null +++ b/include/srsran/ran/srs/srs_resource_formatter.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#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_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_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/lib/phy/upper/signal_processors/CMakeLists.txt b/lib/phy/upper/signal_processors/CMakeLists.txt index 455ee150fe..3d98ff241f 100644 --- a/lib/phy/upper/signal_processors/CMakeLists.txt +++ b/lib/phy/upper/signal_processors/CMakeLists.txt @@ -7,14 +7,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/srs/srs_estimator_factory.cpp b/lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp new file mode 100644 index 0000000000..6f3f84d2bf --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_factory.cpp @@ -0,0 +1,45 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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..4dcfa41bab --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp @@ -0,0 +1,84 @@ +/* + * + * Copyright 2021-2023 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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) +{ + static_vector mask(sequence.size() * comb_size); + + std::fill(mask.begin(), mask.end(), false); + for (unsigned i = 0, i_end = sequence.size(); i != i_end; ++i) { + mask[comb_size * i] = true; + } + + 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 + 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, i_symbol_end = config.resource.start_symbol + 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..8dcc38fa3d --- /dev/null +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h @@ -0,0 +1,65 @@ +/* + * + * Copyright 2021-2023 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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/ran/CMakeLists.txt b/lib/ran/CMakeLists.txt index 167bed187d..ce7098360e 100644 --- a/lib/ran/CMakeLists.txt +++ b/lib/ran/CMakeLists.txt @@ -43,6 +43,7 @@ add_library(srsran_ran 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/srs/srs_information.cpp b/lib/ran/srs/srs_information.cpp new file mode 100644 index 0000000000..7fd5550a79 --- /dev/null +++ b/lib/ran/srs/srs_information.cpp @@ -0,0 +1,95 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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, unsigned comb_size) +{ + srsran_assert((comb_size == 2) || (comb_size == 4), "Invalid comb size (i.e., )", comb_size); + return (m_srs_b * N_RB_SC) / 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, resource.bandwidth_index); + 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.comb_size == 2) || (resource.comb_size == 4), "Invalid comb size (i.e., {})", resource.comb_size); + 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); + + // Calculate sequence group. + unsigned f_gh = 0; + unsigned u = (f_gh + resource.sequence_id) % 30; + + // Calculate sequence number. + unsigned v = 0; + + // Maximum number of cyclic shifts depending on the comb size. + unsigned n_cs_max = (resource.comb_size == 4) ? 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 + (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; + 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 = (resource.comb_offset + resource.comb_size / 2) % resource.comb_size; + } + unsigned k0_bar = resource.freq_shift * 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, 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) / bw_config->m_srs) % bw_config->N; + sum += resource.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 = resource.comb_size; + return info; +} \ No newline at end of file diff --git a/tests/unittests/phy/upper/signal_processors/CMakeLists.txt b/tests/unittests/phy/upper/signal_processors/CMakeLists.txt index 372358a5e3..e983f7a00c 100644 --- a/tests/unittests/phy/upper/signal_processors/CMakeLists.txt +++ b/tests/unittests/phy/upper/signal_processors/CMakeLists.txt @@ -20,6 +20,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/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..74c96be3c5 --- /dev/null +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.h @@ -0,0 +1,109 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +// This file was generated using the following MATLAB class on 06-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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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_test_data.tar.gz b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz new file mode 100644 index 0000000000..fe94aeee01 --- /dev/null +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8855d032fceaa0eb8390a7e043d3d97745024eab5423587e477cba5bfb3c65fe +size 500623 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..da8d99cc84 --- /dev/null +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp @@ -0,0 +1,79 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "../../../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_equal_to(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 From 035310054a2bd085758989d58c51a4f42e650cea Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 6 Mar 2024 17:42:37 +0100 Subject: [PATCH 19/77] phy: review SRS estimator --- .../signal_processors/srs/srs_estimator_configuration.h | 6 +----- .../upper/signal_processors/srs/srs_estimator_factory.h | 3 +-- include/srsran/ran/srs/srs_channel_matrix.h | 4 +++- include/srsran/ran/srs/srs_information.h | 7 ++++--- 4 files changed, 9 insertions(+), 11 deletions(-) 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 index fa86a1cf4c..9308825076 100644 --- a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_configuration.h @@ -10,7 +10,6 @@ #pragma once -#include "srsran/adt/optional.h" #include "srsran/adt/static_vector.h" #include "srsran/ran/slot_point.h" #include "srsran/ran/srs/srs_constants.h" @@ -19,10 +18,7 @@ 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. +/// 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; 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 index d2574c94e6..533320e92c 100644 --- a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h @@ -23,8 +23,7 @@ class srs_estimator_factory /// Default destructor. virtual ~srs_estimator_factory() = default; - /// \brief Creates a sounding reference signal based propagation channel estimator. - /// \return + /// Creates a sounding reference signal based propagation channel estimator. virtual std::unique_ptr create() = 0; }; diff --git a/include/srsran/ran/srs/srs_channel_matrix.h b/include/srsran/ran/srs/srs_channel_matrix.h index a1fc69bf82..1bff28ba03 100644 --- a/include/srsran/ran/srs/srs_channel_matrix.h +++ b/include/srsran/ran/srs/srs_channel_matrix.h @@ -17,6 +17,7 @@ #include "srsran/srsvec/copy.h" #include "srsran/srsvec/sc_prod.h" #include "srsran/support/srsran_assert.h" +#include #include #include @@ -127,7 +128,8 @@ class srs_channel_matrix /// \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 both channel matrices are exactly the same, \c false otherwise. + /// \return \c true if the absolute error between both channel matrices is lower than \c tolerance, \c false + /// otherwise. bool is_near_equal_to(const srs_channel_matrix& other, float tolerance) const { unsigned nof_rx_ports = get_nof_rx_ports(); diff --git a/include/srsran/ran/srs/srs_information.h b/include/srsran/ran/srs/srs_information.h index 6be7e04c24..8e1da37156 100644 --- a/include/srsran/ran/srs/srs_information.h +++ b/include/srsran/ran/srs/srs_information.h @@ -15,9 +15,10 @@ namespace srsran { /// \brief Collects Sounding Reference Signal information. /// -/// Calculates derived parameters that are used for the SRS sequence generation and mapping in TS38.211 Sections +/// Contains the derived parameters that are used for the SRS sequence generation and mapping in 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; @@ -37,8 +38,8 @@ struct srs_information { /// \param resource SRS resource configuration. /// \param i_antenna_port Transmit 0-based antenna port index. /// \param i_symbol OFDM symbol index within the slot. -/// \return SRS information if the parameters are valid. -/// \remark An assertion is triggered if any resource parameter is invalid. +/// \return The SRS information. +/// \remark An assertion is triggered if any resource parameter is invalid or not supported. srs_information get_srs_information(const srs_resource_configuration& resource, unsigned i_antenna_port, unsigned i_symbol); From 2b79b3003133d5abf4268d3f78bb7ffe04b92b60 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 8 Mar 2024 09:32:06 +0100 Subject: [PATCH 20/77] phy: review SRS estimator related --- .../srs/srs_estimator_factory.h | 2 +- .../srs/srs_estimator_result.h | 2 +- include/srsran/ran/pucch/srs_configuration.h | 2 +- .../ran/srs/srs_bandwidth_configuration.h | 2 +- include/srsran/ran/srs/srs_channel_matrix.h | 2 +- include/srsran/ran/srs/srs_information.h | 8 +- .../ran/srs/srs_resource_configuration.h | 47 +++--- .../srs/srs_estimator_generic_impl.cpp | 10 +- .../srs/srs_estimator_generic_impl.h | 4 +- lib/ran/srs/srs_information.cpp | 36 ++--- .../srs/srs_estimator_test_data.h | 146 +++++++++--------- .../srs/srs_estimator_test_data.tar.gz | 4 +- .../srs/srs_estimator_vectortest.cpp | 2 +- 13 files changed, 135 insertions(+), 132 deletions(-) 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 index 533320e92c..5c02dc4537 100644 --- a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_factory.h @@ -23,7 +23,7 @@ class srs_estimator_factory /// Default destructor. virtual ~srs_estimator_factory() = default; - /// Creates a sounding reference signal based propagation channel estimator. + /// Creates a Sounding Reference Signal based propagation channel estimator. virtual std::unique_ptr create() = 0; }; 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 index 4386210426..1d75de9331 100644 --- a/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator_result.h @@ -19,7 +19,7 @@ namespace srsran { struct srs_estimator_result { /// Wideband estimated channel matrix. srs_channel_matrix channel_matrix; - /// Wideband Measured noise variance. + /// Wideband measured noise variance. float noise_variance; /// Measured time alignment. phy_time_unit time_align; diff --git a/include/srsran/ran/pucch/srs_configuration.h b/include/srsran/ran/pucch/srs_configuration.h index 20768afb3e..0bca47f030 100644 --- a/include/srsran/ran/pucch/srs_configuration.h +++ b/include/srsran/ran/pucch/srs_configuration.h @@ -16,7 +16,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/srs/srs_bandwidth_configuration.h b/include/srsran/ran/srs/srs_bandwidth_configuration.h index 5c72d31915..997412c665 100644 --- a/include/srsran/ran/srs/srs_bandwidth_configuration.h +++ b/include/srsran/ran/srs/srs_bandwidth_configuration.h @@ -18,7 +18,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 1bff28ba03..0e77402131 100644 --- a/include/srsran/ran/srs/srs_channel_matrix.h +++ b/include/srsran/ran/srs/srs_channel_matrix.h @@ -130,7 +130,7 @@ class srs_channel_matrix /// \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_equal_to(const srs_channel_matrix& other, float tolerance) const + 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(); diff --git a/include/srsran/ran/srs/srs_information.h b/include/srsran/ran/srs/srs_information.h index 8e1da37156..be99ddbf10 100644 --- a/include/srsran/ran/srs/srs_information.h +++ b/include/srsran/ran/srs/srs_information.h @@ -15,7 +15,7 @@ namespace srsran { /// \brief Collects Sounding Reference Signal information. /// -/// Contains the derived parameters that are used for the SRS sequence generation and mapping in TS38.211 Sections +/// 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. @@ -34,12 +34,12 @@ struct srs_information { unsigned comb_size; }; -/// \brief Get sounding reference signal information. +/// \brief Get Sounding Reference Signal information. /// \param resource SRS resource configuration. -/// \param i_antenna_port Transmit 0-based antenna port index. +/// \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 any resource parameter is invalid or not supported. +/// \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); diff --git a/include/srsran/ran/srs/srs_resource_configuration.h b/include/srsran/ran/srs/srs_resource_configuration.h index ec3808fd0c..b7f70e64ba 100644 --- a/include/srsran/ran/srs/srs_resource_configuration.h +++ b/include/srsran/ran/srs/srs_resource_configuration.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/adt/bounded_integer.h" #include "srsran/adt/optional.h" #include "srsran/ran/srs/srs_constants.h" #include @@ -21,10 +22,12 @@ namespace srsran { /// 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 { - /// Enum for attributes that accept only one, two, or four. + /// 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 { @@ -41,74 +44,74 @@ struct srs_resource_configuration { /// 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$. + /// \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 valid range is {0...13}. /// /// The number of symbols plus the start symbol must not exceed the number of symbols in one slot. - uint8_t start_symbol; + 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). - uint8_t configuration_index; + /// 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). - uint16_t sequence_id; + /// 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). - uint8_t bandwidth_index; + /// 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. - uint8_t comb_size; + 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$). - uint8_t comb_offset; + /// 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$. - uint8_t cyclic_shift; + /// - {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). - uint8_t freq_position; + /// 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). - uint16_t freq_shift; + /// 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). - uint8_t freq_hopping; + /// 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. 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 index 4dcfa41bab..9c4c1fc90d 100644 --- a/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.cpp @@ -27,11 +27,10 @@ void srs_estimator_generic_impl::extract_sequence(span se unsigned initial_subcarrier, unsigned comb_size) { - static_vector mask(sequence.size() * comb_size); + bounded_bitset mask(sequence.size() * comb_size); - std::fill(mask.begin(), mask.end(), false); for (unsigned i = 0, i_end = sequence.size(); i != i_end; ++i) { - mask[comb_size * i] = true; + mask.set(comb_size * i); } grid.get(sequence, i_rx_port, i_symbol, initial_subcarrier, mask); @@ -42,7 +41,7 @@ srs_estimator_result srs_estimator_generic_impl::estimate(const resource_grid_re { 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 + nof_symbols <= nof_symbols_per_slot, + 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, @@ -58,7 +57,8 @@ srs_estimator_result srs_estimator_generic_impl::estimate(const resource_grid_re i_antenna_port != i_antenna_port_end; ++i_antenna_port) { cf_t coefficient = 0; - for (unsigned i_symbol = config.resource.start_symbol, i_symbol_end = config.resource.start_symbol + nof_symbols; + 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. 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 index 8dcc38fa3d..dd72cf8da2 100644 --- a/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h +++ b/lib/phy/upper/signal_processors/srs/srs_estimator_generic_impl.h @@ -17,7 +17,7 @@ namespace srsran { -/// Implements a generic sounding reference signal estimator. +/// Implements a generic Sounding Reference Signal estimator. class srs_estimator_generic_impl : public srs_estimator { public: @@ -40,7 +40,7 @@ class srs_estimator_generic_impl : public srs_estimator /// 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. + /// \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. /// diff --git a/lib/ran/srs/srs_information.cpp b/lib/ran/srs/srs_information.cpp index 7fd5550a79..6e8c5fe6a0 100644 --- a/lib/ran/srs/srs_information.cpp +++ b/lib/ran/srs/srs_information.cpp @@ -19,10 +19,9 @@ using namespace srsran; static constexpr unsigned N_RB_SC = 12; -static constexpr unsigned get_sequence_length(unsigned m_srs_b, unsigned comb_size) +static constexpr unsigned get_sequence_length(unsigned m_srs_b, srs_resource_configuration::comb_size_enum comb_size) { - srsran_assert((comb_size == 2) || (comb_size == 4), "Invalid comb size (i.e., )", comb_size); - return (m_srs_b * N_RB_SC) / comb_size; + return (m_srs_b * N_RB_SC) / static_cast(comb_size); } srs_information @@ -30,15 +29,13 @@ srsran::get_srs_information(const srs_resource_configuration& resource, unsigned { // Select BW configuration. optional srs_bw_config = - srs_configuration_get(resource.configuration_index, resource.bandwidth_index); + 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.comb_size == 2) || (resource.comb_size == 4), "Invalid comb size (i.e., {})", resource.comb_size); 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."); @@ -46,40 +43,43 @@ srsran::get_srs_information(const srs_resource_configuration& resource, unsigned // 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) % 30; + 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 == 4) ? 12 : 8; + 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 + (n_cs_max * i_antenna_port) / static_cast(resource.nof_antenna_ports)) % - n_cs_max; + 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; + 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 = (resource.comb_offset + resource.comb_size / 2) % resource.comb_size; + k_tc = (k_tc + comb_size / 2) % comb_size; } - unsigned k0_bar = resource.freq_shift * N_RB_SC + k_tc; + 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, 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) / bw_config->m_srs) % bw_config->N; - sum += resource.comb_size * M_srs * n_b; + 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; @@ -90,6 +90,6 @@ srsran::get_srs_information(const srs_resource_configuration& resource, unsigned info.sequence_number = v; info.alpha = alpha; info.mapping_initial_subcarrier = initial_subcarrier; - info.comb_size = resource.comb_size; + info.comb_size = comb_size; return info; } \ No newline at end of file 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 index 74c96be3c5..ce6ba9f690 100644 --- 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 @@ -10,7 +10,7 @@ #pragma once -// This file was generated using the following MATLAB class on 06-03-2024 (seed 0): +// 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" @@ -31,78 +31,78 @@ struct test_case_t { 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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"}}, + {{{{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 }; diff --git a/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz index fe94aeee01..cc6c492cbc 100644 --- a/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8855d032fceaa0eb8390a7e043d3d97745024eab5423587e477cba5bfb3c65fe -size 500623 +oid sha256:3b312ca4e684b4edaf34afcd222b5235719608d3f6e7ddcddf2de3aacde8de6d +size 500925 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 index da8d99cc84..00f7314855 100644 --- a/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp +++ b/tests/unittests/phy/upper/signal_processors/srs/srs_estimator_vectortest.cpp @@ -36,7 +36,7 @@ std::ostream& operator<<(std::ostream& os, const srs_channel_matrix& channel) bool operator==(const srs_channel_matrix& left, const srs_channel_matrix& right) { - return left.is_near_equal_to(right, 1e-2); + return left.is_near(right, 1e-2); } } // namespace srsran From 2416ca73449a73c6bbdec018109ae78246c81c6a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 12 Mar 2024 14:57:41 +0100 Subject: [PATCH 21/77] phy: review SRS estimator related --- .../srsran/phy/upper/signal_processors/srs/srs_estimator.h | 2 +- include/srsran/ran/srs/srs_channel_matrix.h | 7 +++---- include/srsran/ran/srs/srs_resource_formatter.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h b/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h index e4bdabf29e..1996aa1187 100644 --- a/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h +++ b/include/srsran/phy/upper/signal_processors/srs/srs_estimator.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/ran/srs/srs_channel_matrix.h b/include/srsran/ran/srs/srs_channel_matrix.h index 0e77402131..a34fbb96b5 100644 --- a/include/srsran/ran/srs/srs_channel_matrix.h +++ b/include/srsran/ran/srs/srs_channel_matrix.h @@ -49,14 +49,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. diff --git a/include/srsran/ran/srs/srs_resource_formatter.h b/include/srsran/ran/srs/srs_resource_formatter.h index cb03732f99..af8b13179c 100644 --- a/include/srsran/ran/srs/srs_resource_formatter.h +++ b/include/srsran/ran/srs/srs_resource_formatter.h @@ -15,7 +15,7 @@ namespace fmt { -/// \brief Custom formatter for \c srsran::srs_estimator_configuration. +/// \brief Custom formatter for \c srsran::srs_resource_configuration. template <> struct formatter { /// Helper used to parse formatting options and format fields. From a6157d2800358de8d4084a01ed0c5e8a756d511d Mon Sep 17 00:00:00 2001 From: asaezper Date: Tue, 12 Mar 2024 15:17:29 +0100 Subject: [PATCH 22/77] all: update copyright year in header --- cmake/modules/FindNUMA.cmake | 2 +- include/srsran/adt/any.h | 2 +- include/srsran/asn1/asn1_ap_utils.h | 2 +- .../hal/phy/upper/channel_processors/hw_accelerator_factories.h | 2 +- .../hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc.h | 2 +- .../upper/channel_processors/hw_accelerator_pdsch_enc_factory.h | 2 +- include/srsran/support/cpu_architecture_info.h | 2 +- lib/fapi/loggers/CMakeLists.txt | 2 +- lib/fapi/message_buffering/CMakeLists.txt | 2 +- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp | 2 +- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.h | 2 +- .../phy/upper/channel_processors/hw_accelerator_factories.cpp | 2 +- .../channel_processors/hw_accelerator_pdsch_enc_acc100_impl.cpp | 2 +- .../channel_processors/hw_accelerator_pdsch_enc_acc100_impl.h | 2 +- .../upper/channel_processors/hw_accelerator_pdsch_enc_impl.cpp | 2 +- .../upper/channel_processors/hw_accelerator_pdsch_enc_impl.h | 2 +- lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.cpp | 2 +- lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h | 2 +- lib/rlc/rlc_sdu_queue_lockfree.h | 2 +- lib/support/cpu_architecture_info.cpp | 2 +- .../upper/channel_processors/pdsch_encoder_hwacc_benchmark.cpp | 2 +- tests/e2e/tests/viavi/config.yml | 2 +- .../phy/upper/channel_processors/pxsch_chain_test.cpp | 2 +- tests/unittests/fapi/message_buffering/CMakeLists.txt | 2 +- tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp | 2 +- tests/unittests/support/executors/sync_task_executor_test.cpp | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cmake/modules/FindNUMA.cmake b/cmake/modules/FindNUMA.cmake index 61b240ee79..e2b00967b7 100644 --- a/cmake/modules/FindNUMA.cmake +++ b/cmake/modules/FindNUMA.cmake @@ -1,5 +1,5 @@ # -# Copyright 2021-2023 Software Radio Systems Limited +# Copyright 2021-2024 Software Radio Systems Limited # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/adt/any.h b/include/srsran/adt/any.h index dbc324504e..73a0e5869b 100644 --- a/include/srsran/adt/any.h +++ b/include/srsran/adt/any.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/asn1/asn1_ap_utils.h b/include/srsran/asn1/asn1_ap_utils.h index 7ef455d50e..1ce9ab07ea 100644 --- a/include/srsran/asn1/asn1_ap_utils.h +++ b/include/srsran/asn1/asn1_ap_utils.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_factories.h b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_factories.h index ed02c73f2e..4d6a7263fc 100644 --- a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_factories.h +++ b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_factories.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc.h b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc.h index 6095d62597..6249c1d114 100644 --- a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc.h +++ b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_factory.h b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_factory.h index e5ec3a22f6..cea4270935 100644 --- a/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_factory.h +++ b/include/srsran/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_factory.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/include/srsran/support/cpu_architecture_info.h b/include/srsran/support/cpu_architecture_info.h index 9efe520263..8ba84a8c3c 100644 --- a/include/srsran/support/cpu_architecture_info.h +++ b/include/srsran/support/cpu_architecture_info.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/fapi/loggers/CMakeLists.txt b/lib/fapi/loggers/CMakeLists.txt index 7b47ea5f18..ab87f1af24 100644 --- a/lib/fapi/loggers/CMakeLists.txt +++ b/lib/fapi/loggers/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2021-2023 Software Radio Systems Limited +# Copyright 2021-2024 Software Radio Systems Limited # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of diff --git a/lib/fapi/message_buffering/CMakeLists.txt b/lib/fapi/message_buffering/CMakeLists.txt index a6030395c4..86e0fb5e13 100644 --- a/lib/fapi/message_buffering/CMakeLists.txt +++ b/lib/fapi/message_buffering/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2021-2023 Software Radio Systems Limited +# Copyright 2021-2024 Software Radio Systems Limited # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp index e2c2103c9c..eaa2938398 100644 --- a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp +++ b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.h b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.h index 1a848b6b15..b6a5e746a2 100644 --- a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.h +++ b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/phy/upper/channel_processors/hw_accelerator_factories.cpp b/lib/hal/phy/upper/channel_processors/hw_accelerator_factories.cpp index 1003514163..27eeaa2874 100644 --- a/lib/hal/phy/upper/channel_processors/hw_accelerator_factories.cpp +++ b/lib/hal/phy/upper/channel_processors/hw_accelerator_factories.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.cpp b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.cpp index 8380b83123..cea29ef90e 100644 --- a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.cpp +++ b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.h b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.h index c67e1a89d7..640a80b3e2 100644 --- a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.h +++ b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_acc100_impl.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.cpp b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.cpp index a265985ef9..5b3b0f9b13 100644 --- a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.cpp +++ b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.h b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.h index f0b4a427a8..4d1bad278d 100644 --- a/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.h +++ b/lib/hal/phy/upper/channel_processors/hw_accelerator_pdsch_enc_impl.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.cpp b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.cpp index e313d887e5..d132781784 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.cpp +++ b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of 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 1beae875d0..eecdb508c7 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/rlc/rlc_sdu_queue_lockfree.h b/lib/rlc/rlc_sdu_queue_lockfree.h index e7056184af..06518c7585 100644 --- a/lib/rlc/rlc_sdu_queue_lockfree.h +++ b/lib/rlc/rlc_sdu_queue_lockfree.h @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/lib/support/cpu_architecture_info.cpp b/lib/support/cpu_architecture_info.cpp index c9b79a879d..737b0cc26d 100644 --- a/lib/support/cpu_architecture_info.cpp +++ b/lib/support/cpu_architecture_info.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/tests/benchmarks/phy/upper/channel_processors/pdsch_encoder_hwacc_benchmark.cpp b/tests/benchmarks/phy/upper/channel_processors/pdsch_encoder_hwacc_benchmark.cpp index 435bce2c5f..b9356db606 100644 --- a/tests/benchmarks/phy/upper/channel_processors/pdsch_encoder_hwacc_benchmark.cpp +++ b/tests/benchmarks/phy/upper/channel_processors/pdsch_encoder_hwacc_benchmark.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/tests/e2e/tests/viavi/config.yml b/tests/e2e/tests/viavi/config.yml index e87b0cae13..90457472f4 100644 --- a/tests/e2e/tests/viavi/config.yml +++ b/tests/e2e/tests/viavi/config.yml @@ -1,5 +1,5 @@ # -# Copyright 2021-2023 Software Radio Systems Limited +# Copyright 2021-2024 Software Radio Systems Limited # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of diff --git a/tests/integrationtests/phy/upper/channel_processors/pxsch_chain_test.cpp b/tests/integrationtests/phy/upper/channel_processors/pxsch_chain_test.cpp index 723b87a27e..568c811c6e 100644 --- a/tests/integrationtests/phy/upper/channel_processors/pxsch_chain_test.cpp +++ b/tests/integrationtests/phy/upper/channel_processors/pxsch_chain_test.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/tests/unittests/fapi/message_buffering/CMakeLists.txt b/tests/unittests/fapi/message_buffering/CMakeLists.txt index 39dce3f4b4..01c4aded78 100644 --- a/tests/unittests/fapi/message_buffering/CMakeLists.txt +++ b/tests/unittests/fapi/message_buffering/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2021-2023 Software Radio Systems Limited +# Copyright 2021-2024 Software Radio Systems Limited # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of diff --git a/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp b/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp index 6e805567fc..e68bb110c0 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp @@ -1,7 +1,7 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of diff --git a/tests/unittests/support/executors/sync_task_executor_test.cpp b/tests/unittests/support/executors/sync_task_executor_test.cpp index b0135f74f8..8902986cf0 100644 --- a/tests/unittests/support/executors/sync_task_executor_test.cpp +++ b/tests/unittests/support/executors/sync_task_executor_test.cpp @@ -1,6 +1,6 @@ /* * - * Copyright 2021-2023 Software Radio Systems Limited + * Copyright 2021-2024 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of From b9b3fb93765f1da9059eb69fee77f687973f60be Mon Sep 17 00:00:00 2001 From: asaezper Date: Tue, 12 Mar 2024 17:43:45 +0100 Subject: [PATCH 23/77] ci: fix intermediate commits git fetch --- .gitlab/ci/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index a99c25ce7d..7d386f2736 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) From 4918115e49b9fd68c56a1d3e57ef9e87d4019783 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Mon, 4 Mar 2024 18:12:15 +0100 Subject: [PATCH 24/77] fapi: removed the profile SSS from the DL_TTI.request PDUs --- include/srsran/fapi/message_builders.h | 226 +---------- include/srsran/fapi/messages.h | 18 +- lib/fapi/validators/dl_csi_pdu.cpp | 50 +-- lib/fapi/validators/dl_pdcch_pdu.cpp | 35 +- lib/fapi/validators/dl_pdsch_pdu.cpp | 67 +--- lib/fapi/validators/dl_ssb_pdu.cpp | 50 +-- .../mac/mac_to_fapi_translator.cpp | 1 - lib/fapi_adaptor/mac/messages/pdcch.cpp | 3 - lib/fapi_adaptor/mac/messages/pdsch.cpp | 5 +- lib/fapi_adaptor/mac/messages/ssb.cpp | 2 - lib/fapi_adaptor/phy/messages/pdcch.cpp | 11 +- lib/fapi_adaptor/phy/messages/pdsch.cpp | 47 +-- lib/fapi_adaptor/phy/messages/ssb.cpp | 2 - .../fapi/builders/dl_csi_pdu_test.cpp | 26 +- .../fapi/builders/dl_pdcch_pdu_test.cpp | 43 +-- .../fapi/builders/dl_pdsch_pdu_test.cpp | 50 +-- .../fapi/builders/dl_ssb_pdu_test.cpp | 22 -- .../fapi/message_builder_helpers.cpp | 69 ++-- .../fapi/validators/dl_csi_pdu_test.cpp | 27 +- .../fapi/validators/dl_pdcch_pdu_test.cpp | 20 +- .../fapi/validators/dl_pdsch_pdu_test.cpp | 54 +-- .../fapi/validators/dl_ssb_pdu_test.cpp | 26 +- .../adaptor_performance_dl_tti_request.cpp | 5 +- .../mac/messages/dl_ssb_pdu_test.cpp | 2 - .../fapi_adaptor/phy/messages/CMakeLists.txt | 12 +- .../phy/messages/dl_pdcch_pdu_test.cpp | 90 ++--- .../phy/messages/dl_pdsch_pdu_test.cpp | 352 ++++++++---------- .../phy/messages/dl_ssb_pdu_test.cpp | 122 +++--- 28 files changed, 368 insertions(+), 1069 deletions(-) diff --git a/include/srsran/fapi/message_builders.h b/include/srsran/fapi/message_builders.h index 6465f74ffb..b97cdd4d3c 100644 --- a/include/srsran/fapi/message_builders.h +++ b/include/srsran/fapi/message_builders.h @@ -72,11 +72,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. @@ -158,39 +154,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() { @@ -214,10 +177,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. @@ -239,22 +199,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; } @@ -268,52 +215,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) @@ -596,19 +497,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, + nzp_csi_rs_epre_to_ssb 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; } @@ -718,44 +611,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) @@ -765,31 +620,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, @@ -876,43 +706,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, + nzp_csi_rs_epre_to_ssb 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 f16f284a0f..df84bdd074 100644 --- a/include/srsran/fapi/messages.h +++ b/include/srsran/fapi/messages.h @@ -100,8 +100,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; @@ -147,7 +145,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. @@ -215,18 +212,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 @@ -305,13 +295,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; + int power_control_offset_profile_nr; nzp_csi_rs_epre_to_ssb 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. @@ -321,7 +310,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. @@ -338,7 +326,7 @@ 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; + int power_control_offset_profile_nr; nzp_csi_rs_epre_to_ssb power_control_offset_ss_profile_nr; tx_precoding_and_beamforming_pdu precoding_and_beamforming; dl_csi_rs_maintenance_v3 csi_rs_maintenance_v3; @@ -369,8 +357,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/lib/fapi/validators/dl_csi_pdu.cpp b/lib/fapi/validators/dl_csi_pdu.cpp index b4f0cd2496..6dfc34302d 100644 --- a/lib/fapi/validators/dl_csi_pdu.cpp +++ b/lib/fapi/validators/dl_csi_pdu.cpp @@ -126,31 +126,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. @@ -159,27 +141,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; @@ -196,12 +160,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 b4c4aa566e..9d5fadcce0 100644 --- a/lib/fapi/validators/dl_pdcch_pdu.cpp +++ b/lib/fapi/validators/dl_pdcch_pdu.cpp @@ -186,32 +186,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. @@ -253,8 +237,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 d066f3df05..2f6c557002 100644 --- a/lib/fapi/validators/dl_pdsch_pdu.cpp +++ b/lib/fapi/validators/dl_pdsch_pdu.cpp @@ -234,58 +234,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. @@ -401,10 +374,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 aaa383b988..d74742529e 100644 --- a/lib/fapi/validators/dl_ssb_pdu.cpp +++ b/lib/fapi/validators/dl_ssb_pdu.cpp @@ -34,13 +34,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); } @@ -102,45 +97,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) @@ -176,8 +132,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/mac_to_fapi_translator.cpp b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp index d298ab2989..561b894537 100644 --- a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp +++ b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp @@ -132,7 +132,6 @@ static void add_csi_rs_pdus_to_dl_request(fapi::dl_tti_request_message_builder& // 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({}); } } diff --git a/lib/fapi_adaptor/mac/messages/pdcch.cpp b/lib/fapi_adaptor/mac/messages/pdcch.cpp index 559e37c81a..fa9a448d35 100644 --- a/lib/fapi_adaptor/mac/messages/pdcch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdcch.cpp @@ -105,9 +105,6 @@ void srsran::fapi_adaptor::convert_pdcch_mac_to_fapi(fapi::dl_pdcch_pdu_builder& 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 b4daa97716..dd484a63f4 100644 --- a/lib/fapi_adaptor/mac/messages/pdsch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdsch.cpp @@ -111,10 +111,7 @@ static void fill_time_allocation(fapi::dl_pdsch_pdu_builder& builder, const ofdm static void fill_power_parameters(fapi::dl_pdsch_pdu_builder& builder) { - 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(0, fapi::nzp_csi_rs_epre_to_ssb::dB0); } static void fill_precoding_and_beamforming(fapi::dl_pdsch_pdu_builder& builder, diff --git a/lib/fapi_adaptor/mac/messages/ssb.cpp b/lib/fapi_adaptor/mac/messages/ssb.cpp index 1a83d687fe..15023a1b54 100644 --- a/lib/fapi_adaptor/mac/messages/ssb.cpp +++ b/lib/fapi_adaptor/mac/messages/ssb.cpp @@ -47,8 +47,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/pdcch.cpp b/lib/fapi_adaptor/phy/messages/pdcch.cpp index f6e9f0b164..53f44b6be9 100644 --- a/lib/fapi_adaptor/phy/messages/pdcch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdcch.cpp @@ -22,7 +22,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; @@ -34,14 +33,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 = static_cast(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 1af4eb6fe7..9f61a9adf3 100644 --- a/lib/fapi_adaptor/phy/messages/pdsch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdsch.cpp @@ -61,49 +61,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 5c882593c4..3dcd598d3d 100644 --- a/lib/fapi_adaptor/phy/messages/ssb.cpp +++ b/lib/fapi_adaptor/phy/messages/ssb.cpp @@ -129,8 +129,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/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp index 6ccc386ed6..8284846ceb 100644 --- a/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp @@ -65,32 +65,10 @@ TEST(dl_csi_pdu_builder, valid_tx_power_info_parameters_passes) 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); - } - 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 a1d143610b..3e87407e05 100644 --- a/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_pdcch_pdu_test.cpp @@ -112,48 +112,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 b16eb16bcd..588785da6a 100644 --- a/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp @@ -180,14 +180,10 @@ TEST(dl_pdsch_pdu_builder, valid_tx_power_info_parameters_passes) 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); - } - 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); } } @@ -281,30 +277,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}) { @@ -336,24 +308,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 17cf1c65be..9f0cad67d5 100644 --- a/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_ssb_pdu_test.cpp @@ -51,28 +51,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 a5ace8bea9..0e2dc64692 100644 --- a/tests/unittests/fapi/message_builder_helpers.cpp +++ b/tests/unittests/fapi/message_builder_helpers.cpp @@ -145,23 +145,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; } @@ -203,8 +201,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(); @@ -256,8 +252,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 @@ -270,23 +264,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 = nzp_csi_rs_epre_to_ssb::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 4e3d20d979..823495e013 100644 --- a/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp @@ -159,27 +159,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, @@ -188,14 +174,13 @@ INSTANTIATE_TEST_SUITE_P(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; }}), 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 9fd9dd1a92..2fceda1ffb 100644 --- a/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_pdcch_pdu_test.cpp @@ -297,33 +297,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 44b8d6946c..07333f0632 100644 --- a/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp @@ -279,31 +279,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, @@ -312,27 +296,12 @@ INSTANTIATE_TEST_SUITE_P(offset_ss_profile_nr, [](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; }}), 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, @@ -568,10 +537,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 9afce2b504..25286eec1b 100644 --- a/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_ssb_pdu_test.cpp @@ -49,14 +49,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, @@ -127,21 +125,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) { @@ -159,14 +142,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 f7396b9674..b0668ad8ea 100644 --- a/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp +++ b/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp @@ -141,9 +141,7 @@ 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. @@ -152,7 +150,6 @@ static void pdcch_conversion_benchmark() 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 c348d3c04a..c5b437c82c 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 @@ -34,8 +34,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 934adbfe14..18fab128c2 100644 --- a/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt +++ b/tests/unittests/fapi_adaptor/phy/messages/CMakeLists.txt @@ -9,16 +9,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 0d2f8fdcb8..0c9402c985 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 @@ -15,7 +15,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; @@ -23,7 +23,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); @@ -38,7 +38,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); @@ -51,7 +50,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); @@ -65,7 +64,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); @@ -90,15 +88,8 @@ 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, {}); @@ -111,7 +102,6 @@ static void pdcch_conversion_test() 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; @@ -119,61 +109,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))); } } } @@ -184,9 +170,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 f2e62797b0..d4e1f1a6e6 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 @@ -13,7 +13,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; @@ -21,45 +21,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::nzp_csi_rs_epre_to_ssb 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::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 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, @@ -117,7 +105,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); @@ -151,166 +139,144 @@ static void pdsch_conversion_test() 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}) { + fapi::nzp_csi_rs_epre_to_ssb::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); + + optional profile_nr; + optional data_profile_sss; + optional dmrs_profile_sss; + + 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. } } } @@ -322,9 +288,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 911fdd0544..605fc34207 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 @@ -11,8 +11,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; @@ -21,7 +21,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); @@ -47,9 +47,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, @@ -77,10 +76,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; @@ -88,94 +83,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); } } } @@ -184,11 +174,3 @@ static void ssb_conversion_test() } } } - -int main() -{ - ssb_conversion_test(); - - fmt::print("Success\n"); - return 0; -} From 7a83f542142a1d432342afbcc5dc3a8dc71c769f Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Thu, 7 Mar 2024 12:53:35 +0100 Subject: [PATCH 25/77] fapi: removed hardcoded power values for PDSCH and PDCCH PDUs --- include/srsran/fapi/messages.h | 21 ++++++++++++++++++- .../mac/mac_to_fapi_translator.cpp | 18 +--------------- lib/fapi_adaptor/mac/messages/pdcch.cpp | 2 +- lib/fapi_adaptor/mac/messages/pdsch.cpp | 16 ++++++-------- lib/fapi_adaptor/phy/messages/csi_rs.cpp | 1 - lib/fapi_adaptor/phy/messages/pdcch.cpp | 2 +- 6 files changed, 29 insertions(+), 31 deletions(-) diff --git a/include/srsran/fapi/messages.h b/include/srsran/fapi/messages.h index df84bdd074..d8efc4c3d8 100644 --- a/include/srsran/fapi/messages.h +++ b/include/srsran/fapi/messages.h @@ -241,11 +241,30 @@ 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 nzp_csi_rs_epre_to_ssb : uint8_t { dB_minus_3, dB0, dB3, dB6 }; 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 }; +/// Converts the given value to a NZP CSI-RS EPRE to SSB value. +inline nzp_csi_rs_epre_to_ssb to_nzp_csi_rs_epre_to_ssb(int value) +{ + switch (value) { + case -3: + return nzp_csi_rs_epre_to_ssb::dB_minus_3; + case 0: + return nzp_csi_rs_epre_to_ssb::dB0; + case 3: + return nzp_csi_rs_epre_to_ssb::dB3; + case 6: + return nzp_csi_rs_epre_to_ssb::dB6; + default: + srsran_assert(0, "Invalid CSI-RS EPRE to SSB value '{}'", value); + break; + } + return nzp_csi_rs_epre_to_ssb::dB0; +} + /// Downlink PDSCH PDU information. struct dl_pdsch_pdu { static constexpr unsigned BITMAP_SIZE = 2U; diff --git a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp index 561b894537..a29c5c66df 100644 --- a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp +++ b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp @@ -92,22 +92,6 @@ 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) { @@ -127,7 +111,7 @@ static void add_csi_rs_pdus_to_dl_request(fapi::dl_tti_request_message_builder& 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)); + fapi::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); diff --git a/lib/fapi_adaptor/mac/messages/pdcch.cpp b/lib/fapi_adaptor/mac/messages/pdcch.cpp index fa9a448d35..5e10dc6571 100644 --- a/lib/fapi_adaptor/mac/messages/pdcch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdcch.cpp @@ -101,7 +101,7 @@ 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); diff --git a/lib/fapi_adaptor/mac/messages/pdsch.cpp b/lib/fapi_adaptor/mac/messages/pdsch.cpp index dd484a63f4..0c3036a7ae 100644 --- a/lib/fapi_adaptor/mac/messages/pdsch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdsch.cpp @@ -109,9 +109,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); + builder.set_tx_power_info_parameters(power_params.pwr_ctrl_offset, + fapi::to_nzp_csi_rs_epre_to_ssb(power_params.pwr_ctrl_offset_ss)); } static void fill_precoding_and_beamforming(fapi::dl_pdsch_pdu_builder& builder, @@ -160,6 +161,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, @@ -247,8 +251,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. @@ -307,8 +309,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. @@ -368,8 +368,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. @@ -420,8 +418,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/phy/messages/csi_rs.cpp b/lib/fapi_adaptor/phy/messages/csi_rs.cpp index 1df34cffed..c373300a6d 100644 --- a/lib/fapi_adaptor/phy/messages/csi_rs.cpp +++ b/lib/fapi_adaptor/phy/messages/csi_rs.cpp @@ -29,7 +29,6 @@ static float translate_amplitude(fapi::nzp_csi_rs_epre_to_ssb power) return 2.F; case fapi::nzp_csi_rs_epre_to_ssb::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 53f44b6be9..3aaf1e8d62 100644 --- a/lib/fapi_adaptor/phy/messages/pdcch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdcch.cpp @@ -33,7 +33,7 @@ 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 = static_cast(fapi_dci.power_control_offset_ss_profile_nr); + 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. From 8e248e745ff652a838b33963ef949c888fbc6a5c Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Fri, 8 Mar 2024 09:41:28 +0100 Subject: [PATCH 26/77] fapi: move filling the ZP CSI-RS power values to the MAC --- include/srsran/fapi/message_builders.h | 8 +++--- include/srsran/fapi/messages.h | 25 +++++++++++-------- .../mac/mac_to_fapi_translator.cpp | 13 +++------- lib/fapi_adaptor/mac/messages/pdsch.cpp | 2 +- lib/fapi_adaptor/phy/messages/csi_rs.cpp | 12 ++++----- lib/fapi_adaptor/phy/messages/pdsch.cpp | 10 ++++---- .../common_scheduling/csi_rs_scheduler.cpp | 4 +++ .../fapi/builders/dl_csi_pdu_test.cpp | 2 +- .../fapi/builders/dl_pdsch_pdu_test.cpp | 2 +- .../fapi/message_builder_helpers.cpp | 4 +-- .../fapi/validators/dl_csi_pdu_test.cpp | 2 +- .../fapi/validators/dl_pdsch_pdu_test.cpp | 2 +- .../adaptor_performance_dl_tti_request.cpp | 3 --- .../phy/messages/dl_pdcch_pdu_test.cpp | 6 ----- .../phy/messages/dl_pdsch_pdu_test.cpp | 23 +++++++---------- 15 files changed, 53 insertions(+), 65 deletions(-) diff --git a/include/srsran/fapi/message_builders.h b/include/srsran/fapi/message_builders.h index b97cdd4d3c..df8502087a 100644 --- a/include/srsran/fapi/message_builders.h +++ b/include/srsran/fapi/message_builders.h @@ -497,8 +497,8 @@ 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(int power_control_offset, - nzp_csi_rs_epre_to_ssb power_control_offset_ss) + dl_pdsch_pdu_builder& set_tx_power_info_parameters(int power_control_offset, + power_control_offset_ss power_control_offset_ss) { pdu.power_control_offset_profile_nr = power_control_offset; pdu.power_control_offset_ss_profile_nr = power_control_offset_ss; @@ -706,8 +706,8 @@ 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(int power_control_offset, - nzp_csi_rs_epre_to_ssb power_control_offset_ss) + 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 = power_control_offset_ss; pdu.power_control_offset_profile_nr = power_control_offset; diff --git a/include/srsran/fapi/messages.h b/include/srsran/fapi/messages.h index d8efc4c3d8..a95f6adda1 100644 --- a/include/srsran/fapi/messages.h +++ b/include/srsran/fapi/messages.h @@ -241,28 +241,31 @@ 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 }; 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 }; -/// Converts the given value to a NZP CSI-RS EPRE to SSB value. -inline nzp_csi_rs_epre_to_ssb to_nzp_csi_rs_epre_to_ssb(int value) +/// 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 nzp_csi_rs_epre_to_ssb::dB_minus_3; + return power_control_offset_ss::dB_minus_3; case 0: - return nzp_csi_rs_epre_to_ssb::dB0; + return power_control_offset_ss::dB0; case 3: - return nzp_csi_rs_epre_to_ssb::dB3; + return power_control_offset_ss::dB3; case 6: - return nzp_csi_rs_epre_to_ssb::dB6; + return power_control_offset_ss::dB6; default: - srsran_assert(0, "Invalid CSI-RS EPRE to SSB value '{}'", value); + srsran_assert(0, "Invalid power control offset SS '{}'", value); break; } - return nzp_csi_rs_epre_to_ssb::dB0; + return power_control_offset_ss::dB0; } /// Downlink PDSCH PDU information. @@ -315,7 +318,7 @@ struct dl_pdsch_pdu { // :TODO: PTRS tx_precoding_and_beamforming_pdu precoding_and_beamforming; int power_control_offset_profile_nr; - nzp_csi_rs_epre_to_ssb power_control_offset_ss_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; @@ -346,7 +349,7 @@ struct dl_csi_rs_pdu { csi_rs_freq_density_type freq_density; uint16_t scramb_id; int power_control_offset_profile_nr; - nzp_csi_rs_epre_to_ssb power_control_offset_ss_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 diff --git a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp index a29c5c66df..4381ebafe7 100644 --- a/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp +++ b/lib/fapi_adaptor/mac/mac_to_fapi_translator.cpp @@ -96,7 +96,6 @@ static void add_csi_rs_pdus_to_dl_request(fapi::dl_tti_request_message_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, @@ -106,16 +105,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, - fapi::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_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/pdsch.cpp b/lib/fapi_adaptor/mac/messages/pdsch.cpp index 0c3036a7ae..ad07a95d67 100644 --- a/lib/fapi_adaptor/mac/messages/pdsch.cpp +++ b/lib/fapi_adaptor/mac/messages/pdsch.cpp @@ -112,7 +112,7 @@ static void fill_time_allocation(fapi::dl_pdsch_pdu_builder& builder, const ofdm static void fill_power_parameters(fapi::dl_pdsch_pdu_builder& builder, const tx_power_pdsch_information& power_params) { builder.set_tx_power_info_parameters(power_params.pwr_ctrl_offset, - fapi::to_nzp_csi_rs_epre_to_ssb(power_params.pwr_ctrl_offset_ss)); + fapi::to_power_control_offset_ss(power_params.pwr_ctrl_offset_ss)); } static void fill_precoding_and_beamforming(fapi::dl_pdsch_pdu_builder& builder, diff --git a/lib/fapi_adaptor/phy/messages/csi_rs.cpp b/lib/fapi_adaptor/phy/messages/csi_rs.cpp index c373300a6d..51a32b39ac 100644 --- a/lib/fapi_adaptor/phy/messages/csi_rs.cpp +++ b/lib/fapi_adaptor/phy/messages/csi_rs.cpp @@ -17,17 +17,17 @@ 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; default: return 1.F; diff --git a/lib/fapi_adaptor/phy/messages/pdsch.cpp b/lib/fapi_adaptor/phy/messages/pdsch.cpp index 9f61a9adf3..c05d109277 100644 --- a/lib/fapi_adaptor/phy/messages/pdsch.cpp +++ b/lib/fapi_adaptor/phy/messages/pdsch.cpp @@ -42,16 +42,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; } diff --git a/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp b/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp index b3ae32fd7b..1573aba3dd 100644 --- a/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp +++ b/lib/scheduler/common_scheduling/csi_rs_scheduler.cpp @@ -35,6 +35,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/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp index 8284846ceb..5a7d733818 100644 --- a/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_csi_pdu_test.cpp @@ -64,7 +64,7 @@ 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; + power_control_offset_ss ss = power_control_offset_ss::dB3; builder.set_tx_power_info_parameters(power, ss); diff --git a/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp index 588785da6a..fa280bb7f6 100644 --- a/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/builders/dl_pdsch_pdu_test.cpp @@ -179,7 +179,7 @@ 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; + power_control_offset_ss ss_profile = power_control_offset_ss::dB0; builder.set_tx_power_info_parameters(power, ss_profile); diff --git a/tests/unittests/fapi/message_builder_helpers.cpp b/tests/unittests/fapi/message_builder_helpers.cpp index 0e2dc64692..218e132632 100644 --- a/tests/unittests/fapi/message_builder_helpers.cpp +++ b/tests/unittests/fapi/message_builder_helpers.cpp @@ -236,7 +236,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(); @@ -277,7 +277,7 @@ dl_csi_rs_pdu unittest::build_valid_dl_csi_pdu() 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.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(); diff --git a/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp b/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp index 823495e013..08ff6572dc 100644 --- a/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_csi_pdu_test.cpp @@ -173,7 +173,7 @@ 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); + static_cast(value); }}), testing::Values(test_case_data{0, true}, test_case_data{1, true}, diff --git a/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp b/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp index 07333f0632..baec42d8f8 100644 --- a/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp +++ b/tests/unittests/fapi/validators/dl_pdsch_pdu_test.cpp @@ -295,7 +295,7 @@ 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); + static_cast(value); }}), testing::Values(test_case_data{0, true}, test_case_data{2, true}, 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 b0668ad8ea..8580354f81 100644 --- a/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp +++ b/tests/unittests/fapi_adaptor/adaptor_performance_dl_tti_request.cpp @@ -147,9 +147,6 @@ static void pdcch_conversion_benchmark() // Payload. dci_payload payload; builder_dci.set_payload(payload); - - optional profile_data; - optional profile_dmrs; builder_dci.set_parameters_v4_dci(nid_dmrs_dist(gen)); pdcch_processor::pdu_t proc_pdu; 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 0c9402c985..c9ac5930a5 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 @@ -96,12 +96,6 @@ TEST(fapi_to_phy_pdcch_conversion_test, valid_pdu_conversion_success) // 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_parameters_v4_dci(nid_dmrs); pdcch_processor::pdu_t proc_pdu; 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 d4e1f1a6e6..055193b595 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 @@ -21,20 +21,20 @@ 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) +static float calculate_ratio_pdsch_data_to_sss_dB(int profile_nr, fapi::power_control_offset_ss profile_ss_nr) { float power_control_offset_ss_dB = 0.0F; switch (profile_ss_nr) { - case fapi::nzp_csi_rs_epre_to_ssb::dB_minus_3: + case fapi::power_control_offset_ss::dB_minus_3: power_control_offset_ss_dB = -3.F; break; - case fapi::nzp_csi_rs_epre_to_ssb::dB0: + case fapi::power_control_offset_ss::dB0: power_control_offset_ss_dB = .0F; break; - case fapi::nzp_csi_rs_epre_to_ssb::dB3: + case fapi::power_control_offset_ss::dB3: power_control_offset_ss_dB = 3.F; break; - case fapi::nzp_csi_rs_epre_to_ssb::dB6: + case fapi::power_control_offset_ss::dB6: default: power_control_offset_ss_dB = 6.F; break; @@ -136,10 +136,10 @@ TEST(fapi_to_phy_pdsch_conversion_test, valid_pdu_conversion_success) 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}) { + 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) { @@ -206,11 +206,6 @@ TEST(fapi_to_phy_pdsch_conversion_test, valid_pdu_conversion_success) } builder.set_pdsch_allocation_in_time_parameters(start_symbol_index, nr_of_symbols); - - optional profile_nr; - optional data_profile_sss; - optional dmrs_profile_sss; - builder.set_tx_power_info_parameters(power_profile_nr, power_ss_profile_nr); // :TODO: not filling CBG to retx control parameters. From fe6fd26bb138e14f762fbbb0dc136bf3b0674ac4 Mon Sep 17 00:00:00 2001 From: ofontbach Date: Mon, 11 Mar 2024 16:08:00 +0100 Subject: [PATCH 27/77] hal: makes sure that the tb-crc static_vector has been initialized before accessing it --- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp index eaa2938398..de83899247 100644 --- a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp +++ b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp @@ -112,7 +112,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. From f84b0a2b4122744f0c76ae1f626bfe224ac31160 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Mon, 4 Mar 2024 10:43:02 +0100 Subject: [PATCH 28/77] srsvec: new phase angle unwrap function --- include/srsran/srsvec/unwrap.h | 32 ++++++++ lib/srsvec/CMakeLists.txt | 3 +- lib/srsvec/unwrap.cpp | 61 ++++++++++++++ tests/unittests/srsvec/CMakeLists.txt | 4 + tests/unittests/srsvec/srsvec_unwrap_test.cpp | 80 +++++++++++++++++++ 5 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 include/srsran/srsvec/unwrap.h create mode 100644 lib/srsvec/unwrap.cpp create mode 100644 tests/unittests/srsvec/srsvec_unwrap_test.cpp diff --git a/include/srsran/srsvec/unwrap.h b/include/srsran/srsvec/unwrap.h new file mode 100644 index 0000000000..aeadc2c26a --- /dev/null +++ b/include/srsran/srsvec/unwrap.h @@ -0,0 +1,32 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +/// \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/lib/srsvec/CMakeLists.txt b/lib/srsvec/CMakeLists.txt index 40ab11e31d..b1c0b756f5 100644 --- a/lib/srsvec/CMakeLists.txt +++ b/lib/srsvec/CMakeLists.txt @@ -21,10 +21,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..6114b39846 --- /dev/null +++ b/lib/srsvec/unwrap.cpp @@ -0,0 +1,61 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +/// \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/tests/unittests/srsvec/CMakeLists.txt b/tests/unittests/srsvec/CMakeLists.txt index decd8a655a..66cbfb3aec 100644 --- a/tests/unittests/srsvec/CMakeLists.txt +++ b/tests/unittests/srsvec/CMakeLists.txt @@ -57,3 +57,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..e28f85e2dd --- /dev/null +++ b/tests/unittests/srsvec/srsvec_unwrap_test.cpp @@ -0,0 +1,80 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +/// \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)); +} From 2d29e1b70cf3ad1adcc88e2c3de677409317cdf0 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 5 Mar 2024 18:06:27 +0100 Subject: [PATCH 29/77] channel estimator: improve estimation at edges Create some out-of-band virtual pilots and use them to improve the channel estimation. --- .../port_channel_estimator_average_impl.cpp | 211 ++++++++++++++---- .../dmrs_pusch_estimator_test_data.h | 98 ++++---- .../dmrs_pusch_estimator_test_data.tar.gz | 4 +- .../port_channel_estimator_test_data.h | 30 +-- .../port_channel_estimator_test_data.tar.gz | 4 +- 5 files changed, 236 insertions(+), 111 deletions(-) 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 e8beca6f4d..a3d18585c3 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 @@ -18,6 +18,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; @@ -32,6 +33,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. /// @@ -84,44 +101,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. @@ -246,9 +248,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]; @@ -268,7 +270,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))); @@ -292,10 +294,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); @@ -417,3 +430,115 @@ static float estimate_time_alignment(span return ta_estimator.estimate(pilots_lse, re_mask, scs).time_alignment; } + +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; + } + + 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); + } +} 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 76ea37fec1..230b17ec87 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 @@ -10,7 +10,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" @@ -33,53 +33,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"}}, @@ -129,53 +129,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/dmrs_pusch_estimator_test_data.tar.gz b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.tar.gz index 6f0f6e16b6..fc98a6d7a2 100644 --- a/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.tar.gz +++ b/tests/unittests/phy/upper/signal_processors/dmrs_pusch_estimator_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e109a9d704f1aba492f498906934926ba4ecddd6fcd61807b8e0ccc052c2621 -size 6436890 +oid sha256:3d8b9a9be2cf0c8361cd104ca7b1b55cf8c2a2b70ec9999bebde7ef2e076277d +size 6434292 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 0ef6bc6aae..382db5c1c7 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.h @@ -10,7 +10,7 @@ #pragma once -// This file was generated using the following MATLAB class on 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" @@ -35,20 +35,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/port_channel_estimator_test_data.tar.gz b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz index eddc10ec0b..4556c7288c 100644 --- a/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz +++ b/tests/unittests/phy/upper/signal_processors/port_channel_estimator_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1acc680053cd663d6bbe9f4310a75b69e7e70b15c26e1f08777a02a844eb86ed -size 93712 +oid sha256:7a356247ed3ab6769a3f34f7edb1e0da78fdce210b5bb935a9f034edb099db20 +size 93600 From 8f4801600d856c26766e73bb4f61c29dfef78d98 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 5 Mar 2024 18:30:13 +0100 Subject: [PATCH 30/77] tests: update pdcch-related vectors Follows from fixing a minor bug in the generation of these test vectors. --- .../pdcch_modulator_test_data.h | 28 +- .../pdcch_modulator_test_data.tar.gz | 4 +- .../pdcch_processor_test_data.h | 226 ++++----- .../pdcch_processor_test_data.tar.gz | 4 +- .../ran/pdcch/pdcch_candidates_ue_test_data.h | 432 +++++++++--------- 5 files changed, 347 insertions(+), 347 deletions(-) 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 a8557e7c79..b9aed44260 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 @@ -10,7 +10,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" @@ -30,22 +30,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_modulator_test_data.tar.gz b/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.tar.gz index 190439783c..58cece2279 100644 --- a/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.tar.gz +++ b/tests/unittests/phy/upper/channel_processors/pdcch_modulator_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad433b6e54650629287b046a95a48c0b4b3ee66fdd81eddecb16c9a87870b6c4 -size 16808 +oid sha256:3d0a705eb9d3e50833273bd0562b7c995f6eab361ea708cf7975bc3efa884e23 +size 16997 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 4de05a853e..a3b61a0769 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 @@ -10,7 +10,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" @@ -28,122 +28,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/pdcch_processor_test_data.tar.gz b/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.tar.gz index c501f51825..55b6e191eb 100644 --- a/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.tar.gz +++ b/tests/unittests/phy/upper/channel_processors/pdcch_processor_test_data.tar.gz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1b9934ff65bbdc824fcdcce0b6c49a958d01213f11956f7f628c7edf621647f -size 124241 +oid sha256:0b7e65eff3bc130440c94fea4c79f1aae025caf257631ee0b53fba3a4a0eab32 +size 124919 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 f2f1c4e582..732f7053e6 100644 --- a/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h +++ b/tests/unittests/ran/pdcch/pdcch_candidates_ue_test_data.h @@ -10,7 +10,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" @@ -24,224 +24,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 }; From 84468b81420e40400bbb8cdf2519bb5175ccee3d Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 11 Mar 2024 10:42:33 +0100 Subject: [PATCH 31/77] gnb: use a dedicated strand for each DU to handle RB-specific tasks --- apps/gnb/gnb_worker_manager.cpp | 65 ++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 796693ce80..75397256af 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -10,7 +10,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" @@ -84,6 +83,32 @@ 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; @@ -108,7 +133,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(), @@ -118,21 +143,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. @@ -140,6 +151,17 @@ 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_spsc, + 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 @@ -152,7 +174,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) 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}}}); } @@ -233,9 +255,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"), From 56d55bb444a591163ea4020e63a7d43fdd36e03a Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 11 Mar 2024 11:01:02 +0100 Subject: [PATCH 32/77] cu-up: use single object to manage lifetime of executors of a PDU session --- include/srsran/cu_up/cu_up_executor_pool.h | 32 +++++--- lib/cu_up/cu_up_executor_mapper.cpp | 94 ++++++++++++---------- lib/cu_up/cu_up_impl.cpp | 7 +- lib/cu_up/cu_up_impl.h | 2 +- lib/cu_up/ue_context.h | 46 +++++------ lib/cu_up/ue_manager.cpp | 14 ++-- tests/unittests/cu_up/cu_up_test_helpers.h | 48 ++++------- 7 files changed, 117 insertions(+), 126 deletions(-) diff --git a/include/srsran/cu_up/cu_up_executor_pool.h b/include/srsran/cu_up/cu_up_executor_pool.h index 8cab12ebba..40998ead32 100644 --- a/include/srsran/cu_up/cu_up_executor_pool.h +++ b/include/srsran/cu_up/cu_up_executor_pool.h @@ -15,28 +15,36 @@ namespace srsran { -/// \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 PDU session in the CU-CP. +class pdu_session_executor_mapper { public: - using ptr = std::unique_ptr>; + virtual ~pdu_session_executor_mapper() = default; - virtual ~cu_up_executor_pool() = default; + /// \brief Returns the task executor appropriate for the control aspects of the PDU session (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 new PDU session. + virtual std::unique_ptr create_pdu_session() = 0; }; /// \brief Creates an executor mapper for the CU-UP. diff --git a/lib/cu_up/cu_up_executor_mapper.cpp b/lib/cu_up/cu_up_executor_mapper.cpp index cc7fe8ed11..1f86db523f 100644 --- a/lib/cu_up/cu_up_executor_mapper.cpp +++ b/lib/cu_up/cu_up_executor_mapper.cpp @@ -12,65 +12,77 @@ using namespace srsran; -class cu_up_executor_mapper_impl : public cu_up_executor_pool +class cu_up_executor_mapper_impl final : public cu_up_executor_pool { + struct session_executor_context { + task_executor& ctrl_exec; + task_executor& ul_exec; + task_executor& dl_exec; + + session_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: + class pdu_session_executor_mapper_impl final : public pdu_session_executor_mapper + { + public: + pdu_session_executor_mapper_impl(cu_up_executor_mapper_impl& parent_, session_executor_context& ctxt_) : + parent(parent_), ctxt(ctxt_) + { + } + + ~pdu_session_executor_mapper_impl() override { parent.deregister_pdu_session(ctxt); } + + task_executor& ctrl_executor() override { return ctxt.ctrl_exec; } + task_executor& ul_pdu_executor() override { return ctxt.ul_exec; } + task_executor& dl_pdu_executor() override { return ctxt.dl_exec; } + + private: + cu_up_executor_mapper_impl& parent; + session_executor_context& ctxt; + }; + 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()); - } + 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"); + } - 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); - } - }}; + for (unsigned i = 0; i != ctrl_executors.size(); ++i) { + sessions.emplace_back(*ctrl_executors[i], *ul_executors[i], *dl_executors[i]); + } } - ptr create_ctrl_executor() override + std::unique_ptr create_pdu_session() 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); - } - }}; + return std::make_unique( + *this, sessions[round_robin_index.fetch_add(1, std::memory_order_relaxed) % sessions.size()]); } private: - void dealloc_pdu_executor(task_executor* exec) - { - // do nothing. - } - void dealloc_ctrl_executor(task_executor* exec) + void deregister_pdu_session(session_executor_context& session_ctxt) { // do nothing. } - std::vector dl_execs; - std::vector ul_execs; - std::vector ctrl_execs; + std::vector sessions; - std::atomic round_robin_dl_index{0}; - std::atomic round_robin_ul_index{0}; - std::atomic round_robin_ctrl_index{0}; + std::atomic round_robin_index{0}; }; std::unique_ptr srsran::make_cu_up_executor_mapper(span dl_executors, diff --git a/lib/cu_up/cu_up_impl.cpp b/lib/cu_up/cu_up_impl.cpp index 3284de818f..24bb04a721 100644 --- a/lib/cu_up/cu_up_impl.cpp +++ b/lib/cu_up/cu_up_impl.cpp @@ -56,15 +56,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_pdu_session(); + 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 b2115337ca..6854e3d2d3 100644 --- a/lib/cu_up/cu_up_impl.h +++ b/lib/cu_up/cu_up_impl.h @@ -68,7 +68,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 83a65a71aa..b58f1fc8f0 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -35,22 +35,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 pdu_session_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_}), @@ -69,13 +67,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_, + pdu_session_exec_mapper_->dl_pdu_executor(), + pdu_session_exec_mapper_->ul_pdu_executor(), + pdu_session_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_)), + pdu_session_exec_mapper(std::move(pdu_session_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_) @@ -122,9 +118,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 pdu_session_exec_mapper; timer_factory ue_dl_timer_factory; timer_factory ue_ul_timer_factory; @@ -142,7 +136,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 (!pdu_session_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 94ec788da8..0f272e0f31 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -60,14 +60,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 pdu_session_execs = exec_pool.create_pdu_session(); // 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, pdu_session_execs->dl_pdu_executor()}; + timer_factory ue_ul_timer_factory = {timers, pdu_session_execs->ul_pdu_executor()}; + timer_factory ue_ctrl_timer_factory = {timers, pdu_session_execs->ctrl_executor()}; // Create UE object std::unique_ptr new_ctx = std::make_unique(new_idx, @@ -75,9 +73,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(pdu_session_execs), ue_dl_timer_factory, ue_ul_timer_factory, ue_ctrl_timer_factory, diff --git a/tests/unittests/cu_up/cu_up_test_helpers.h b/tests/unittests/cu_up/cu_up_test_helpers.h index 92cfb9f681..77fc98a396 100644 --- a/tests/unittests/cu_up/cu_up_test_helpers.h +++ b/tests/unittests/cu_up/cu_up_test_helpers.h @@ -31,47 +31,27 @@ namespace srsran { /// Dummy CU-UP executor pool used for testing class dummy_cu_up_executor_pool final : public 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 pdu_session_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_) {} - ptr create_dl_pdu_executor() override - { - return {test_executor, [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } + task_executor& ctrl_executor() override { return *exec; } + task_executor& ul_pdu_executor() override { return *exec; } + task_executor& dl_pdu_executor() override { return *exec; } - ptr create_ctrl_executor() override - { - return {test_executor, [this](task_executor* p) { - if (p != nullptr) { - dealloc_pdu_executor(p); - } - }}; - } + task_executor* exec; + }; -private: - void dealloc_pdu_executor(task_executor* exec) - { - // do nothing. - } - void dealloc_ctrl_executor(task_executor* exec) +public: + dummy_cu_up_executor_pool(task_executor* test_executor_) : test_executor(test_executor_) {} + + std::unique_ptr create_pdu_session() override { - // do nothing. + return std::make_unique(*test_executor); } +private: task_executor* test_executor; }; From b533847a1478bd67bf0cbd5f4db4c108dbcef731 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 11 Mar 2024 11:31:54 +0100 Subject: [PATCH 33/77] cu-up: make the destruction of the UE in the CU-UP an async task that awaits for the completion of all the pending UE tasks --- apps/gnb/gnb_worker_manager.cpp | 5 +- apps/gnb/gnb_worker_manager.h | 2 +- include/srsran/cu_up/cu_up_executor_pool.h | 23 +++-- lib/cu_up/cu_up_executor_mapper.cpp | 99 ++++++++++++++++------ lib/cu_up/cu_up_impl.cpp | 2 +- lib/cu_up/cu_up_impl.h | 4 +- lib/cu_up/ue_context.h | 42 ++++----- lib/cu_up/ue_manager.cpp | 30 ++++--- lib/cu_up/ue_manager.h | 3 + tests/unittests/cu_up/cu_up_test_helpers.h | 14 ++- 10 files changed, 153 insertions(+), 71 deletions(-) diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 75397256af..9345f9f801 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -158,7 +158,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) {{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_spsc, + concurrent_queue_policy::lockfree_mpmc, appcfg.cu_up_cfg.gtpu_queue_size}}}); } @@ -243,7 +243,8 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) 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_mapper(*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); diff --git a/apps/gnb/gnb_worker_manager.h b/apps/gnb/gnb_worker_manager.h index 7783fcae32..f74acce016 100644 --- a/apps/gnb/gnb_worker_manager.h +++ b/apps/gnb/gnb_worker_manager.h @@ -63,7 +63,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/include/srsran/cu_up/cu_up_executor_pool.h b/include/srsran/cu_up/cu_up_executor_pool.h index 40998ead32..7e81363f91 100644 --- a/include/srsran/cu_up/cu_up_executor_pool.h +++ b/include/srsran/cu_up/cu_up_executor_pool.h @@ -11,17 +11,24 @@ #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 This class holds the executors available to a given UE PDU session in the CU-CP. -class pdu_session_executor_mapper +/// \brief This class holds the executors available to a given UE in the CU-UP. +class ue_executor_mapper { public: - virtual ~pdu_session_executor_mapper() = default; + virtual ~ue_executor_mapper() = default; - /// \brief Returns the task executor appropriate for the control aspects of the PDU session (e.g. timers, deletion). + /// \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 Returns the task executor to handle UL PDUs in the user plane. @@ -43,13 +50,15 @@ class cu_up_executor_pool public: virtual ~cu_up_executor_pool() = default; - /// \brief Instantiate executors for a new PDU session. - virtual std::unique_ptr create_pdu_session() = 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, +std::unique_ptr make_cu_up_executor_mapper(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/lib/cu_up/cu_up_executor_mapper.cpp b/lib/cu_up/cu_up_executor_mapper.cpp index 1f86db523f..c3b7806e9b 100644 --- a/lib/cu_up/cu_up_executor_mapper.cpp +++ b/lib/cu_up/cu_up_executor_mapper.cpp @@ -9,45 +9,89 @@ */ #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_mapper_impl final : public cu_up_executor_pool +class cu_up_executor_pool_impl final : public cu_up_executor_pool { - struct session_executor_context { + struct ue_executor_context { task_executor& ctrl_exec; task_executor& ul_exec; task_executor& dl_exec; - session_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: - class pdu_session_executor_mapper_impl final : public pdu_session_executor_mapper + /// Implementation of the UE executor mapper. + class ue_executor_mapper_impl final : public ue_executor_mapper { public: - pdu_session_executor_mapper_impl(cu_up_executor_mapper_impl& parent_, session_executor_context& ctxt_) : - parent(parent_), ctxt(ctxt_) + ue_executor_mapper_impl(cu_up_executor_pool_impl& parent_, ue_executor_context& ctxt_) : + parent(parent_), ctxt(&ctxt_) { } - ~pdu_session_executor_mapper_impl() override { parent.deregister_pdu_session(ctxt); } + ~ue_executor_mapper_impl() override { parent.release_ue_executors(*ctxt); } - task_executor& ctrl_executor() override { return ctxt.ctrl_exec; } - task_executor& ul_pdu_executor() override { return ctxt.ul_exec; } - task_executor& dl_pdu_executor() override { return ctxt.dl_exec; } + 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_mapper_impl& parent; - session_executor_context& ctxt; + cu_up_executor_pool_impl& parent; + ue_executor_context* ctxt; }; - cu_up_executor_mapper_impl(span dl_executors, - span ul_executors, - span ctrl_executors) + 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()) { @@ -64,30 +108,35 @@ class cu_up_executor_mapper_impl final : public cu_up_executor_pool } for (unsigned i = 0; i != ctrl_executors.size(); ++i) { - sessions.emplace_back(*ctrl_executors[i], *ul_executors[i], *dl_executors[i]); + execs.emplace_back(*ctrl_executors[i], *ul_executors[i], *dl_executors[i]); } } - std::unique_ptr create_pdu_session() override + std::unique_ptr create_ue_executor_mapper() override { - return std::make_unique( - *this, sessions[round_robin_index.fetch_add(1, std::memory_order_relaxed) % sessions.size()]); + return std::make_unique( + *this, execs[round_robin_index.fetch_add(1, std::memory_order_relaxed) % execs.size()]); } private: - void deregister_pdu_session(session_executor_context& session_ctxt) + void release_ue_executors(ue_executor_context& ue_execs) { // do nothing. } - std::vector sessions; + // 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::make_cu_up_executor_mapper(span dl_executors, - span ul_executors, - span ctrl_executors) +std::unique_ptr srsran::srs_cu_up::make_cu_up_executor_mapper(task_executor& cu_up_main_exec, + span dl_executors, + span ul_executors, + span ctrl_executors) { - return std::make_unique(dl_executors, ul_executors, ctrl_executors); + return std::make_unique(cu_up_main_exec, dl_executors, ul_executors, ctrl_executors); } diff --git a/lib/cu_up/cu_up_impl.cpp b/lib/cu_up/cu_up_impl.cpp index 24bb04a721..836cbb58c5 100644 --- a/lib/cu_up/cu_up_impl.cpp +++ b/lib/cu_up/cu_up_impl.cpp @@ -56,7 +56,7 @@ 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); - ctrl_exec_mapper = cfg.ue_exec_pool->create_pdu_session(); + 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 diff --git a/lib/cu_up/cu_up_impl.h b/lib/cu_up/cu_up_impl.h index 6854e3d2d3..3b1b7aa196 100644 --- a/lib/cu_up/cu_up_impl.h +++ b/lib/cu_up/cu_up_impl.h @@ -32,7 +32,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; @@ -68,7 +68,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 ctrl_exec_mapper; + 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 b58f1fc8f0..1fa0eda3b9 100644 --- a/lib/cu_up/ue_context.h +++ b/lib/cu_up/ue_context.h @@ -35,20 +35,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 pdu_session_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) : + 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_}), @@ -67,11 +67,11 @@ class ue_context : public pdu_session_manager_ctrl f1u_teid_allocator_, gtpu_tx_notifier_, gtpu_rx_demux_, - pdu_session_exec_mapper_->dl_pdu_executor(), - pdu_session_exec_mapper_->ul_pdu_executor(), - pdu_session_exec_mapper_->ctrl_executor(), + ue_exec_mapper_->dl_pdu_executor(), + ue_exec_mapper_->ul_pdu_executor(), + ue_exec_mapper_->ctrl_executor(), gtpu_pcap), - pdu_session_exec_mapper(std::move(pdu_session_exec_mapper_)), + 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_) @@ -89,6 +89,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 { @@ -118,7 +120,7 @@ class ue_context : public pdu_session_manager_ctrl e1ap_control_message_handler& e1ap; pdu_session_manager_impl pdu_session_manager; - std::unique_ptr pdu_session_exec_mapper; + std::unique_ptr ue_exec_mapper; timer_factory ue_dl_timer_factory; timer_factory ue_ul_timer_factory; @@ -136,7 +138,7 @@ class ue_context : public pdu_session_manager_ctrl e1ap.handle_bearer_context_inactivity_notification(msg); }; - if (!pdu_session_exec_mapper->ctrl_executor().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 0f272e0f31..99608952ee 100644 --- a/lib/cu_up/ue_manager.cpp +++ b/lib/cu_up/ue_manager.cpp @@ -34,7 +34,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) { } @@ -60,12 +61,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 pdu_session_execs = exec_pool.create_pdu_session(); + std::unique_ptr ue_exec_mapper = exec_pool.create_ue_executor_mapper(); // Create executor-specific timer factories - timer_factory ue_dl_timer_factory = {timers, pdu_session_execs->dl_pdu_executor()}; - timer_factory ue_ul_timer_factory = {timers, pdu_session_execs->ul_pdu_executor()}; - timer_factory ue_ctrl_timer_factory = {timers, pdu_session_execs->ctrl_executor()}; + 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, @@ -73,7 +74,7 @@ ue_context* ue_manager::add_ue(const ue_context_cfg& ue_cfg) e1ap, net_config, n3_config, - std::move(pdu_session_execs), + std::move(ue_exec_mapper), ue_dl_timer_factory, ue_ul_timer_factory, ue_ctrl_timer_factory, @@ -90,15 +91,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 05f8a38554..b2b16a5280 100644 --- a/lib/cu_up/ue_manager.h +++ b/lib/cu_up/ue_manager.h @@ -14,6 +14,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 { @@ -60,6 +61,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/tests/unittests/cu_up/cu_up_test_helpers.h b/tests/unittests/cu_up/cu_up_test_helpers.h index 77fc98a396..8bb1641da1 100644 --- a/tests/unittests/cu_up/cu_up_test_helpers.h +++ b/tests/unittests/cu_up/cu_up_test_helpers.h @@ -29,9 +29,9 @@ 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 { - class dummy_pdu_session_executor_mapper_impl : public pdu_session_executor_mapper + class dummy_pdu_session_executor_mapper_impl : public srs_cu_up::ue_executor_mapper { public: dummy_pdu_session_executor_mapper_impl(task_executor& exec_) : exec(&exec_) {} @@ -40,13 +40,21 @@ class dummy_cu_up_executor_pool final : public cu_up_executor_pool 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(); + }); + } + task_executor* exec; }; public: dummy_cu_up_executor_pool(task_executor* test_executor_) : test_executor(test_executor_) {} - std::unique_ptr create_pdu_session() override + std::unique_ptr create_ue_executor_mapper() override { return std::make_unique(*test_executor); } From 32704634121880fd1c95fb2edb57140f33dbe42a Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Mon, 11 Mar 2024 11:42:02 +0100 Subject: [PATCH 34/77] cu-up: instantiate multiple strands for UEs in the CU-UP --- apps/gnb/gnb.cpp | 14 +++++++------- apps/gnb/gnb_worker_manager.cpp | 25 +++++++++++++------------ apps/gnb/gnb_worker_manager.h | 7 +++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/apps/gnb/gnb.cpp b/apps/gnb/gnb.cpp index 23c3c48026..36149686c0 100644 --- a/apps/gnb/gnb.cpp +++ b/apps/gnb/gnb.cpp @@ -471,13 +471,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_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 9345f9f801..7f999d5b22 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -166,8 +166,10 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) // 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_exec", concurrent_queue_policy::lockfree_mpmc, 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), @@ -229,22 +231,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_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 = - srs_cu_up::make_cu_up_executor_mapper(*cu_up_ctrl_exec, ue_up_dl_execs, ue_up_ul_execs, ue_up_ctrl_execs); + cu_up_exec_mapper = srs_cu_up::make_cu_up_executor_mapper( + *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); diff --git a/apps/gnb/gnb_worker_manager.h b/apps/gnb/gnb_worker_manager.h index f74acce016..f927f526b3 100644 --- a/apps/gnb/gnb_worker_manager.h +++ b/apps/gnb/gnb_worker_manager.h @@ -38,10 +38,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; From 9e4fce1ab92cf1d737c56f387b1b65ec7d2da8f8 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Wed, 13 Mar 2024 10:46:05 +0100 Subject: [PATCH 35/77] cu-up: rename executor pool class and executors of CU-UP --- apps/gnb/gnb_worker_manager.cpp | 12 ++++++++---- include/srsran/cu_up/cu_up_executor_pool.h | 8 ++++---- lib/cu_up/CMakeLists.txt | 2 +- ...p_executor_mapper.cpp => cu_up_executor_pool.cpp} | 11 ++++++----- 4 files changed, 19 insertions(+), 14 deletions(-) rename lib/cu_up/{cu_up_executor_mapper.cpp => cu_up_executor_pool.cpp} (92%) diff --git a/apps/gnb/gnb_worker_manager.cpp b/apps/gnb/gnb_worker_manager.cpp index 7f999d5b22..5ccb53887e 100644 --- a/apps/gnb/gnb_worker_manager.cpp +++ b/apps/gnb/gnb_worker_manager.cpp @@ -95,14 +95,17 @@ void append_pcap_strands(std::vector& strand_li 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); @@ -166,8 +169,9 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) // 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. - cu_up_strands.push_back(strand{{{"cu_up_ctrl_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}, - {"cu_up_io_exec", concurrent_queue_policy::lockfree_mpmc, task_worker_queue_size}}}); + 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( @@ -232,7 +236,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) cu_cp_e2_exec = exec_map.at("ctrl_exec"); metrics_hub_exec = exec_map.at("ctrl_exec"); cu_up_ctrl_exec = exec_map.at("cu_up_ctrl_exec"); - cu_up_io_ul_exec = exec_map.at("cu_up_io_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. @@ -244,7 +248,7 @@ void worker_manager::create_du_cu_executors(const gnb_appconfig& appcfg) 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 = srs_cu_up::make_cu_up_executor_mapper( + 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. diff --git a/include/srsran/cu_up/cu_up_executor_pool.h b/include/srsran/cu_up/cu_up_executor_pool.h index 7e81363f91..ef1a2cdee1 100644 --- a/include/srsran/cu_up/cu_up_executor_pool.h +++ b/include/srsran/cu_up/cu_up_executor_pool.h @@ -55,10 +55,10 @@ class cu_up_executor_pool }; /// \brief Creates an executor mapper for the CU-UP. -std::unique_ptr make_cu_up_executor_mapper(task_executor& cu_up_main_executor, - 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/lib/cu_up/CMakeLists.txt b/lib/cu_up/CMakeLists.txt index d8c7b05557..ee22abb82a 100644 --- a/lib/cu_up/CMakeLists.txt +++ b/lib/cu_up/CMakeLists.txt @@ -7,7 +7,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_pool.cpp similarity index 92% rename from lib/cu_up/cu_up_executor_mapper.cpp rename to lib/cu_up/cu_up_executor_pool.cpp index c3b7806e9b..c58997c157 100644 --- a/lib/cu_up/cu_up_executor_mapper.cpp +++ b/lib/cu_up/cu_up_executor_pool.cpp @@ -133,10 +133,11 @@ class cu_up_executor_pool_impl final : public cu_up_executor_pool std::atomic round_robin_index{0}; }; -std::unique_ptr srsran::srs_cu_up::make_cu_up_executor_mapper(task_executor& cu_up_main_exec, - span dl_executors, - span ul_executors, - span ctrl_executors) +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_exec, dl_executors, ul_executors, ctrl_executors); + return std::make_unique( + cu_up_main_executor, dl_pdu_executors, ul_pdu_executors, ctrl_executors); } From 9f9fbd385b93b48f0dcf22f843186383fe86de8e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 12 Mar 2024 15:38:27 +0100 Subject: [PATCH 36/77] sched: wait for all UCI PDUs to be scheduled before removing the UE --- lib/scheduler/cell/resource_grid.cpp | 3 +- lib/scheduler/cell/resource_grid.h | 5 +- lib/scheduler/cell/resource_grid_util.h | 8 +++ .../uci_scheduling/uci_scheduler_impl.cpp | 1 - lib/scheduler/ue_scheduling/ue_repository.cpp | 31 ++++++--- lib/scheduler/ue_scheduling/ue_repository.h | 8 ++- .../scheduler/scheduler_ue_removal_test.cpp | 65 ++++++++++++++++--- 7 files changed, 97 insertions(+), 24 deletions(-) diff --git a/lib/scheduler/cell/resource_grid.cpp b/lib/scheduler/cell/resource_grid.cpp index 1a1eaef4dc..9b6e7f475e 100644 --- a/lib/scheduler/cell/resource_grid.cpp +++ b/lib/scheduler/cell/resource_grid.cpp @@ -289,8 +289,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 16a8a392e4..ec6e4e10cb 100644 --- a/lib/scheduler/cell/resource_grid.h +++ b/lib/scheduler/cell/resource_grid.h @@ -248,9 +248,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 43faa95c71..f52670da66 100644 --- a/lib/scheduler/cell/resource_grid_util.h +++ b/lib/scheduler/cell/resource_grid_util.h @@ -10,6 +10,8 @@ #pragma once +#include "srsran/scheduler/sched_consts.h" + namespace srsran { /// \brief Retrieves the resource grid allocator ring size greater than given minimum value. @@ -36,4 +38,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/uci_scheduling/uci_scheduler_impl.cpp b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp index 9373155991..9b9d15d134 100644 --- a/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp +++ b/lib/scheduler/uci_scheduling/uci_scheduler_impl.cpp @@ -237,7 +237,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/ue_repository.cpp b/lib/scheduler/ue_scheduling/ue_repository.cpp index a0c1230207..9235e9ba80 100644 --- a/lib/scheduler/ue_scheduling/ue_repository.cpp +++ b/lib/scheduler/ue_scheduling/ue_repository.cpp @@ -9,6 +9,7 @@ */ #include "ue_repository.h" +#include "../cell/resource_grid_util.h" using namespace srsran; @@ -53,15 +54,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]; @@ -84,13 +93,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(); } @@ -116,10 +125,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 696678c301..f93c34988f 100644 --- a/lib/scheduler/ue_scheduling/ue_repository.h +++ b/lib/scheduler/ue_scheduling/ue_repository.h @@ -71,8 +71,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/tests/unittests/scheduler/scheduler_ue_removal_test.cpp b/tests/unittests/scheduler/scheduler_ue_removal_test.cpp index a3fac60b4e..2f44b1161a 100644 --- a/tests/unittests/scheduler/scheduler_ue_removal_test.cpp +++ b/tests/unittests/scheduler/scheduler_ue_removal_test.cpp @@ -11,6 +11,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" @@ -18,6 +19,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( @@ -48,10 +51,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); @@ -59,14 +83,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) @@ -92,6 +129,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. @@ -125,12 +163,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) @@ -145,10 +193,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. From 2040c6dae4ed455626eeb0daa7e012b0a148f403 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 12 Mar 2024 16:25:03 +0100 Subject: [PATCH 37/77] ngap: write to pcap NGAP Tx PDUs when no-core option is used --- apps/gnb/adapters/ngap_adapter.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/gnb/adapters/ngap_adapter.cpp b/apps/gnb/adapters/ngap_adapter.cpp index d1fa7951d4..fd4f56e6ee 100644 --- a/apps/gnb/adapters/ngap_adapter.cpp +++ b/apps/gnb/adapters/ngap_adapter.cpp @@ -39,6 +39,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) { From 589265e706d60543ee50b5b308b4202a98058f49 Mon Sep 17 00:00:00 2001 From: asaezper Date: Wed, 13 Mar 2024 11:33:00 +0100 Subject: [PATCH 38/77] ci,e2e: change x300/n300 request --- .gitlab/ci/e2e/.env | 2 +- .gitlab/ci/e2e/retina_request_android_n300.yml | 10 +++++----- .gitlab/ci/e2e/retina_request_android_x300.yml | 10 +++++----- .gitlab/ci/e2e/retina_request_zmq.yml | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index fa24f2da95..535f469057 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.44.8 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_zmq.yml b/.gitlab/ci/e2e/retina_request_zmq.yml index 12b5fea347..ec19cacd76 100644 --- a/.gitlab/ci/e2e/retina_request_zmq.yml +++ b/.gitlab/ci/e2e/retina_request_zmq.yml @@ -43,8 +43,8 @@ requests: "8G" limits: "8G" ephemeral-storage: - requests: "6G" - limits: "6G" + requests: "15G" + limits: "15G" resources: - type: zmq environment: From 4bd083b6754721b8af18ce12eda03d2994c96258 Mon Sep 17 00:00:00 2001 From: qarlosalberto Date: Tue, 12 Mar 2024 17:02:33 +0100 Subject: [PATCH 39/77] ci: add viavi tests --- .gitlab/ci/e2e.yml | 1 - .gitlab/ci/e2e/retina_request_viavi.yml | 6 +++--- .gitlab/run_viavi_pipeline.py | 2 +- tests/e2e/tests/viavi.py | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.gitlab/ci/e2e.yml b/.gitlab/ci/e2e.yml index 49f81799ad..e175750e98 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -517,7 +517,6 @@ android n300: viavi: stage: rf extends: .e2e-run - when: manual allow_failure: true variables: GROUP: "viavi" 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/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/tests/e2e/tests/viavi.py b/tests/e2e/tests/viavi.py index 53707257fd..0d9676c978 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -95,18 +95,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", ), ), @@ -127,6 +131,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, @@ -155,6 +160,7 @@ def test_viavi( gnb_stop_timeout=gnb_stop_timeout, log_search=log_search, post_commands=post_commands, + max_rb_size=max_rb_size, ) @@ -179,17 +185,14 @@ 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 """ retina_data.test_config = { "gnb": { - "parameters": { - "gnb_id": 1, - "log_level": "warning", - "pcap": False, - }, + "parameters": {"gnb_id": 1, "log_level": "warning", "pcap": False, "max_rb_size": max_rb_size}, "templates": {"cell": str(Path(__file__).joinpath("../viavi/config.yml").resolve())}, }, } From 0ef129acec489b090a16a6edffd6875ae0b15e5e Mon Sep 17 00:00:00 2001 From: Pavel Harbanau Date: Wed, 13 Mar 2024 18:34:28 +0000 Subject: [PATCH 40/77] gnb: prevent crashing in CPU index validation when the config is invalid --- apps/gnb/gnb_appconfig_cli11_schema.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/gnb/gnb_appconfig_cli11_schema.cpp b/apps/gnb/gnb_appconfig_cli11_schema.cpp index e04032a7c0..21edd20cb6 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -1956,11 +1956,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(); } From 4b0816dfa361b750c58934f7d07a8a86b24b86ca Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Wed, 13 Mar 2024 10:44:30 +0100 Subject: [PATCH 41/77] misc: update clang tidy config - disable include cleaner (new in clang v17.0.6) --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) 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, From 677e403dc46ed05d2dc53e515f4af25acc478fb9 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 13 Mar 2024 13:36:45 +0000 Subject: [PATCH 42/77] trace: allow setting L1, L2 and UP traces from define this allows the user to set the traces from the command line, using something like `-DCMAKE_CXX_FLAGS="-D SRSRAN_L2_TRACE"`. --- include/srsran/instrumentation/traces/du_traces.h | 11 +++++++++-- include/srsran/instrumentation/traces/up_traces.h | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/srsran/instrumentation/traces/du_traces.h b/include/srsran/instrumentation/traces/du_traces.h index 4362fbe7c0..e86e53ab97 100644 --- a/include/srsran/instrumentation/traces/du_traces.h +++ b/include/srsran/instrumentation/traces/du_traces.h @@ -15,15 +15,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 238c53b3b4..abf3011338 100644 --- a/include/srsran/instrumentation/traces/up_traces.h +++ b/include/srsran/instrumentation/traces/up_traces.h @@ -14,7 +14,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. From acc8d5570f0f4d465dd265f6f669635ea7595495 Mon Sep 17 00:00:00 2001 From: faluco Date: Mon, 11 Mar 2024 14:09:29 +0100 Subject: [PATCH 43/77] byte_buffer_chain: ban constructors in favour of factory methods byte_buffer: ban constructors in favour of factory methods byte_buffer: use expected<> for deep copies --- apps/examples/du/du_example.cpp | 2 +- include/srsran/adt/byte_buffer.h | 49 +-- include/srsran/adt/byte_buffer_chain.h | 57 ++-- include/srsran/f1u/common/nru_message.h | 6 +- .../inter_cu_handover_target_routine.cpp | 24 +- .../inter_cu_handover_target_routine.h | 2 +- .../pdu_session_resource_setup_routine.cpp | 23 +- .../pdu_session_resource_setup_routine.h | 2 +- .../adapters/mac_test_mode_adapter.cpp | 34 +- lib/du_high/du_high_impl.cpp | 18 +- .../common/e2_subscription_manager_impl.cpp | 9 +- lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp | 30 +- lib/f1u/cu_up/f1u_bearer_impl.cpp | 8 +- .../mac/fapi_to_mac_data_msg_translator.cpp | 14 +- lib/gateways/sctp_network_gateway_impl.cpp | 8 +- lib/gtpu/gtpu_demux_impl.cpp | 7 +- lib/gtpu/gtpu_tunnel_base_tx.h | 7 +- lib/pcap/backend_pcap_writer.h | 11 +- lib/pcap/dlt_pcap_impl.cpp | 18 +- lib/pcap/mac_pcap_impl.cpp | 41 ++- lib/pdcp/pdcp_entity_rx.cpp | 6 +- lib/pdcp/pdcp_entity_tx.cpp | 25 +- lib/rrc/ue/rrc_ue_srb_context.h | 7 +- lib/support/byte_buffer_chain.cpp | 21 +- .../benchmarks/du_high/du_high_benchmark.cpp | 17 +- tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp | 16 +- tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp | 10 +- .../rlc/rlc_handle_status_report.cpp | 16 +- .../integrationtests/rlc/rlc_stress_test_f1.h | 2 +- .../rlc/rlc_stress_test_mac.cpp | 4 +- tests/test_doubles/mac/mac_test_messages.cpp | 14 +- .../unittests/adt/byte_buffer_chain_test.cpp | 63 ++-- tests/unittests/adt/byte_buffer_test.cpp | 69 ++-- tests/unittests/asn1/asn1_e1ap_test.cpp | 4 +- tests/unittests/asn1/asn1_f1ap_test.cpp | 6 +- tests/unittests/asn1/asn1_ngap_test.cpp | 18 +- tests/unittests/asn1/asn1_rrc_nr_test.cpp | 208 ++++++------ tests/unittests/asn1/asn1_utils_test.cpp | 2 +- .../cu_cp/du_processor_test_messages.cpp | 2 +- tests/unittests/cu_up/cu_up_test.cpp | 8 +- tests/unittests/cu_up/cu_up_test_helpers.h | 2 +- .../du_manager/du_manager_test_helpers.h | 4 +- .../du_manager/du_ue/ue_manager_test.cpp | 2 +- .../du_manager_procedure_test_helpers.cpp | 2 +- .../procedures/ue_configuration_test.cpp | 16 +- .../unittests/e2/e2_setup_procedure_test.cpp | 12 +- .../e2/e2_subscription_setup_test.cpp | 16 +- .../f1ap/common/f1ap_cu_test_messages.h | 4 +- .../f1ap/common/f1ap_du_test_messages.cpp | 2 +- .../f1ap/cu_cp/f1ap_cu_test_helpers.cpp | 3 +- .../f1ap_du_dl_rrc_message_transfer_test.cpp | 6 +- .../f1ap/du/f1ap_du_test_helpers.cpp | 7 +- .../f1ap/du/f1ap_du_ue_config_test.cpp | 11 +- .../f1ap_du_ue_context_modification_test.cpp | 6 +- ...1ap_du_ue_context_setup_procedure_test.cpp | 9 +- .../f1ap_du_ul_rrc_message_transfer_test.cpp | 4 +- .../f1u/common/f1u_connector_test.cpp | 72 ++-- .../f1u/cu_up/f1u_cu_up_bearer_test.cpp | 14 +- tests/unittests/f1u/du/f1u_du_bearer_test.cpp | 56 ++-- tests/unittests/gtpu/gtpu_demux_test.cpp | 8 +- tests/unittests/gtpu/gtpu_echo_test.cpp | 6 +- tests/unittests/gtpu/gtpu_test.cpp | 37 ++- .../gtpu/gtpu_tunnel_ngu_rx_test.cpp | 42 +-- tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp | 6 +- .../mac/dl_sch_pdu_assembler_test.cpp | 8 +- .../mac/mac_rar_pdu_assembler_test.cpp | 2 +- tests/unittests/mac/mac_test_helpers.h | 2 +- tests/unittests/mac/mac_ul_pdu_test.cpp | 52 +-- tests/unittests/mac/mac_ul_processor_test.cpp | 30 +- .../unittests/ngap/ngap_asn1_packer_test.cpp | 2 +- tests/unittests/pcap/mac_pcap_test.cpp | 11 +- tests/unittests/pcap/ngap_pcap_test.cpp | 10 +- tests/unittests/pdcp/pdcp_gen_helper.cpp | 2 +- tests/unittests/pdcp/pdcp_rx_metrics_test.cpp | 6 +- .../pdcp/pdcp_rx_reestablish_test.cpp | 14 +- .../pdcp/pdcp_rx_status_report_test.cpp | 10 +- tests/unittests/pdcp/pdcp_rx_test.cpp | 26 +- tests/unittests/pdcp/pdcp_test_vectors.h | 186 +++++------ .../pdcp/pdcp_tx_empty_pool_test.cpp | 8 +- tests/unittests/pdcp/pdcp_tx_metrics_test.cpp | 2 +- .../pdcp/pdcp_tx_reestablish_test.cpp | 6 +- .../pdcp/pdcp_tx_status_report_test.cpp | 6 +- tests/unittests/pdcp/pdcp_tx_test.cpp | 36 +- tests/unittests/psup/psup_packing_test.cpp | 16 +- tests/unittests/rlc/rlc_pdu_recycler_test.cpp | 16 +- tests/unittests/rlc/rlc_rx_am_test.cpp | 46 +-- tests/unittests/rlc/rlc_rx_tm_test.cpp | 4 +- .../rlc/rlc_sdu_queue_lockfree_test.cpp | 4 +- tests/unittests/rlc/rlc_sdu_queue_test.cpp | 4 +- tests/unittests/rlc/rlc_tx_am_test.cpp | 311 ++++++++++++++---- tests/unittests/rlc/rlc_tx_tm_test.cpp | 35 +- tests/unittests/rlc/rlc_um_test.cpp | 177 +++++++--- .../rrc/rrc_ue_dl_info_transfer_proc_test.cpp | 4 +- tests/unittests/rrc/rrc_ue_test_helpers.h | 37 ++- tests/unittests/sdap/sdap_rx_test.cpp | 4 +- tests/unittests/sdap/sdap_test.cpp | 32 +- tests/unittests/sdap/sdap_tx_test.cpp | 4 +- tests/unittests/security/security_test.cpp | 53 +-- tests/unittests/support/bit_encoding_test.cpp | 22 +- 99 files changed, 1431 insertions(+), 992 deletions(-) diff --git a/apps/examples/du/du_example.cpp b/apps/examples/du/du_example.cpp index 9b095841e3..fd9747a1ea 100644 --- a/apps/examples/du/du_example.cpp +++ b/apps/examples/du/du_example.cpp @@ -229,7 +229,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/include/srsran/adt/byte_buffer.h b/include/srsran/adt/byte_buffer.h index 8ab60e2c96..a172e1a129 100644 --- a/include/srsran/adt/byte_buffer.h +++ b/include/srsran/adt/byte_buffer.h @@ -189,13 +189,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) { @@ -206,22 +199,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) @@ -239,33 +222,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; @@ -483,7 +456,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); @@ -493,7 +466,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 d2a4900d74..924df374dd 100644 --- a/include/srsran/adt/byte_buffer_chain.h +++ b/include/srsran/adt/byte_buffer_chain.h @@ -121,6 +121,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&; @@ -132,8 +139,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() { @@ -145,8 +151,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)) @@ -155,43 +161,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) { @@ -218,14 +213,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; @@ -376,14 +369,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/f1u/common/nru_message.h b/include/srsran/f1u/common/nru_message.h index c7d19538d0..e9a2916395 100644 --- a/include/srsran/f1u/common/nru_message.h +++ b/include/srsran/f1u/common/nru_message.h @@ -34,7 +34,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). /// @@ -48,7 +48,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). /// @@ -133,7 +133,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/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp b/lib/cu_cp/routines/mobility/inter_cu_handover_target_routine.cpp index b9be08ab22..6ce5c1cd9d 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 @@ -82,7 +82,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, @@ -248,16 +251,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; @@ -274,6 +288,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 36e524c171..e132b86678 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 @@ -33,7 +33,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 42a2f2fb25..822e6b2661 100644 --- a/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp +++ b/lib/cu_cp/routines/pdu_session_resource_setup_routine.cpp @@ -106,7 +106,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, @@ -398,7 +401,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; @@ -406,9 +409,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; @@ -425,6 +438,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 f3fa1ed95a..26205e7f33 100644 --- a/lib/cu_cp/routines/pdu_session_resource_setup_routine.h +++ b/lib/cu_cp/routines/pdu_session_resource_setup_routine.h @@ -52,7 +52,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/du_high/adapters/mac_test_mode_adapter.cpp b/lib/du_high/adapters/mac_test_mode_adapter.cpp index 49e934ff20..ef2cfe1e16 100644 --- a/lib/du_high/adapters/mac_test_mode_adapter.cpp +++ b/lib/du_high/adapters/mac_test_mode_adapter.cpp @@ -15,6 +15,7 @@ #include "srsran/ran/csi_report/csi_report_on_pucch_helpers.h" #include "srsran/scheduler/harq_id.h" #include +#include using namespace srsran; @@ -22,7 +23,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. @@ -34,9 +35,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. @@ -76,7 +80,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_) { @@ -265,7 +269,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; } @@ -276,7 +280,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; } @@ -303,7 +307,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 @@ -315,8 +319,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); } @@ -343,8 +352,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 e33b79dc19..526f6852cb 100644 --- a/lib/du_high/du_high_impl.cpp +++ b/lib/du_high/du_high_impl.cpp @@ -165,14 +165,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/e2/common/e2_subscription_manager_impl.cpp b/lib/e2/common/e2_subscription_manager_impl.cpp index 6490c50a0a..cd6a6cf503 100644 --- a/lib/e2/common/e2_subscription_manager_impl.cpp +++ b/lib/e2/common/e2_subscription_manager_impl.cpp @@ -122,9 +122,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 2fcaece0c3..98844b6dec 100644 --- a/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp +++ b/lib/e2/e2sm/e2sm_kpm/e2sm_kpm_asn1_packer.cpp @@ -75,9 +75,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; @@ -95,9 +95,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); } @@ -110,9 +110,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); } @@ -125,9 +125,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); } @@ -140,9 +140,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); } @@ -155,9 +155,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); } @@ -171,6 +171,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/f1u/cu_up/f1u_bearer_impl.cpp b/lib/f1u/cu_up/f1u_bearer_impl.cpp index 7f52d4a650..16d5145314 100644 --- a/lib/f1u/cu_up/f1u_bearer_impl.cpp +++ b/lib/f1u/cu_up/f1u_bearer_impl.cpp @@ -50,12 +50,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_adaptor/mac/fapi_to_mac_data_msg_translator.cpp b/lib/fapi_adaptor/mac/fapi_to_mac_data_msg_translator.cpp index 32531dd960..71f876e93e 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 @@ -92,16 +92,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/gateways/sctp_network_gateway_impl.cpp b/lib/gateways/sctp_network_gateway_impl.cpp index 66b4791a4e..221edc4018 100644 --- a/lib/gateways/sctp_network_gateway_impl.cpp +++ b/lib/gateways/sctp_network_gateway_impl.cpp @@ -561,7 +561,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 a68665b915..b997cd63fc 100644 --- a/lib/gtpu/gtpu_demux_impl.cpp +++ b/lib/gtpu/gtpu_demux_impl.cpp @@ -81,7 +81,12 @@ void gtpu_demux_impl::handle_pdu_impl(gtpu_teid_t teid 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); diff --git a/lib/gtpu/gtpu_tunnel_base_tx.h b/lib/gtpu/gtpu_tunnel_base_tx.h index 3b85163dd3..bbb052d585 100644 --- a/lib/gtpu/gtpu_tunnel_base_tx.h +++ b/lib/gtpu/gtpu_tunnel_base_tx.h @@ -52,7 +52,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/pcap/backend_pcap_writer.h b/lib/pcap/backend_pcap_writer.h index 844f82ed92..f5b8e98a1b 100644 --- a/lib/pcap/backend_pcap_writer.h +++ b/lib/pcap/backend_pcap_writer.h @@ -22,10 +22,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))) { @@ -81,4 +86,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 672e71b1d5..1f0c35b1fd 100644 --- a/lib/pcap/dlt_pcap_impl.cpp +++ b/lib/pcap/dlt_pcap_impl.cpp @@ -14,12 +14,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_, @@ -45,7 +45,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 fa039743fd..f46cf31bc2 100644 --- a/lib/pcap/mac_pcap_impl.cpp +++ b/lib/pcap/mac_pcap_impl.cpp @@ -13,10 +13,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_), @@ -37,7 +37,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) @@ -47,33 +51,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; @@ -83,13 +88,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 */ @@ -105,7 +110,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 48b540a742..c716f00e86 100644 --- a/lib/pdcp/pdcp_entity_rx.cpp +++ b/lib/pdcp/pdcp_entity_rx.cpp @@ -61,12 +61,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 6f4f7fd988..cfb059a6b7 100644 --- a/lib/pdcp/pdcp_entity_tx.cpp +++ b/lib/pdcp/pdcp_entity_tx.cpp @@ -72,7 +72,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 @@ -211,7 +217,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 @@ -408,7 +420,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/rrc/ue/rrc_ue_srb_context.h b/lib/rrc/ue/rrc_ue_srb_context.h index bbbcc76b27..af8a35bf14 100644 --- a/lib/rrc/ue/rrc_ue_srb_context.h +++ b/lib/rrc/ue/rrc_ue_srb_context.h @@ -122,7 +122,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/support/byte_buffer_chain.cpp b/lib/support/byte_buffer_chain.cpp index c976451262..7213d5df77 100644 --- a/lib/support/byte_buffer_chain.cpp +++ b/lib/support/byte_buffer_chain.cpp @@ -14,19 +14,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/tests/benchmarks/du_high/du_high_benchmark.cpp b/tests/benchmarks/du_high/du_high_benchmark.cpp index 07e254effd..b17fdf7ded 100644 --- a/tests/benchmarks/du_high/du_high_benchmark.cpp +++ b/tests/benchmarks/du_high/du_high_benchmark.cpp @@ -687,8 +687,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. @@ -728,19 +731,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]}); } } })) { @@ -990,7 +993,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 7cdb5e91f0..68a0e822f5 100644 --- a/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp +++ b/tests/benchmarks/pdcp/pdcp_rx_benchmark.cpp @@ -16,11 +16,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 { @@ -30,12 +32,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; }; @@ -68,6 +66,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/rlc/rlc_am_rx_benchmark.cpp b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp index 9da95a4b49..f4c1cc0f58 100644 --- a/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp +++ b/tests/benchmarks/rlc/rlc_am_rx_benchmark.cpp @@ -170,8 +170,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); @@ -182,7 +184,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 4efb4d8f12..b6a276130f 100644 --- a/tests/benchmarks/rlc/rlc_handle_status_report.cpp +++ b/tests/benchmarks/rlc/rlc_handle_status_report.cpp @@ -125,12 +125,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/integrationtests/rlc/rlc_stress_test_f1.h b/tests/integrationtests/rlc/rlc_stress_test_f1.h index e5d172daf1..e3ed2590c1 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_f1.h +++ b/tests/integrationtests/rlc/rlc_stress_test_f1.h @@ -71,7 +71,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 84611ecc0e..ad0ca2e7cf 100644 --- a/tests/integrationtests/rlc/rlc_stress_test_mac.cpp +++ b/tests/integrationtests/rlc/rlc_stress_test_mac.cpp @@ -34,7 +34,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"); } @@ -75,7 +75,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/mac/mac_test_messages.cpp b/tests/test_doubles/mac/mac_test_messages.cpp index 784f0187bb..9fa0aa93fa 100644 --- a/tests/test_doubles/mac/mac_test_messages.cpp +++ b/tests/test_doubles/mac/mac_test_messages.cpp @@ -18,7 +18,10 @@ 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) @@ -26,9 +29,14 @@ mac_rx_data_indication srsran::test_helpers::create_pdu_with_sdu(slot_point sl_r return mac_rx_data_indication{ sl_rx, to_du_cell_index(0), - {mac_rx_pdu{rnti, 0, 0, {(uint8_t)lcid, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05, 0xdf, 0x80, 0x10, 0x5e, + {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}}}}; + 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) diff --git a/tests/unittests/adt/byte_buffer_chain_test.cpp b/tests/unittests/adt/byte_buffer_chain_test.cpp index 07f58283a5..63b21535d1 100644 --- a/tests/unittests/adt/byte_buffer_chain_test.cpp +++ b/tests/unittests/adt/byte_buffer_chain_test.cpp @@ -39,7 +39,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); @@ -64,12 +66,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())); @@ -95,21 +99,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); @@ -131,7 +137,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; @@ -139,8 +145,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); @@ -148,12 +154,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()); @@ -180,13 +188,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()); @@ -203,12 +213,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 0326fb1406..7772b9450a 100644 --- a/tests/unittests/adt/byte_buffer_test.cpp +++ b/tests/unittests/adt/byte_buffer_test.cpp @@ -172,7 +172,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); @@ -181,7 +181,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())); @@ -189,8 +189,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. @@ -205,7 +205,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); @@ -216,7 +216,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); @@ -247,7 +247,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); @@ -264,7 +264,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()); @@ -356,7 +356,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()); } @@ -369,7 +369,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); @@ -482,7 +482,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)); @@ -497,7 +497,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()); @@ -517,7 +517,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); @@ -758,7 +758,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()); @@ -809,15 +809,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 { @@ -860,28 +861,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, @@ -938,7 +939,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()); @@ -968,8 +969,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[]. @@ -989,7 +990,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()}; @@ -1017,9 +1018,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) { @@ -1054,7 +1055,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 fcddc7e8d7..8f18de3d33 100644 --- a/tests/unittests/asn1/asn1_e1ap_test.cpp +++ b/tests/unittests/asn1/asn1_e1ap_test.cpp @@ -104,7 +104,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); @@ -165,7 +165,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 04c9255534..36257dcabb 100644 --- a/tests/unittests/asn1/asn1_f1ap_test.cpp +++ b/tests/unittests/asn1/asn1_f1ap_test.cpp @@ -228,7 +228,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); @@ -267,7 +267,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); @@ -307,7 +307,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 e8055ebf0a..7bcb01985d 100644 --- a/tests/unittests/asn1/asn1_ngap_test.cpp +++ b/tests/unittests/asn1/asn1_ngap_test.cpp @@ -175,7 +175,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; @@ -224,7 +224,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; @@ -258,7 +258,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; @@ -297,7 +297,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); @@ -329,7 +329,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); @@ -358,7 +358,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); @@ -382,7 +382,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); @@ -403,7 +403,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); @@ -430,7 +430,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 b87e5a8db2..b2cb4dea28 100644 --- a/tests/unittests/asn1/asn1_rrc_nr_test.cpp +++ b/tests/unittests/asn1/asn1_rrc_nr_test.cpp @@ -148,9 +148,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}; @@ -187,7 +189,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; @@ -223,7 +225,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; @@ -267,7 +269,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; @@ -324,20 +326,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}; @@ -357,84 +362,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 765ee048c6..79e50e413b 100644 --- a/tests/unittests/asn1/asn1_utils_test.cpp +++ b/tests/unittests/asn1/asn1_utils_test.cpp @@ -185,7 +185,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 d228d82bd8..8808410b6f 100644 --- a/tests/unittests/cu_cp/du_processor_test_messages.cpp +++ b/tests/unittests/cu_cp/du_processor_test_messages.cpp @@ -88,7 +88,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 6336740b6b..58425b30b3 100644 --- a/tests/unittests/cu_up/cu_up_test.cpp +++ b/tests/unittests/cu_up/cu_up_test.cpp @@ -278,9 +278,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 @@ -291,9 +291,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 8bb1641da1..e3c08b31a9 100644 --- a/tests/unittests/cu_up/cu_up_test_helpers.h +++ b/tests/unittests/cu_up/cu_up_test_helpers.h @@ -146,7 +146,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 2e5a60e99c..c861757438 100644 --- a/tests/unittests/du_manager/du_manager_test_helpers.h +++ b/tests/unittests/du_manager/du_manager_test_helpers.h @@ -66,7 +66,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); } @@ -180,7 +180,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/ue_manager_test.cpp b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp index 7008e6328a..ee4c185bf6 100644 --- a/tests/unittests/du_manager/du_ue/ue_manager_test.cpp +++ b/tests/unittests/du_manager/du_ue/ue_manager_test.cpp @@ -42,7 +42,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 cbf813f318..677b3eb73b 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 @@ -23,7 +23,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 c9e9aec000..98d5093551 100644 --- a/tests/unittests/du_manager/procedures/ue_configuration_test.cpp +++ b/tests/unittests/du_manager/procedures/ue_configuration_test.cpp @@ -188,14 +188,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. @@ -211,7 +212,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); } @@ -219,7 +221,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})); @@ -227,7 +230,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. @@ -245,7 +248,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 20ab236421..fef97024b5 100644 --- a/tests/unittests/e2/e2_setup_procedure_test.cpp +++ b/tests/unittests/e2/e2_setup_procedure_test.cpp @@ -231,10 +231,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 5476afda51..30379ae0aa 100644 --- a/tests/unittests/e2/e2_subscription_setup_test.cpp +++ b/tests/unittests/e2/e2_subscription_setup_test.cpp @@ -29,7 +29,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); @@ -48,7 +48,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 = {}; @@ -82,7 +82,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); @@ -118,7 +118,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); @@ -130,9 +130,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)); @@ -144,4 +144,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 d616fb4b68..e95637bee8 100644 --- a/tests/unittests/f1ap/common/f1ap_cu_test_messages.h +++ b/tests/unittests/f1ap/common/f1ap_cu_test_messages.h @@ -39,8 +39,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 01efdf15b9..95a7c2f9b7 100644 --- a/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp +++ b/tests/unittests/f1ap/common/f1ap_du_test_messages.cpp @@ -65,7 +65,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 f7cbd1c8c2..196392afc8 100644 --- a/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp +++ b/tests/unittests/f1ap/cu_cp/f1ap_cu_test_helpers.cpp @@ -43,7 +43,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 3d643ae96a..e103116f07 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 @@ -23,7 +23,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()); @@ -38,12 +38,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 4f2f09d879..42e3ee94d6 100644 --- a/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_test_helpers.cpp @@ -165,7 +165,7 @@ 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; } @@ -313,8 +313,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_ue_config_test.cpp b/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp index fedd66d14f..0b02b193bf 100644 --- a/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp +++ b/tests/unittests/f1ap/du/f1ap_du_ue_config_test.cpp @@ -59,14 +59,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); @@ -84,7 +86,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 0442fecd4e..d30df8270a 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 @@ -39,7 +39,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); @@ -107,7 +108,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 fb63e7675f..f5020b72f1 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 @@ -64,7 +64,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) { @@ -148,8 +148,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); @@ -222,7 +223,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 fc126c62aa..6c5de35b67 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 @@ -27,8 +27,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 cad562e97e..8dd3728ff9 100644 --- a/tests/unittests/f1u/common/f1u_connector_test.cpp +++ b/tests/unittests/f1u/common/f1u_connector_test.cpp @@ -15,6 +15,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 @@ -22,8 +24,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 { @@ -100,6 +102,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) { @@ -132,17 +136,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); @@ -152,9 +160,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 } @@ -183,17 +193,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); @@ -236,17 +250,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); @@ -268,17 +286,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 13a9a9299c..e3869f251d 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 @@ -169,7 +169,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 @@ -229,13 +229,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)); @@ -274,7 +274,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 @@ -283,7 +285,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 5c29dcbe52..820d293aa4 100644 --- a/tests/unittests/f1u/du/f1u_du_bearer_test.cpp +++ b/tests/unittests/f1u/du/f1u_du_bearer_test.cpp @@ -17,6 +17,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 { @@ -103,6 +105,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()); @@ -119,11 +123,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 = {}; @@ -131,7 +135,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()); @@ -166,13 +170,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)); @@ -200,23 +204,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()); @@ -235,16 +243,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(); @@ -262,7 +274,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()); @@ -288,16 +300,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(); @@ -315,7 +331,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()); @@ -335,7 +351,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()); { @@ -370,7 +386,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()); { @@ -405,7 +421,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/gtpu/gtpu_demux_test.cpp b/tests/unittests/gtpu/gtpu_demux_test.cpp index a289a191d5..e1d5207b23 100644 --- a/tests/unittests/gtpu/gtpu_demux_test.cpp +++ b/tests/unittests/gtpu/gtpu_demux_test.cpp @@ -64,7 +64,7 @@ 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(); @@ -75,7 +75,7 @@ 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); @@ -87,7 +87,7 @@ 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}); @@ -100,7 +100,7 @@ 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); diff --git a/tests/unittests/gtpu/gtpu_echo_test.cpp b/tests/unittests/gtpu/gtpu_echo_test.cpp index 67e79eef99..63812cd087 100644 --- a/tests/unittests/gtpu/gtpu_echo_test.cpp +++ b/tests/unittests/gtpu/gtpu_echo_test.cpp @@ -124,13 +124,13 @@ 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); }; @@ -145,7 +145,7 @@ TEST_F(gtpu_echo_test, rx_error_indication) echo = create_gtpu_echo(msg); sockaddr_storage orig_addr = {}; - byte_buffer error_indication = {gtpu_error_indication}; + 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); diff --git a/tests/unittests/gtpu/gtpu_test.cpp b/tests/unittests/gtpu/gtpu_test.cpp index 29dce17826..4f1bca3488 100644 --- a/tests/unittests/gtpu/gtpu_test.cpp +++ b/tests/unittests/gtpu/gtpu_test.cpp @@ -56,9 +56,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"); @@ -74,14 +74,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 @@ -108,7 +108,7 @@ TEST_F(gtpu_test, pack_unpack) 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"); @@ -121,15 +121,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 @@ -169,13 +170,15 @@ 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; @@ -184,7 +187,7 @@ TEST_F(gtpu_test, pack_unpack_ext_hdr) 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_tunnel_ngu_rx_test.cpp b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp index 714d36c1f7..5783475c59 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_rx_test.cpp @@ -212,7 +212,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); @@ -237,7 +237,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); @@ -262,7 +262,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); @@ -275,7 +275,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); @@ -287,7 +287,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); @@ -298,7 +298,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); @@ -310,7 +310,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); @@ -338,7 +338,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); @@ -351,7 +351,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); @@ -363,7 +363,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); @@ -374,7 +374,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); @@ -386,7 +386,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); @@ -412,7 +412,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); @@ -425,7 +425,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); @@ -436,7 +436,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); @@ -457,7 +457,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); @@ -484,7 +484,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); @@ -497,7 +497,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); @@ -508,7 +508,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); @@ -519,7 +519,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); @@ -536,7 +536,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 e9ef2de96d..d56d0fc00f 100644 --- a/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp +++ b/tests/unittests/gtpu/gtpu_tunnel_ngu_test.cpp @@ -143,7 +143,7 @@ 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(); @@ -167,8 +167,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 cf347cf97c..a7902e3ab2 100644 --- a/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp +++ b/tests/unittests/mac/dl_sch_pdu_assembler_test.cpp @@ -46,7 +46,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); } @@ -70,7 +70,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; @@ -103,7 +103,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; @@ -132,7 +132,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 fb744197ba..3cbc76b2d4 100644 --- a/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp +++ b/tests/unittests/mac/mac_rar_pdu_assembler_test.cpp @@ -76,7 +76,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 12d9c25e4c..8841948036 100644 --- a/tests/unittests/mac/mac_test_helpers.h +++ b/tests/unittests/mac/mac_test_helpers.h @@ -151,7 +151,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 ebe1f8761e..eb74583c10 100644 --- a/tests/unittests/mac/mac_ul_pdu_test.cpp +++ b/tests/unittests/mac/mac_ul_pdu_test.cpp @@ -34,7 +34,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 @@ -62,7 +62,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. @@ -87,7 +87,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. @@ -117,7 +117,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. @@ -152,7 +152,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. @@ -194,7 +194,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. @@ -237,7 +237,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. @@ -275,7 +275,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. @@ -312,7 +312,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. @@ -343,7 +343,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. @@ -380,7 +380,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. @@ -402,7 +402,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 @@ -436,7 +436,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. @@ -465,9 +465,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); @@ -502,9 +502,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); @@ -529,7 +529,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); } @@ -538,9 +538,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); @@ -560,9 +560,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 d8d2decb1d..4fd3ac15cc 100644 --- a/tests/unittests/mac/mac_ul_processor_test.cpp +++ b/tests/unittests/mac/mac_ul_processor_test.cpp @@ -234,7 +234,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); @@ -262,7 +262,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); @@ -291,7 +291,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); @@ -320,7 +320,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); @@ -349,7 +349,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); @@ -377,7 +377,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); @@ -406,7 +406,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); @@ -433,11 +433,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))); @@ -471,12 +471,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 @@ -509,7 +509,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); @@ -541,11 +541,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))); @@ -564,7 +564,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 3c666251eb..050b66dd09 100644 --- a/tests/unittests/ngap/ngap_asn1_packer_test.cpp +++ b/tests/unittests/ngap/ngap_asn1_packer_test.cpp @@ -74,7 +74,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 05d2207fac..af3f094281 100644 --- a/tests/unittests/pcap/mac_pcap_test.cpp +++ b/tests/unittests/pcap/mac_pcap_test.cpp @@ -224,8 +224,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; @@ -250,7 +252,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" @@ -1677,9 +1678,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 1d6abd5a5a..68bbf71229 100644 --- a/tests/unittests/pcap/ngap_pcap_test.cpp +++ b/tests/unittests/pcap/ngap_pcap_test.cpp @@ -114,10 +114,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 35da64fd9b..4d08b8b268 100644 --- a/tests/unittests/pdcp/pdcp_gen_helper.cpp +++ b/tests/unittests/pdcp/pdcp_gen_helper.cpp @@ -146,7 +146,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 a216fe4956..2b13c0e1a6 100644 --- a/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_metrics_test.cpp @@ -38,7 +38,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); @@ -88,7 +88,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); @@ -134,7 +134,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 5fcb06c5d2..cc2616a7d7 100644 --- a/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_reestablish_test.cpp @@ -41,9 +41,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. @@ -88,9 +88,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. @@ -135,9 +135,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. @@ -161,7 +161,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 829142bf1e..76a2f7da58 100644 --- a/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_status_report_test.cpp @@ -49,7 +49,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(); @@ -71,7 +71,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(); @@ -119,11 +119,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(); @@ -173,7 +173,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 d18a47701a..37f138903f 100644 --- a/tests/unittests/pdcp/pdcp_rx_test.cpp +++ b/tests/unittests/pdcp/pdcp_rx_test.cpp @@ -74,9 +74,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); @@ -119,19 +119,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); @@ -171,11 +171,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); @@ -214,9 +214,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); @@ -256,10 +256,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); @@ -296,7 +296,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); @@ -337,7 +337,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 583e8071b3..e24414e269 100644 --- a/tests/unittests/pdcp/pdcp_test_vectors.h +++ b/tests/unittests/pdcp/pdcp_test_vectors.h @@ -246,52 +246,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; @@ -299,49 +299,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; @@ -362,52 +362,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; @@ -415,49 +415,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; @@ -478,52 +478,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; @@ -531,49 +531,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 8af93d73d6..9e69161ecd 100644 --- a/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_empty_pool_test.cpp @@ -56,8 +56,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 1e8380aa8d..6194e1632b 100644 --- a/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_metrics_test.cpp @@ -34,7 +34,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 2e28171fed..0f19c1032e 100644 --- a/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_reestablish_test.cpp @@ -32,7 +32,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)); } @@ -57,7 +57,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()); @@ -81,7 +81,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 9e1c2ac15f..eb5ca8680c 100644 --- a/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_status_report_test.cpp @@ -35,7 +35,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)); @@ -69,7 +69,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 { @@ -129,7 +129,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 c4c8556d65..a4a488c45c 100644 --- a/tests/unittests/pdcp/pdcp_tx_test.cpp +++ b/tests/unittests/pdcp/pdcp_tx_test.cpp @@ -73,7 +73,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 @@ -123,7 +123,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 @@ -133,7 +133,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 @@ -144,7 +144,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 @@ -181,14 +181,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()); @@ -230,7 +230,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()); @@ -312,7 +312,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 @@ -322,7 +322,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 @@ -337,7 +337,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 @@ -347,7 +347,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 @@ -358,7 +358,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 @@ -403,7 +403,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)); } @@ -426,27 +426,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/psup/psup_packing_test.cpp b/tests/unittests/psup/psup_packing_test.cpp index 79a5b3c5b4..30a984baba 100644 --- a/tests/unittests/psup/psup_packing_test.cpp +++ b/tests/unittests/psup/psup_packing_test.cpp @@ -60,7 +60,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) @@ -71,7 +71,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{}; @@ -105,7 +105,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) @@ -127,7 +127,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{}; @@ -149,7 +149,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); @@ -158,7 +158,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); @@ -167,7 +167,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); @@ -176,7 +176,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/rlc/rlc_pdu_recycler_test.cpp b/tests/unittests/rlc/rlc_pdu_recycler_test.cpp index 4712cc2175..117f45d188 100644 --- a/tests/unittests/rlc/rlc_pdu_recycler_test.cpp +++ b/tests/unittests/rlc/rlc_pdu_recycler_test.cpp @@ -63,7 +63,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); @@ -92,7 +92,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); @@ -108,7 +108,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); @@ -128,7 +128,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); @@ -155,7 +155,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); @@ -169,11 +169,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 d300a6ba3b..da887e57aa 100644 --- a/tests/unittests/rlc/rlc_rx_am_test.cpp +++ b/tests/unittests/rlc/rlc_rx_am_test.cpp @@ -228,7 +228,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) { @@ -311,7 +311,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)); } @@ -374,7 +374,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++; @@ -386,7 +386,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); @@ -482,7 +482,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 @@ -509,7 +509,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 @@ -592,7 +592,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 @@ -625,7 +625,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 @@ -652,7 +652,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 @@ -669,7 +669,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 @@ -709,7 +709,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++; @@ -721,7 +721,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 @@ -848,7 +848,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 @@ -911,7 +911,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++; @@ -980,7 +980,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++; @@ -1030,7 +1030,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++; @@ -1075,7 +1075,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++; @@ -1124,7 +1124,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)); @@ -1143,7 +1143,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())); @@ -1198,7 +1198,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 @@ -1300,7 +1300,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)); } @@ -1314,7 +1314,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)); } @@ -1328,7 +1328,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 c85ed75078..3771225215 100644 --- a/tests/unittests/rlc/rlc_rx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_rx_tm_test.cpp @@ -79,14 +79,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 e68bb110c0..9f02f87df9 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_lockfree_test.cpp @@ -23,7 +23,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))); @@ -40,7 +40,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 7acca39ea3..cc21bcb3a0 100644 --- a/tests/unittests/rlc/rlc_sdu_queue_test.cpp +++ b/tests/unittests/rlc/rlc_sdu_queue_test.cpp @@ -21,7 +21,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))); @@ -38,7 +38,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 9453e4df10..ad0a2496fd 100644 --- a/tests/unittests/rlc/rlc_tx_am_test.cpp +++ b/tests/unittests/rlc/rlc_tx_am_test.cpp @@ -146,7 +146,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)); } @@ -165,7 +165,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); @@ -213,7 +213,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)); } @@ -233,7 +233,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); @@ -316,8 +316,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); @@ -335,7 +339,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); @@ -445,7 +463,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)); } @@ -559,7 +577,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)); } @@ -660,9 +678,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); @@ -686,7 +708,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; @@ -709,7 +735,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]); @@ -737,7 +763,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; @@ -758,13 +788,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( @@ -772,7 +801,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 @@ -806,7 +836,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; @@ -833,7 +867,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( @@ -864,7 +898,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; @@ -891,7 +931,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, @@ -923,7 +963,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; @@ -950,7 +996,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, @@ -982,11 +1028,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); @@ -1036,11 +1095,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); @@ -1100,11 +1174,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); @@ -1149,7 +1238,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; @@ -1176,7 +1271,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( @@ -1205,7 +1300,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; @@ -1232,7 +1333,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( @@ -1256,9 +1357,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); @@ -1308,9 +1422,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); @@ -1389,7 +1516,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); @@ -1436,7 +1567,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; @@ -1474,7 +1609,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 @@ -1500,7 +1635,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; @@ -1538,7 +1677,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()); @@ -1700,8 +1839,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; @@ -1733,7 +1876,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); @@ -1748,7 +1892,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); @@ -1763,7 +1908,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); @@ -1772,8 +1918,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; @@ -1784,7 +1936,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); @@ -1800,7 +1952,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); } @@ -1827,7 +1980,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); } @@ -1840,7 +1994,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); } @@ -1853,15 +2008,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; @@ -1898,7 +2058,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); @@ -1914,7 +2075,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; @@ -1951,7 +2116,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 fdcd13124e..c7a3b037ba 100644 --- a/tests/unittests/rlc/rlc_tx_tm_test.cpp +++ b/tests/unittests/rlc/rlc_tx_tm_test.cpp @@ -104,7 +104,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)); @@ -113,12 +114,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(); @@ -129,7 +129,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); @@ -139,7 +139,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); @@ -149,7 +149,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); @@ -159,7 +159,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)); @@ -171,7 +171,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(); @@ -182,7 +182,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(); @@ -199,7 +199,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)); @@ -216,12 +217,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(); @@ -238,7 +238,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)); @@ -248,10 +249,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 48447b62eb..ba7227361f 100644 --- a/tests/unittests/rlc/rlc_um_test.cpp +++ b/tests/unittests/rlc/rlc_um_test.cpp @@ -161,23 +161,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; @@ -330,7 +340,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(); @@ -339,12 +349,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 @@ -399,7 +414,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(); @@ -408,15 +423,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 @@ -478,7 +503,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)); } @@ -520,7 +545,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; @@ -542,7 +568,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; @@ -582,7 +608,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)); } @@ -625,7 +651,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; @@ -646,7 +673,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; @@ -683,7 +710,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(); @@ -692,15 +719,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 @@ -763,7 +800,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(); @@ -772,15 +809,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; @@ -889,7 +935,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; } @@ -952,7 +999,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; } @@ -1015,7 +1063,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(); @@ -1024,15 +1072,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; @@ -1094,7 +1151,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(); @@ -1103,15 +1160,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 24e67d8fe8..33afd29382 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 @@ -53,7 +53,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); } @@ -61,6 +61,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 510c5f946a..2590f05059 100644 --- a/tests/unittests/rrc/rrc_ue_test_helpers.h +++ b/tests/unittests/rrc/rrc_ue_test_helpers.h @@ -119,8 +119,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; @@ -145,7 +146,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() @@ -154,7 +156,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() @@ -197,13 +200,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) @@ -228,19 +232,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) @@ -284,23 +291,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)); @@ -311,7 +319,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/sdap/sdap_rx_test.cpp b/tests/unittests/sdap/sdap_rx_test.cpp index 3fd514258b..9e8437d0ef 100644 --- a/tests/unittests/sdap/sdap_rx_test.cpp +++ b/tests/unittests/sdap/sdap_rx_test.cpp @@ -70,9 +70,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 2d57ec1967..42651ebed2 100644 --- a/tests/unittests/sdap/sdap_test.cpp +++ b/tests/unittests/sdap/sdap_test.cpp @@ -23,9 +23,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()); @@ -36,14 +36,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()); @@ -53,14 +53,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()); @@ -73,13 +73,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 = {}; @@ -87,8 +87,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); @@ -102,8 +102,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()); @@ -143,14 +143,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 d5c55456a9..9c41722082 100644 --- a/tests/unittests/sdap/sdap_tx_test.cpp +++ b/tests/unittests/sdap/sdap_tx_test.cpp @@ -70,9 +70,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 0e814f416b..476db1ba7f 100644 --- a/tests/unittests/security/security_test.cpp +++ b/tests/unittests/security/security_test.cpp @@ -265,7 +265,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 @@ -291,7 +291,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 @@ -318,7 +318,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 @@ -346,7 +346,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 @@ -373,7 +373,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 @@ -405,7 +405,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 @@ -468,7 +468,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 @@ -679,7 +679,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 @@ -708,7 +708,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 } { @@ -716,7 +716,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); } } @@ -746,7 +746,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 @@ -776,7 +776,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 @@ -807,7 +807,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 } { @@ -815,7 +815,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); } } @@ -846,7 +846,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 @@ -881,7 +881,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 @@ -947,7 +947,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 } { @@ -955,7 +955,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); } } @@ -1163,7 +1163,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 @@ -1191,7 +1191,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 @@ -1220,7 +1220,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 @@ -1253,7 +1253,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 @@ -1294,7 +1294,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 @@ -1463,9 +1463,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/support/bit_encoding_test.cpp b/tests/unittests/support/bit_encoding_test.cpp index 84616ddbc5..cc76e70831 100644 --- a/tests/unittests/support/bit_encoding_test.cpp +++ b/tests/unittests/support/bit_encoding_test.cpp @@ -62,12 +62,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. @@ -124,7 +124,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() @@ -134,7 +134,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); @@ -148,7 +148,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()); @@ -167,7 +167,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()); @@ -220,7 +220,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; @@ -298,7 +298,7 @@ void test_bit_decoder() void test_bit_decoder_bytes() { - byte_buffer bytes = {0b1, 0b10, 0b11, 0b100}; + byte_buffer bytes = byte_buffer::create({0b1, 0b10, 0b11, 0b100}).value(); bit_decoder dec(bytes); std::vector vec; @@ -337,7 +337,7 @@ void test_bit_decoder_bytes() 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; @@ -352,7 +352,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; @@ -369,7 +369,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; From 1ebd65cf0513ecbc06db5057011089c23764b0c2 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 13 Mar 2024 17:57:19 +0000 Subject: [PATCH 44/77] gtpu: make sure that enqueued tasks don't access deleted tunnels --- lib/gtpu/gtpu_demux_impl.cpp | 24 +++++++++++++++++------- lib/gtpu/gtpu_demux_impl.h | 5 +---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/gtpu/gtpu_demux_impl.cpp b/lib/gtpu/gtpu_demux_impl.cpp index b997cd63fc..fbc6c24644 100644 --- a/lib/gtpu/gtpu_demux_impl.cpp +++ b/lib/gtpu/gtpu_demux_impl.cpp @@ -62,9 +62,7 @@ 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 cfg.warn_on_drop) { @@ -75,10 +73,7 @@ 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()) { auto pdu_copy = pdu.deep_copy(); @@ -91,6 +86,21 @@ void gtpu_demux_impl::handle_pdu_impl(gtpu_teid_t teid 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 5c21103417..077b44f5e6 100644 --- a/lib/gtpu/gtpu_demux_impl.h +++ b/lib/gtpu/gtpu_demux_impl.h @@ -40,10 +40,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; From 76ba095d2c41c1f46616f7c03d0c22544b3df136 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 14 Mar 2024 12:21:20 +0000 Subject: [PATCH 45/77] gtpu: fix deadlock on gtpu_demux test This was being caused by calling execute instead of defere, when the executor was the same. Also removed unused executor. --- lib/gtpu/gtpu_demux_impl.cpp | 2 +- tests/unittests/gtpu/gtpu_demux_test.cpp | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/gtpu/gtpu_demux_impl.cpp b/lib/gtpu/gtpu_demux_impl.cpp index fbc6c24644..c1b14f67c6 100644 --- a/lib/gtpu/gtpu_demux_impl.cpp +++ b/lib/gtpu/gtpu_demux_impl.cpp @@ -64,7 +64,7 @@ void gtpu_demux_impl::handle_pdu(byte_buffer pdu, const sockaddr_storage& src_ad 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 { diff --git a/tests/unittests/gtpu/gtpu_demux_test.cpp b/tests/unittests/gtpu/gtpu_demux_test.cpp index e1d5207b23..bf7496a805 100644 --- a/tests/unittests/gtpu/gtpu_demux_test.cpp +++ b/tests/unittests/gtpu/gtpu_demux_test.cpp @@ -51,10 +51,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); @@ -67,7 +64,7 @@ TEST_F(gtpu_demux_test, when_tunnel_not_registered_pdu_is_dropped) 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); } @@ -79,7 +76,7 @@ TEST_F(gtpu_demux_test, when_tunnel_registered_pdu_is_forwarded) 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)); } @@ -92,7 +89,7 @@ TEST_F(gtpu_demux_test, when_tunnel_is_removed_pdu_is_dropped) 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); } @@ -104,7 +101,13 @@ TEST_F(gtpu_demux_test, when_different_tunnel_registered_pdu_is_dropped) 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(); +} From 15b6afdd0837023f37e2bea355dc0ba8b0c2c151 Mon Sep 17 00:00:00 2001 From: qarlosalberto Date: Tue, 12 Mar 2024 17:02:33 +0100 Subject: [PATCH 46/77] ci: add viavi tests --- .gitlab/ci/build.yml | 2 -- .gitlab/ci/e2e.yml | 1 - tests/e2e/tests/viavi/config.yml | 10 +++------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 7d386f2736..48542b216b 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -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 e175750e98..ec9af7bca3 100644 --- a/.gitlab/ci/e2e.yml +++ b/.gitlab/ci/e2e.yml @@ -517,7 +517,6 @@ android n300: viavi: stage: rf extends: .e2e-run - allow_failure: true variables: GROUP: "viavi" TESTBED: "viavi" diff --git a/tests/e2e/tests/viavi/config.yml b/tests/e2e/tests/viavi/config.yml index 90457472f4..81df8206a1 100644 --- a/tests/e2e/tests/viavi/config.yml +++ b/tests/e2e/tests/viavi/config.yml @@ -6,12 +6,6 @@ # the distribution. # -cu_cp: - pdu_session_setup_timeout: 5 - inactivity_timer: 5 - rrc: - force_reestablishment_fallback: true - cell_cfg: dl_arfcn: 625000 band: 78 @@ -38,7 +32,9 @@ cell_cfg: mcs_table: qam256 max_alloc_attempts: 8 max_pdschs_per_slot: 8 - # max_rb_size: 45 # <-- enable this only for 32UE +{% if max_rb_size != -1 %} + max_rb_size: {{ max_rb_size }} +{% endif %} ul_common: max_ul_grants_per_slot: 16 max_pucchs_per_slot: 14 From 9941c47e6b0c35b41895fdf2cbb366e28de5486e Mon Sep 17 00:00:00 2001 From: Supreeth Herle Date: Wed, 13 Mar 2024 15:23:42 +0100 Subject: [PATCH 47/77] sched: set maximum k2 value based on TS 38.306 specification --- include/srsran/scheduler/sched_consts.h | 5 ++++- lib/scheduler/config/serving_cell_config_factory.cpp | 7 ------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/srsran/scheduler/sched_consts.h b/include/srsran/scheduler/sched_consts.h index f80bff5761..2df424cb2e 100644 --- a/include/srsran/scheduler/sched_consts.h +++ b/include/srsran/scheduler/sched_consts.h @@ -41,7 +41,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/lib/scheduler/config/serving_cell_config_factory.cpp b/lib/scheduler/config/serving_cell_config_factory.cpp index 2c3cbd0a1c..8aebe2e482 100644 --- a/lib/scheduler/config/serving_cell_config_factory.cpp +++ b/lib/scheduler/config/serving_cell_config_factory.cpp @@ -313,13 +313,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; - } } } } From 4e1a00e451b8af6969c88623ef72e1234ad4337e Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 14 Mar 2024 14:17:22 +0100 Subject: [PATCH 48/77] gnb: configurable stdout metrics period --- apps/gnb/gnb_appconfig.h | 5 +++-- apps/gnb/gnb_appconfig_cli11_schema.cpp | 5 +++++ apps/gnb/gnb_appconfig_translators.cpp | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/gnb/gnb_appconfig.h b/apps/gnb/gnb_appconfig.h index 73918ace02..70a946a7ff 100644 --- a/apps/gnb/gnb_appconfig.h +++ b/apps/gnb/gnb_appconfig.h @@ -807,11 +807,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 @@ -821,6 +821,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 21edd20cb6..bb4c828dd3 100644 --- a/apps/gnb/gnb_appconfig_cli11_schema.cpp +++ b/apps/gnb/gnb_appconfig_cli11_schema.cpp @@ -211,6 +211,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) diff --git a/apps/gnb/gnb_appconfig_translators.cpp b/apps/gnb/gnb_appconfig_translators.cpp index d1085a7a2c..80d8ecdf7f 100644 --- a/apps/gnb/gnb_appconfig_translators.cpp +++ b/apps/gnb/gnb_appconfig_translators.cpp @@ -1794,6 +1794,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) { From dec4b8ff7fee21ede3649a66e599bb639231894c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 14 Mar 2024 14:25:56 +0100 Subject: [PATCH 49/77] gnb: fix formatting of gnb console --- apps/gnb/helpers/metrics_plotter_stdout.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/gnb/helpers/metrics_plotter_stdout.cpp b/apps/gnb/helpers/metrics_plotter_stdout.cpp index 1649101e93..4eb379b6a6 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.cpp +++ b/apps/gnb/helpers/metrics_plotter_stdout.cpp @@ -43,8 +43,8 @@ static std::string scaled_fmt_integer(uint64_t num) 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\n"); } static std::string float_to_string(float f, int digits, int field_width) @@ -126,9 +126,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)); From 971e8be978ae2172a591234c46bf0106ad3bd2ed Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 14 Mar 2024 15:34:34 +0100 Subject: [PATCH 50/77] gnb: print to the console the TA --- apps/gnb/helpers/metrics_plotter_stdout.cpp | 17 +++++++- include/srsran/scheduler/scheduler_metrics.h | 40 ++++++++++--------- .../logging/scheduler_metric_handler.cpp | 7 +++- .../logging/scheduler_metrics_handler.h | 1 + 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/apps/gnb/helpers/metrics_plotter_stdout.cpp b/apps/gnb/helpers/metrics_plotter_stdout.cpp index 4eb379b6a6..773b188ebf 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.cpp +++ b/apps/gnb/helpers/metrics_plotter_stdout.cpp @@ -40,11 +40,19 @@ 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\n"); } static std::string float_to_string(float f, int digits, int field_width) @@ -173,6 +181,11 @@ 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"); + } fmt::print("\n"); } diff --git a/include/srsran/scheduler/scheduler_metrics.h b/include/srsran/scheduler/scheduler_metrics.h index 40107014c5..c9104799e7 100644 --- a/include/srsran/scheduler/scheduler_metrics.h +++ b/include/srsran/scheduler/scheduler_metrics.h @@ -10,6 +10,7 @@ #pragma once +#include "srsran/adt/optional.h" #include "srsran/adt/span.h" #include "srsran/ran/pci.h" #include "srsran/ran/rnti.h" @@ -19,25 +20,26 @@ 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; }; /// \brief Notifier interface used by scheduler to report UE metrics. diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index 9514867473..9043ab684b 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -52,6 +52,9 @@ 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(); + } } } @@ -236,7 +239,9 @@ 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)}; + } // 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 7f5736f235..729917d46f 100644 --- a/lib/scheduler/logging/scheduler_metrics_handler.h +++ b/lib/scheduler/logging/scheduler_metrics_handler.h @@ -95,6 +95,7 @@ class scheduler_metrics_handler final : public harq_timeout_handler, public sche uint8_t last_ri = 1; unsigned last_bsr = 0; phr_report last_phr; + double last_ta = -1; std::array last_dl_bs{0}; non_persistent_data data; From 552df2911f84c4b40cff0c8730f7794fcb221aa8 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 14 Mar 2024 16:04:38 +0100 Subject: [PATCH 51/77] sched: report TA measured via PUCCH to metrics --- .../logging/scheduler_metric_handler.cpp | 62 ++++++++++++++----- .../logging/scheduler_metrics_handler.h | 10 +-- .../ue_scheduling/ue_event_manager.cpp | 38 +++++------- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index 9043ab684b..6995ef89f6 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -58,16 +58,19 @@ void scheduler_metrics_handler::handle_crc_indication(const ul_crc_pdu_indicatio } } -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(); } } @@ -95,13 +98,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()); + } } } } diff --git a/lib/scheduler/logging/scheduler_metrics_handler.h b/lib/scheduler/logging/scheduler_metrics_handler.h index 729917d46f..761e1ce30e 100644 --- a/lib/scheduler/logging/scheduler_metrics_handler.h +++ b/lib/scheduler/logging/scheduler_metrics_handler.h @@ -39,17 +39,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); @@ -104,6 +101,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/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index b74eb0a5d0..fc257d2ea7 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -289,18 +289,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); @@ -339,9 +339,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) @@ -353,9 +350,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()) { @@ -371,9 +368,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()) { @@ -381,8 +375,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()) { @@ -394,8 +388,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()) { @@ -417,9 +411,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(); @@ -429,6 +420,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 From 1affbbc204a36b2accead60575743f13dc6e1428 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 14 Mar 2024 16:46:04 +0100 Subject: [PATCH 52/77] sched: report PHR in metrics --- apps/gnb/helpers/metrics_plotter_stdout.cpp | 11 +++++++++-- include/srsran/scheduler/scheduler_metrics.h | 1 + lib/scheduler/logging/scheduler_metric_handler.cpp | 6 +++++- lib/scheduler/logging/scheduler_metrics_handler.h | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/gnb/helpers/metrics_plotter_stdout.cpp b/apps/gnb/helpers/metrics_plotter_stdout.cpp index 773b188ebf..3a28daeaa9 100644 --- a/apps/gnb/helpers/metrics_plotter_stdout.cpp +++ b/apps/gnb/helpers/metrics_plotter_stdout.cpp @@ -51,8 +51,10 @@ static std::string scaled_time(std::chrono::microseconds t) 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 ta\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) @@ -186,6 +188,11 @@ void metrics_plotter_stdout::report_metrics(span ue_ } 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/scheduler/scheduler_metrics.h b/include/srsran/scheduler/scheduler_metrics.h index c9104799e7..978b5990bd 100644 --- a/include/srsran/scheduler/scheduler_metrics.h +++ b/include/srsran/scheduler/scheduler_metrics.h @@ -40,6 +40,7 @@ struct scheduler_ue_metrics { unsigned bsr; unsigned dl_bs; optional last_ta; + optional last_phr; }; /// \brief Notifier interface used by scheduler to report UE metrics. diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index 6995ef89f6..6a20cfb17f 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -158,7 +158,10 @@ 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()) { + interval rg = phr_ind.phr.get_phr().front().ph; + u.last_phr = (rg.start() + rg.stop()) / 2; + } } } @@ -274,6 +277,7 @@ scheduler_metrics_handler::ue_metric_context::compute_report(std::chrono::millis 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 761e1ce30e..c95c696c7e 100644 --- a/lib/scheduler/logging/scheduler_metrics_handler.h +++ b/lib/scheduler/logging/scheduler_metrics_handler.h @@ -91,7 +91,7 @@ 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; From cc74458bbdaf3d05b9edd12fbb9cb000dd04014c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 15 Mar 2024 10:07:58 +0100 Subject: [PATCH 53/77] sched: add comment explaining how the PHR is calculated in the metrics --- lib/scheduler/logging/scheduler_metric_handler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/scheduler/logging/scheduler_metric_handler.cpp b/lib/scheduler/logging/scheduler_metric_handler.cpp index 6a20cfb17f..f229f57dad 100644 --- a/lib/scheduler/logging/scheduler_metric_handler.cpp +++ b/lib/scheduler/logging/scheduler_metric_handler.cpp @@ -159,6 +159,7 @@ void scheduler_metrics_handler::handle_ul_phr_indication(const ul_phr_indication // Store last 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; } From 963a010ee728234960d92d11c96ed07fd462335b Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Thu, 14 Mar 2024 17:16:10 +0100 Subject: [PATCH 54/77] cu_cp,ngap: schedule transmission of ul nas transport msg --- lib/ngap/ngap_impl.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/ngap/ngap_impl.cpp b/lib/ngap/ngap_impl.cpp index 637789eb4b..9c27c85617 100644 --- a/lib/ngap/ngap_impl.cpp +++ b/lib/ngap/ngap_impl.cpp @@ -179,8 +179,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) @@ -714,11 +718,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) { From fefb11606d1e1671362639146a0ba07fab8735db Mon Sep 17 00:00:00 2001 From: asaezper Date: Fri, 15 Mar 2024 11:32:08 +0100 Subject: [PATCH 55/77] ci: update retina --- .gitlab/ci/e2e/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index 535f469057..d47c6fb363 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.8 +RETINA_VERSION=0.44.9 UBUNTU_VERSION=24.04 AMARISOFT_VERSION=2023-09-08 SRSUE_VERSION=23.11 From b7117bd584e5ffa7085d88ac79d142920f2b6714 Mon Sep 17 00:00:00 2001 From: Oriol Font-Bach Date: Fri, 15 Mar 2024 12:51:28 +0000 Subject: [PATCH 56/77] hal: fixes bbdev encoded data unpacking --- lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp | 8 ++++---- lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp index de83899247..2763d4b185 100644 --- a/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp +++ b/lib/hal/dpdk/bbdev/ldpc/bbdev_ldpc_encoder.cpp @@ -206,10 +206,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/phy/upper/channel_processors/pdsch_encoder_hw_impl.h b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h index eecdb508c7..7d7feafb1a 100644 --- a/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h +++ b/lib/phy/upper/channel_processors/pdsch_encoder_hw_impl.h @@ -25,6 +25,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 { @@ -95,7 +97,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. From e385ede9d5235392fe438c54f814922e37a4f36c Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 15 Mar 2024 14:59:43 +0100 Subject: [PATCH 57/77] sched: fix out-of-bounds access to MAC UCI in uci_cell_decoder --- lib/mac/mac_sched/uci_cell_decoder.cpp | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/mac/mac_sched/uci_cell_decoder.cpp b/lib/mac/mac_sched/uci_cell_decoder.cpp index 5708f0b493..7b379362f2 100644 --- a/lib/mac/mac_sched/uci_cell_decoder.cpp +++ b/lib/mac/mac_sched/uci_cell_decoder.cpp @@ -72,18 +72,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()) { @@ -128,20 +128,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); } } @@ -168,13 +168,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()); @@ -191,7 +191,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); } } @@ -216,7 +216,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); } } } From 72ededfde44732bb3edb1d124b0b2faafa3a0b8c Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 20 Feb 2024 17:11:20 +0100 Subject: [PATCH 58/77] sched: refactor srb sched - retx and ahead scheduling Signed-off-by: Carlo Galiotto --- include/srsran/ran/tdd/tdd_ul_dl_config.h | 6 + lib/ran/tdd_ul_dl_config.cpp | 28 ++ .../ue_scheduling/ue_event_manager.cpp | 7 +- .../ue_scheduling/ue_srb0_scheduler.cpp | 335 +++++++++++++++--- .../ue_scheduling/ue_srb0_scheduler.h | 78 +++- .../ue_scheduling/srb0_scheduler_test.cpp | 2 +- 6 files changed, 396 insertions(+), 60 deletions(-) diff --git a/include/srsran/ran/tdd/tdd_ul_dl_config.h b/include/srsran/ran/tdd/tdd_ul_dl_config.h index 395a8553ce..22529263f6 100644 --- a/include/srsran/ran/tdd/tdd_ul_dl_config.h +++ b/include/srsran/ran/tdd/tdd_ul_dl_config.h @@ -77,6 +77,12 @@ 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 UL symbols, starting from the given slot index. +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. +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. optional find_next_tdd_ul_slot(const tdd_ul_dl_config_common& cfg, unsigned start_slot_index = 0); diff --git a/lib/ran/tdd_ul_dl_config.cpp b/lib/ran/tdd_ul_dl_config.cpp index 6209987db0..fb9f911442 100644 --- a/lib/ran/tdd_ul_dl_config.cpp +++ b/lib/ran/tdd_ul_dl_config.cpp @@ -83,6 +83,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/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index fc257d2ea7..0fc84de237 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -80,7 +80,12 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ 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); + parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb(dl_bo.ue_index, + true); + } else if (dl_bo.lcid == LCID_SRB1) { + // Signal SRB0 scheduler with the new SRB0 buffer state. + parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb(dl_bo.ue_index, + false); } // Log event. diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 050679f9d5..e1c11f637d 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -37,6 +37,8 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) { + slot_indication(); + if (ues.empty()) { return; } @@ -45,91 +47,181 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) 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 and SRB1 retransmissions, if any. + auto next_ue_retx = ongoing_ues.begin(); + while (next_ue_retx != ongoing_ues.end()) { + // TODO: Add a stopping condition in this loop, so next_ue won't iterate over all the UEs and HARQ-processes if + // there are + // no resources. + + // Check if UE exists. + if (not ues.contains(next_ue_retx->ue_index)) { + next_ue_retx = ongoing_ues.erase(next_ue_retx); + continue; + } + auto& u = *ues.find(next_ue_retx->ue_index); + + for (auto& h_dl_rext : next_ue_retx->ongoing_h_procs) { + if (h_dl_rext.h_dl->has_pending_retx()) { + if (h_dl_rext.is_srb0) { + schedule_srb0(res_alloc, u, h_dl_rext.h_dl); + } else { + // TODO: Change this into SRB1_retx. + schedule_srb1(res_alloc, u); + } + } + } + ++next_ue_retx; } // Schedule SRB0 messages. - auto it = pending_ues.begin(); - while (it != pending_ues.end()) { + auto next_ue = pending_ues_srb0.begin(); + while (next_ue != pending_ues_srb0.end()) { // Check if UE exists. - if (not ues.contains(*it)) { - it = pending_ues.erase(it); + if (not ues.contains(*next_ue)) { + next_ue = pending_ues_srb0.erase(next_ue); continue; } - auto& u = ues[*it]; + auto& u = ues[*next_ue]; if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb0(res_alloc, u)) { - it = pending_ues.erase(it); + next_ue = pending_ues_srb0.erase(next_ue); + } else { + ++next_ue; + } + } + + // Keep SRB1 with lower priority than SRB0. + next_ue = pending_ues_srb1.begin(); + while (next_ue != pending_ues_srb1.end()) { + // Check if UE exists. + if (not ues.contains(*next_ue)) { + next_ue = pending_ues_srb1.erase(next_ue); + continue; + } + + auto& u = ues[*next_ue]; + if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb1(res_alloc, u)) { + next_ue = pending_ues_srb1.erase(next_ue); } else { - ++it; + ++next_ue; } } } -void ue_srb0_scheduler::handle_dl_buffer_state_indication(du_ue_index_t ue_index) +void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) { - pending_ues.push_back(ue_index); + is_srb0 ? pending_ues_srb0.push_back(ue_index) : pending_ues_srb1.push_back(ue_index); } -bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u) +static unsigned get_next_srb_slot(const cell_configuration& cell_cfg, slot_point sl_tx) +{ + if (not cell_cfg.is_tdd()) { + // In FDD, we advance by 1 slot. + return 1U; + } + const auto& tdd_cfg = cell_cfg.tdd_cfg_common.value(); + const unsigned tdd_period_nof_slots = nof_slots_per_tdd_period(tdd_cfg); + optional next_dl_slot_offset = + find_next_tdd_full_dl_slot(cell_cfg.tdd_cfg_common.value(), sl_tx.slot_index() % tdd_period_nof_slots); + if (not next_dl_slot_offset.has_value()) { + // This returns the offset from the current slot to the next DL slot within the next TDD period. + next_dl_slot_offset = tdd_period_nof_slots - sl_tx.slot_index() % tdd_period_nof_slots; + } + return next_dl_slot_offset.value(); +} + +bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u, dl_harq_process* h_dl_retx) { 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; + unsigned offset = 0; + for (unsigned offset_cnt = 0; offset_cnt != max_dl_slots_ahead_sched; + ++offset_cnt, offset = get_next_srb_slot(cell_cfg, res_alloc[0 + offset].slot)) { + 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); + + if (h_dl_retx != nullptr and h_dl_retx->last_alloc_params().nof_symbols != pdsch_td_cfg.symbols.length()) { + continue; + } + + // Fetch PDSCH resource grid allocators. + const cell_slot_resource_allocator& pdsch_alloc = res_alloc[offset + pdsch_td_cfg.k0]; + + // We do not support multiplexing of PDSCH for SRB0 with CSI-RS. + if (not pdsch_alloc.result.dl.csi_rs.empty()) { + continue; + } + + 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 (h_dl_retx != nullptr) { + return schedule_srb0_retx(u, res_alloc, time_res_idx, offset, *h_dl_retx); + } else { + dl_harq_process* candidate_h_dl = schedule_srb0(u, res_alloc, time_res_idx, offset); + if (candidate_h_dl != nullptr) { + cache_ue_srb_tx(u.ue_index, candidate_h_dl, /* is_srb0*/ true); + 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); + slot_point pdcch_slot = res_alloc[0].slot; + logger.debug("rnti={}: Not enough PDSCH space for SRB0 message found in any of the slots:[{},{}).", + u.crnti, + pdcch_slot, + pdcch_slot + max_dl_slots_ahead_sched); return false; } -bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, unsigned pdsch_time_res) +bool ue_srb0_scheduler::schedule_srb1(cell_resource_allocator& res_alloc, ue& u) +{ + // TODO: + return true; +} + +dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset) { 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]; + cell_slot_resource_allocator& pdcch_alloc = res_alloc[slot_offset]; + cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + 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; + return nullptr; } // 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; + return nullptr; } // Find available symbol x RB resources. @@ -169,7 +261,7 @@ bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, 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; + return nullptr; } if (mcs_idx > expert_cfg.max_msg4_mcs) { @@ -177,9 +269,99 @@ bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, 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. + 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 = 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, 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("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH."); + 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}); + + 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 h_dl; +} + +bool ue_srb0_scheduler::schedule_srb0_retx(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + dl_harq_process& h_dl_retx) +{ + 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[slot_offset]; + cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + 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; } + 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); + + // See 38.214, table 5.1.3.1-1: MCS index table 1 for PDSCH. + sch_mcs_index mcs_idx = h_dl_retx.last_alloc_params().tb[0]->mcs; + // 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{h_dl_retx.last_alloc_params().rbs.type1().length(), + h_dl_retx.last_alloc_params().tb[0].value().tbs_bytes}; + 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 ({} < {})", @@ -203,8 +385,8 @@ bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, 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); + 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; @@ -217,11 +399,12 @@ bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, } // Mark resources as occupied in the ResourceGrid. + // NOTE: the caller of this function has verified that the number of symbols is the same as the original transmission. 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, + h_dl_retx, *pdcch, pdsch_alloc.result.dl.ue_grants.emplace_back(), pucch_res_indicator.value(), @@ -230,7 +413,8 @@ bool ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, mcs_idx, ue_grant_crbs, pdsch_cfg, - prbs_tbs.tbs_bytes); + prbs_tbs.tbs_bytes, + &h_dl_retx); return true; } @@ -246,16 +430,23 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, sch_mcs_index mcs_idx, const crb_interval& ue_grant_crbs, const pdsch_config_params& pdsch_params, - unsigned tbs_bytes) + unsigned tbs_bytes, + dl_harq_process* h_dl_retx) { 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()); + if (h_dl_retx == nullptr) { + 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()); + } else { + // We do not multiplex the SRBO PUCCH with existing PUCCH HARQs. + 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; @@ -289,3 +480,41 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg { return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; } + +void ue_srb0_scheduler::cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) +{ + auto it_ue = std::find_if(ongoing_ues.begin(), ongoing_ues.end(), [ue_index](const ue_srb_tx_tracker& tracker) { + return tracker.ue_index == ue_index; + }); + + // There is already a UE with HARQ processes waiting for ACK or with pending retx. + if (it_ue != ongoing_ues.end()) { + srsran_assert(it_ue->has_harq_id(h_dl->id), "This HARQ process was already in the list"); + it_ue->add_harq_id(h_dl, is_srb0); + } else { + ongoing_ues.emplace_back(ue_index); + auto& ue_harq_tracker = ongoing_ues.back(); + srsran_assert(ue_harq_tracker.has_harq_id(h_dl->id), "This HARQ process was already in the list"); + ue_harq_tracker.add_harq_id(h_dl, is_srb0); + } +} + +void ue_srb0_scheduler::slot_indication() +{ + if (ongoing_ues.empty()) { + return; + } + + // Iterate over the UEs, and check if there are any empty HARQ processes. + auto it_ue = ongoing_ues.begin(); + while (it_ue != ongoing_ues.end()) { + // Remove HARQ processes that have been acked for the current UE. + it_ue->erase_acked_processes(); + // If the UE has no current HARQ process with pending retx or waiting for ack, remove it. + if (it_ue->ongoing_h_procs.empty()) { + it_ue = ongoing_ues.erase(it_ue); + continue; + } + ++it_ue; + } +} diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index 74a9418763..9315272f1b 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -29,9 +29,12 @@ class ue_srb0_scheduler pucch_allocator& pucch_alloc_, ue_repository& ues_); + /// Erase the UEs' HARQ processes that have been acked from the SRB scheduler cache. + void slot_indication(); + /// 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); + 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. @@ -39,10 +42,21 @@ class ue_srb0_scheduler 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); + bool schedule_srb0(cell_resource_allocator& res_alloc, ue& u, dl_harq_process* h_dl_retx = nullptr); + + /// \brief Tries to schedule SRB0 message for a UE. Returns true if successful, false otherwise. + bool schedule_srb1(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); + dl_harq_process* + schedule_srb0(ue& u, cell_resource_allocator& res_alloc, unsigned pdsch_time_res, unsigned slot_offset); + + /// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space for a . + bool schedule_srb0_retx(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + dl_harq_process& h_dl_retx); void fill_srb0_grant(ue& u, slot_point pdsch_slot, @@ -55,12 +69,60 @@ class ue_srb0_scheduler sch_mcs_index mcs_idx, const crb_interval& ue_grant_crbs, const pdsch_config_params& pdsch_params, - unsigned tbs_bytes); + unsigned tbs_bytes, + dl_harq_process* h_dl_retx = nullptr); const pdsch_time_domain_resource_allocation& get_pdsch_td_cfg(unsigned pdsch_time_res_idx) const; + /// Class that keeps track of the UEs' that are waiting for the SRB HARQ processes to be ACKed or retransmitted. + class ue_srb_tx_tracker + { + public: + explicit ue_srb_tx_tracker(du_ue_index_t ue_index_) : ue_index(ue_index_) {} + + struct srb_dl_harq { + dl_harq_process* h_dl; + bool is_srb0; + }; + + void add_harq_id(dl_harq_process* h_dl, bool is_srb0_) + { + if (h_dl == nullptr) { + return; + } + ongoing_h_procs.push_back(srb_dl_harq{h_dl, is_srb0_}); + } + + void erase_acked_processes() + { + auto it_h_dl = ongoing_h_procs.begin(); + + // Iterate over the HARQ processes, and check if there are any empty HARQ processes. + while (it_h_dl != ongoing_h_procs.end()) { + if ((*it_h_dl).h_dl->empty()) { + it_h_dl = ongoing_h_procs.erase(it_h_dl); + continue; + } + ++it_h_dl; + } + } + + bool has_harq_id(harq_id_t h_id) const + { + return std::find_if(ongoing_h_procs.begin(), ongoing_h_procs.end(), [h_id](const srb_dl_harq& srb_h_proc) { + return srb_h_proc.h_dl->id == h_id; + }) != ongoing_h_procs.end(); + } + + du_ue_index_t ue_index; + std::vector ongoing_h_procs; + }; + + void cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); + const scheduler_ue_expert_config& expert_cfg; const cell_configuration& cell_cfg; + const unsigned max_dl_slots_ahead_sched = 5U; pdcch_resource_allocator& pdcch_sch; pucch_allocator& pucch_alloc; ue_repository& ues; @@ -74,7 +136,13 @@ class ue_srb0_scheduler coreset_configuration cs_cfg; /// List of UE's DU Indexes for which SRB0 messages needs to be scheduled. - std::vector pending_ues; + std::vector pending_ues_srb0; + + /// List of UE's DU Indexes for which SRB1 messages needs to be scheduled. + std::vector pending_ues_srb1; + + /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. + std::vector ongoing_ues; srslog::basic_logger& logger; }; diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index 7a38b828bb..972d993a4b 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -273,7 +273,7 @@ class base_srb0_scheduler_tester 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); + bench->srb0_sched.handle_dl_buffer_state_indication_srb(ue_idx, true); } unsigned get_pending_bytes(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx].pending_dl_srb0_newtx_bytes(); } From 663d1843f32f31724f9cfc48e8e9f00a3d5bf51d Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 26 Feb 2024 11:25:11 +0100 Subject: [PATCH 59/77] sched: add SRB1 fallback scheduler to srb0 sched Signed-off-by: Carlo Galiotto --- lib/scheduler/support/dci_builder.cpp | 24 +- lib/scheduler/support/dci_builder.h | 22 +- lib/scheduler/support/mcs_tbs_calculator.cpp | 9 +- lib/scheduler/support/mcs_tbs_calculator.h | 9 +- .../support/pdsch/pdsch_resource_allocation.h | 5 +- lib/scheduler/support/sch_pdu_builder.cpp | 16 +- lib/scheduler/support/sch_pdu_builder.h | 7 +- .../dl_logical_channel_manager.cpp | 9 +- .../dl_logical_channel_manager.h | 7 +- lib/scheduler/ue_scheduling/harq_process.cpp | 10 +- lib/scheduler/ue_scheduling/harq_process.h | 4 +- lib/scheduler/ue_scheduling/ue.cpp | 19 +- lib/scheduler/ue_scheduling/ue.h | 10 +- lib/scheduler/ue_scheduling/ue_cell.cpp | 2 +- .../ue_scheduling/ue_cell_grid_allocator.cpp | 12 +- .../ue_scheduling/ue_event_manager.cpp | 10 +- .../ue_pdsch_param_candidate_searcher.h | 4 +- .../ue_scheduling/ue_srb0_scheduler.cpp | 495 +++++++++++++----- .../ue_scheduling/ue_srb0_scheduler.h | 109 ++-- .../support/mcs_tbs_calculator_test.cpp | 5 +- .../ue_scheduling/srb0_scheduler_test.cpp | 5 +- 21 files changed, 504 insertions(+), 289 deletions(-) diff --git a/lib/scheduler/support/dci_builder.cpp b/lib/scheduler/support/dci_builder.cpp index 9ef02d3df6..330b018438 100644 --- a/lib/scheduler/support/dci_builder.cpp +++ b/lib/scheduler/support/dci_builder.cpp @@ -150,22 +150,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 14982fed4f..36a1489ce9 100644 --- a/lib/scheduler/support/dci_builder.h +++ b/lib/scheduler/support/dci_builder.h @@ -52,17 +52,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 2a9a259819..40248f2069 100644 --- a/lib/scheduler/support/mcs_tbs_calculator.cpp +++ b/lib/scheduler/support/mcs_tbs_calculator.cpp @@ -149,11 +149,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 25f5486617..936ef966a6 100644 --- a/lib/scheduler/support/mcs_tbs_calculator.h +++ b/lib/scheduler/support/mcs_tbs_calculator.h @@ -31,17 +31,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 842b93c6aa..4cada44d03 100644 --- a/lib/scheduler/support/pdsch/pdsch_resource_allocation.h +++ b/lib/scheduler/support/pdsch/pdsch_resource_allocation.h @@ -52,11 +52,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 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/sch_pdu_builder.cpp b/lib/scheduler/support/sch_pdu_builder.cpp index de2fcdaae9..e578105850 100644 --- a/lib/scheduler/support/sch_pdu_builder.cpp +++ b/lib/scheduler/support/sch_pdu_builder.cpp @@ -60,7 +60,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. @@ -70,12 +71,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; @@ -482,14 +482,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 4e55999541..281f49896f 100644 --- a/lib/scheduler/support/sch_pdu_builder.h +++ b/lib/scheduler/support/sch_pdu_builder.h @@ -53,7 +53,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. @@ -129,8 +130,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/ue_scheduling/dl_logical_channel_manager.cpp b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp index 9b59b87058..6ef931bb00 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp @@ -37,12 +37,12 @@ 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(); + lcid = lcid == lcid_t::INVALID_LCID ? get_max_prio_lcid() : lcid; if (lcid == lcid_t::INVALID_LCID) { return 0; } @@ -130,7 +130,8 @@ 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; @@ -138,7 +139,7 @@ unsigned srsran::allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_m // 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; } diff --git a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h index e4693c407d..20c05470a5 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h @@ -117,7 +117,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. @@ -156,7 +156,10 @@ class dl_logical_channel_manager /// \param[in] lch_mng UE DL logical channel manager. /// \param[in] total_tbs available space in bytes for subPDUs. /// \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 8543a7c327..5d082a0146 100644 --- a/lib/scheduler/ue_scheduling/harq_process.cpp +++ b/lib/scheduler/ue_scheduling/harq_process.cpp @@ -184,13 +184,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 9643989f92..2936de31c5 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -270,6 +270,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; }; struct dl_ack_info_result { @@ -311,7 +312,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 a047606f0b..ab5f7f7eef 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -113,17 +113,22 @@ unsigned ue::pending_dl_newtx_bytes() const return 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(); } return pending_bytes; } +unsigned ue::pending_dl_srb1_newtx_bytes() const +{ + return dl_lc_ch_mgr.pending_bytes(LCID_SRB1); +} + unsigned ue::pending_ul_newtx_bytes() const { constexpr static unsigned SR_GRANT_BYTES = 512; @@ -156,18 +161,18 @@ 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_srb0_srb1_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_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, lcid); return total_subpdu_bytes; } diff --git a/lib/scheduler/ue_scheduling/ue.h b/lib/scheduler/ue_scheduling/ue.h index 39344e3550..76a7bf9f64 100644 --- a/lib/scheduler/ue_scheduling/ue.h +++ b/lib/scheduler/ue_scheduling/ue.h @@ -134,7 +134,11 @@ class ue /// \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; + unsigned pending_dl_srb0_or_srb1_newtx_bytes(bool is_srb0) 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_srb1_newtx_bytes() 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. @@ -146,12 +150,12 @@ 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. /// \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_srb0_srb1_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, lcid_t lcid); 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 fa4c760d63..6f95075936 100644 --- a/lib/scheduler/ue_scheduling/ue_cell.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell.cpp @@ -84,7 +84,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 3b8adb2c4e..2abe96a58e 100644 --- a/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp +++ b/lib/scheduler/ue_scheduling/ue_cell_grid_allocator.cpp @@ -265,7 +265,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); @@ -301,7 +301,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( @@ -366,8 +366,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, @@ -420,8 +420,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); diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 0fc84de237..fe9698c48e 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -78,14 +78,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) { + if (dl_bo.lcid == LCID_SRB0 or (u.get_pcell().is_in_fallback_mode() and dl_bo.lcid == LCID_SRB1)) { // Signal SRB0 scheduler with the new SRB0 buffer state. - parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb(dl_bo.ue_index, - true); - } else if (dl_bo.lcid == LCID_SRB1) { - // Signal SRB0 scheduler with the new SRB0 buffer state. - parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb(dl_bo.ue_index, - false); + parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb( + dl_bo.ue_index, dl_bo.lcid == LCID_SRB0); } // Log event. 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 633a647c3f..611bf19b28 100644 --- a/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h +++ b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h @@ -35,7 +35,7 @@ class ue_pdsch_param_candidate_searcher using ss_iter = static_vector::const_iterator; public: - struct iterator; + // struct iterator; /// Parameters for a given PDSCH candidate. struct candidate { @@ -137,7 +137,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 ((not h.last_alloc_params().is_fallback) and h.has_pending_retx()) { dl_harq_candidates.push_back(&h); } } diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index e1c11f637d..7bf7f05937 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -48,62 +48,69 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) return; } - // Schedule SRB0 and SRB1 retransmissions, if any. - auto next_ue_retx = ongoing_ues.begin(); - while (next_ue_retx != ongoing_ues.end()) { + auto next_ue_harq_retx = ongoing_ues_ack_retx.begin(); + while (next_ue_harq_retx != ongoing_ues_ack_retx.end()) { // TODO: Add a stopping condition in this loop, so next_ue won't iterate over all the UEs and HARQ-processes if - // there are - // no resources. + // there are no resources. // Check if UE exists. - if (not ues.contains(next_ue_retx->ue_index)) { - next_ue_retx = ongoing_ues.erase(next_ue_retx); + if (not ues.contains(next_ue_harq_retx->ue_index)) { + next_ue_harq_retx = ongoing_ues_ack_retx.erase(next_ue_harq_retx); continue; } - auto& u = *ues.find(next_ue_retx->ue_index); - - for (auto& h_dl_rext : next_ue_retx->ongoing_h_procs) { - if (h_dl_rext.h_dl->has_pending_retx()) { - if (h_dl_rext.is_srb0) { - schedule_srb0(res_alloc, u, h_dl_rext.h_dl); - } else { - // TODO: Change this into SRB1_retx. - schedule_srb1(res_alloc, u); - } + auto& u = *ues.find(next_ue_harq_retx->ue_index); + auto* h_dl = next_ue_harq_retx->get_harq_process(); + + if (h_dl->last_alloc_params().is_fallback and h_dl->has_pending_retx()) { + if (next_ue_harq_retx->is_srb0) { + schedule_srb(res_alloc, u, true, h_dl); + } else { + // TODO: Change this into SRB1_retx. + schedule_srb(res_alloc, u, true, h_dl); } } - ++next_ue_retx; + ++next_ue_harq_retx; } // Schedule SRB0 messages. - auto next_ue = pending_ues_srb0.begin(); - while (next_ue != pending_ues_srb0.end()) { + auto next_ue = pending_ues.begin(); + while (next_ue != pending_ues.end()) { // Check if UE exists. - if (not ues.contains(*next_ue)) { - next_ue = pending_ues_srb0.erase(next_ue); + if (not ues.contains(next_ue->ue_index)) { + next_ue = pending_ues.erase(next_ue); continue; } - auto& u = ues[*next_ue]; - if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb0(res_alloc, u)) { - next_ue = pending_ues_srb0.erase(next_ue); + if (not next_ue->is_srb0) { + continue; + ++next_ue; + } + + auto& u = ues[next_ue->ue_index]; + if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb(res_alloc, u, true)) { + next_ue = pending_ues.erase(next_ue); } else { ++next_ue; } } // Keep SRB1 with lower priority than SRB0. - next_ue = pending_ues_srb1.begin(); - while (next_ue != pending_ues_srb1.end()) { + next_ue = pending_ues.begin(); + while (next_ue != pending_ues.end()) { // Check if UE exists. - if (not ues.contains(*next_ue)) { - next_ue = pending_ues_srb1.erase(next_ue); + if (not ues.contains(next_ue->ue_index)) { + next_ue = pending_ues.erase(next_ue); + continue; + } + + if (next_ue->is_srb0) { continue; + ++next_ue; } - auto& u = ues[*next_ue]; - if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb1(res_alloc, u)) { - next_ue = pending_ues_srb1.erase(next_ue); + auto& u = ues[next_ue->ue_index]; + if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false)) { + next_ue = pending_ues.erase(next_ue); } else { ++next_ue; } @@ -112,7 +119,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) { - is_srb0 ? pending_ues_srb0.push_back(ue_index) : pending_ues_srb1.push_back(ue_index); + is_srb0 ? pending_ues.push_back({ue_index, true}) : pending_ues.push_back({ue_index, false}); } static unsigned get_next_srb_slot(const cell_configuration& cell_cfg, slot_point sl_tx) @@ -132,7 +139,10 @@ static unsigned get_next_srb_slot(const cell_configuration& cell_cfg, slot_point return next_dl_slot_offset.value(); } -bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u, dl_harq_process* h_dl_retx) +bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, + ue& u, + bool is_srb0, + dl_harq_process* h_dl_retx) { const auto& bwp_cfg_common = cell_cfg.dl_cfg_common.init_dl_bwp; // Search valid PDSCH time domain resource. @@ -151,12 +161,12 @@ bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u, // Fetch PDSCH resource grid allocators. const cell_slot_resource_allocator& pdsch_alloc = res_alloc[offset + pdsch_td_cfg.k0]; - // We do not support multiplexing of PDSCH for SRB0 with CSI-RS. - if (not pdsch_alloc.result.dl.csi_rs.empty()) { + if (not cell_cfg.is_dl_enabled(pdsch_alloc.slot)) { continue; } - if (not cell_cfg.is_dl_enabled(pdsch_alloc.slot)) { + // We do not support multiplexing of PDSCH for SRB0 with CSI-RS. + if (not pdsch_alloc.result.dl.csi_rs.empty()) { continue; } @@ -171,9 +181,12 @@ bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u, } if (h_dl_retx != nullptr) { - return schedule_srb0_retx(u, res_alloc, time_res_idx, offset, *h_dl_retx); + dl_harq_process* ret_outcome = is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset, h_dl_retx) + : schedule_srb1(u, res_alloc, time_res_idx, offset, h_dl_retx); + return ret_outcome != nullptr; } else { - dl_harq_process* candidate_h_dl = schedule_srb0(u, res_alloc, time_res_idx, offset); + dl_harq_process* candidate_h_dl = is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset) + : schedule_srb1(u, res_alloc, time_res_idx, offset); if (candidate_h_dl != nullptr) { cache_ue_srb_tx(u.ue_index, candidate_h_dl, /* is_srb0*/ true); return true; @@ -191,16 +204,11 @@ bool ue_srb0_scheduler::schedule_srb0(cell_resource_allocator& res_alloc, ue& u, return false; } -bool ue_srb0_scheduler::schedule_srb1(cell_resource_allocator& res_alloc, ue& u) -{ - // TODO: - return true; -} - dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, cell_resource_allocator& res_alloc, unsigned pdsch_time_res, - unsigned slot_offset) + unsigned slot_offset, + 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; @@ -217,59 +225,74 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, return nullptr; } + 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 = ue_pcell.harqs.find_empty_dl_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; } - // 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); + sch_prbs_tbs prbs_tbs{}; + sch_mcs_index mcs_idx = 0; 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; + + if (is_retx) { + // See 38.214, table 5.1.3.1-1: MCS index table 1 for PDSCH. + mcs_idx = h_dl->last_alloc_params().tb[0]->mcs; + // 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. + 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 { + // Find available symbol x RB resources. + const unsigned pending_bytes = u.pending_dl_srb0_or_srb1_newtx_bytes(true); + + 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. + + // 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. + 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; } - ++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 (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={}: MCS index chosen ({}) for SRB0 exceeds maximum allowed MCS index ({}).", - u.crnti, - mcs_idx, - expert_cfg.max_msg4_mcs); - return nullptr; + 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 nullptr; + } } crb_interval ue_grant_crbs = rb_helper::find_empty_interval_of_length(used_crbs, prbs_tbs.nof_prbs, 0); @@ -322,53 +345,125 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, mcs_idx, ue_grant_crbs, pdsch_cfg, - prbs_tbs.tbs_bytes); + prbs_tbs.tbs_bytes, + is_retx); return h_dl; } -bool ue_srb0_scheduler::schedule_srb0_retx(ue& u, - cell_resource_allocator& res_alloc, - unsigned pdsch_time_res, - unsigned slot_offset, - dl_harq_process& h_dl_retx) +dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + 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); // Fetch PDCCH and PDSCH resource grid allocators. cell_slot_resource_allocator& pdcch_alloc = res_alloc[slot_offset]; + slot_point pdcch_slot = pdcch_alloc.slot; cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + 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; + return nullptr; } - 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) { + 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. 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); - // See 38.214, table 5.1.3.1-1: MCS index table 1 for PDSCH. - sch_mcs_index mcs_idx = h_dl_retx.last_alloc_params().tb[0]->mcs; - // 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{h_dl_retx.last_alloc_params().rbs.type1().length(), - h_dl_retx.last_alloc_params().tb[0].value().tbs_bytes}; + crb_interval ue_grant_crbs; + sch_mcs_tbs final_mcs_tbs; - 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; + 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 alloc_outcome::skip_ue; + 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_srb1_newtx_bytes(); + 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 alloc_outcome::skip_ue; + 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(pdcch_slot + pdsch_td_cfg.k0) 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 alloc_outcome::skip_ue; + 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. @@ -376,7 +471,7 @@ bool ue_srb0_scheduler::schedule_srb0_retx(ue& u, 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; + return nullptr; } // Allocate PUCCH resources. @@ -395,28 +490,27 @@ bool ue_srb0_scheduler::schedule_srb0_retx(ue& u, 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; + return nullptr; } // Mark resources as occupied in the ResourceGrid. - // NOTE: the caller of this function has verified that the number of symbols is the same as the original transmission. pdsch_alloc.dl_res_grid.fill(grant_info{scs, pdsch_td_cfg.symbols, ue_grant_crbs}); - fill_srb0_grant(u, + fill_srb1_grant(u, pdsch_alloc.slot, - h_dl_retx, + *h_dl, *pdcch, pdsch_alloc.result.dl.ue_grants.emplace_back(), pucch_res_indicator.value(), pdsch_time_res, k1, - mcs_idx, + final_mcs_tbs.mcs, ue_grant_crbs, pdsch_cfg, - prbs_tbs.tbs_bytes, - &h_dl_retx); + final_mcs_tbs.tbs, + is_retx); - return true; + return h_dl; } void ue_srb0_scheduler::fill_srb0_grant(ue& u, @@ -431,17 +525,19 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, const crb_interval& ue_grant_crbs, const pdsch_config_params& pdsch_params, unsigned tbs_bytes, - dl_harq_process* h_dl_retx) + bool is_retx) { static constexpr uint8_t srb0_dai = 0; // Allocate DL HARQ. - if (h_dl_retx == nullptr) { + if (not is_retx) { + const bool is_fallback = true; 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()); + u.get_pcell().channel_state_manager().get_nof_dl_layers(), + is_fallback); } else { // We do not multiplex the SRBO PUCCH with existing PUCCH HARQs. const unsigned harq_bit_idx = 0U; @@ -469,8 +565,125 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, 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); + if (not is_retx) { + // Set MAC logical channels to schedule in this PDU. + u.build_dl_srb0_srb1_transport_block_info( + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB0); + } + + // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. + h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); +} + +void ue_srb0_scheduler::fill_srb1_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, + bool is_retx) +{ + static constexpr uint8_t srb1_dai = 0; + // Allocate DL HARQ. + if (not is_retx) { + const bool is_fallback = true; + h_dl.new_tx(pdsch_slot, + k1, + expert_cfg.max_nof_harq_retxs, + srb1_dai, + u.get_pcell().channel_state_manager().get_wideband_cqi(), + 1U, + is_fallback); + } else { + // We do not multiplex the SRBO PUCCH with existing PUCCH HARQs. + 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; + switch (pdcch.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, + srb1_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 (pdcch.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, true); + + // Set MAC logical channels to schedule in this PDU. + if (not is_retx) { + u.build_dl_srb0_srb1_transport_block_info( + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB1); + } + break; + } + 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"); + } + } + // 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); + u.build_dl_srb0_srb1_transport_block_info( + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB1); // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); @@ -483,38 +696,32 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg void ue_srb0_scheduler::cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) { - auto it_ue = std::find_if(ongoing_ues.begin(), ongoing_ues.end(), [ue_index](const ue_srb_tx_tracker& tracker) { - return tracker.ue_index == ue_index; - }); - - // There is already a UE with HARQ processes waiting for ACK or with pending retx. - if (it_ue != ongoing_ues.end()) { - srsran_assert(it_ue->has_harq_id(h_dl->id), "This HARQ process was already in the list"); - it_ue->add_harq_id(h_dl, is_srb0); - } else { - ongoing_ues.emplace_back(ue_index); - auto& ue_harq_tracker = ongoing_ues.back(); - srsran_assert(ue_harq_tracker.has_harq_id(h_dl->id), "This HARQ process was already in the list"); - ue_harq_tracker.add_harq_id(h_dl, is_srb0); - } + auto it_ue = std::find_if( + ongoing_ues_ack_retx.begin(), ongoing_ues_ack_retx.end(), [ue_index, h_dl](const ack_and_retx_tracker& tracker) { + return tracker.match_ue_harq(ue_index, h_dl); + }); + + srsran_assert(it_ue == ongoing_ues_ack_retx.end(), "This UE and HARQ process were already in the list"); + ongoing_ues_ack_retx.emplace_back(ue_index, h_dl, is_srb0, ues); } void ue_srb0_scheduler::slot_indication() { - if (ongoing_ues.empty()) { + if (ongoing_ues_ack_retx.empty()) { return; } - // Iterate over the UEs, and check if there are any empty HARQ processes. - auto it_ue = ongoing_ues.begin(); - while (it_ue != ongoing_ues.end()) { - // Remove HARQ processes that have been acked for the current UE. - it_ue->erase_acked_processes(); - // If the UE has no current HARQ process with pending retx or waiting for ack, remove it. - if (it_ue->ongoing_h_procs.empty()) { - it_ue = ongoing_ues.erase(it_ue); + auto it_ue_harq = ongoing_ues_ack_retx.begin(); + while (it_ue_harq != ongoing_ues_ack_retx.end()) { + if (not ues.contains(it_ue_harq->ue_index)) { + it_ue_harq = ongoing_ues_ack_retx.erase(it_ue_harq); + continue; + } + dl_harq_process& h_dl = *it_ue_harq->get_harq_process(); + if (h_dl.empty()) { + it_ue_harq = ongoing_ues_ack_retx.erase(it_ue_harq); continue; } - ++it_ue; + ++it_ue_harq; } } diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index 9315272f1b..336fb896fe 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -15,6 +15,7 @@ #include "../support/slot_event_list.h" #include "ue_repository.h" #include "srsran/scheduler/scheduler_configurator.h" +#include #include namespace srsran { @@ -29,9 +30,6 @@ class ue_srb0_scheduler pucch_allocator& pucch_alloc_, ue_repository& ues_); - /// Erase the UEs' HARQ processes that have been acked from the SRB scheduler cache. - void slot_indication(); - /// 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); @@ -41,22 +39,25 @@ class ue_srb0_scheduler 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, dl_harq_process* h_dl_retx = nullptr); + /// Erase the UEs' HARQ processes that have been acked from the SRB scheduler cache. + void slot_indication(); /// \brief Tries to schedule SRB0 message for a UE. Returns true if successful, false otherwise. - bool schedule_srb1(cell_resource_allocator& res_alloc, ue& u); + bool schedule_srb(cell_resource_allocator& res_alloc, ue& u, bool is_srb0, dl_harq_process* h_dl_retx = nullptr); /// \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); + dl_harq_process* schedule_srb0(ue& u, + cell_resource_allocator& res_alloc, + unsigned pdsch_time_res, + unsigned slot_offset, + dl_harq_process* h_dl_retx = nullptr); - /// \brief Tries to schedule SRB0 message for a UE and a specific PDSCH TimeDomain Resource and Search Space for a . - bool schedule_srb0_retx(ue& u, - cell_resource_allocator& res_alloc, - unsigned pdsch_time_res, - unsigned slot_offset, - 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, + dl_harq_process* h_dl_retx = nullptr); void fill_srb0_grant(ue& u, slot_point pdsch_slot, @@ -70,52 +71,58 @@ class ue_srb0_scheduler const crb_interval& ue_grant_crbs, const pdsch_config_params& pdsch_params, unsigned tbs_bytes, - dl_harq_process* h_dl_retx = nullptr); + bool is_retx); + + void fill_srb1_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, + bool is_retx); 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 ue_srb_tx_tracker + class ack_and_retx_tracker { public: - explicit ue_srb_tx_tracker(du_ue_index_t ue_index_) : ue_index(ue_index_) {} - - struct srb_dl_harq { - dl_harq_process* h_dl; - bool is_srb0; - }; - - void add_harq_id(dl_harq_process* h_dl, bool is_srb0_) + 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_), ues(ues_) { - if (h_dl == nullptr) { - return; - } - ongoing_h_procs.push_back(srb_dl_harq{h_dl, is_srb0_}); + srsran_assert(ues.contains(ue_index), "UE not found in the UE repository"); + srsran_assert(h_dl_ == &(ues[ue_idx].get_pcell().harqs.dl_harq(h_dl_->id)), + "HARQ process not found among the UE HARQs"); } - void erase_acked_processes() + bool match_ue_harq(du_ue_index_t ue_idx_, dl_harq_process* h_dl_) const { - auto it_h_dl = ongoing_h_procs.begin(); - - // Iterate over the HARQ processes, and check if there are any empty HARQ processes. - while (it_h_dl != ongoing_h_procs.end()) { - if ((*it_h_dl).h_dl->empty()) { - it_h_dl = ongoing_h_procs.erase(it_h_dl); - continue; - } - ++it_h_dl; - } + return ue_index == ue_idx_ and h_dl == h_dl_; } - bool has_harq_id(harq_id_t h_id) const - { - return std::find_if(ongoing_h_procs.begin(), ongoing_h_procs.end(), [h_id](const srb_dl_harq& srb_h_proc) { - return srb_h_proc.h_dl->id == h_id; - }) != ongoing_h_procs.end(); - } + // We make the access to the HARQ process is subject to the UE existence in the UE repository. + dl_harq_process* get_harq_process() const { return ues.contains(ue_index) ? h_dl : nullptr; } - du_ue_index_t ue_index; - std::vector ongoing_h_procs; + du_ue_index_t ue_index; + bool is_srb0; + + private: + dl_harq_process* h_dl; + ue_repository& ues; }; void cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); @@ -135,14 +142,8 @@ class ue_srb0_scheduler 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_srb0; - - /// List of UE's DU Indexes for which SRB1 messages needs to be scheduled. - std::vector pending_ues_srb1; - /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. - std::vector ongoing_ues; + std::list ongoing_ues_ack_retx; srslog::basic_logger& logger; }; diff --git a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp index 12026b3fcc..25a2e6bdc2 100644 --- a/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp +++ b/tests/unittests/scheduler/support/mcs_tbs_calculator_test.cpp @@ -43,7 +43,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/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index 972d993a4b..9cb4cbe4d2 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -276,7 +276,10 @@ class base_srb0_scheduler_tester bench->srb0_sched.handle_dl_buffer_state_indication_srb(ue_idx, true); } - unsigned get_pending_bytes(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx].pending_dl_srb0_newtx_bytes(); } + unsigned get_pending_bytes(du_ue_index_t ue_idx) + { + return bench->ue_db[ue_idx].pending_dl_srb0_or_srb1_newtx_bytes(true); + } const ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } }; From dc606dbf830de1f9da5c311a909c9e45769152be Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 1 Mar 2024 19:13:08 +0100 Subject: [PATCH 60/77] sched: refactor for loop for ahead-scheduling srb0 Signed-off-by: Carlo Galiotto --- include/srsran/ran/tdd/tdd_ul_dl_config.h | 10 +- lib/scheduler/ue_scheduling/ue.cpp | 5 +- lib/scheduler/ue_scheduling/ue.h | 5 +- .../ue_pdsch_param_candidate_searcher.h | 2 +- .../ue_scheduling/ue_srb0_scheduler.cpp | 308 ++++++++++-------- .../ue_scheduling/ue_srb0_scheduler.h | 20 +- 6 files changed, 205 insertions(+), 145 deletions(-) diff --git a/include/srsran/ran/tdd/tdd_ul_dl_config.h b/include/srsran/ran/tdd/tdd_ul_dl_config.h index 22529263f6..5c5d6b00bd 100644 --- a/include/srsran/ran/tdd/tdd_ul_dl_config.h +++ b/include/srsran/ran/tdd/tdd_ul_dl_config.h @@ -77,16 +77,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 UL symbols, starting from the given slot index. +/// \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/lib/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index ab5f7f7eef..9042599705 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -169,10 +169,11 @@ unsigned ue::build_dl_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_ return total_subpdu_bytes; } -unsigned ue::build_dl_srb0_srb1_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, lcid_t lcid) +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, lcid); + 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 76a7bf9f64..f4735065c5 100644 --- a/lib/scheduler/ue_scheduling/ue.h +++ b/lib/scheduler/ue_scheduling/ue.h @@ -153,9 +153,10 @@ class ue 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_srb1_transport_block_info(dl_msg_tb_info& tb_info, unsigned tb_size_bytes, lcid_t lcid); + 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_pdsch_param_candidate_searcher.h b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h index 611bf19b28..b6c45734e7 100644 --- a/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h +++ b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h @@ -35,7 +35,7 @@ class ue_pdsch_param_candidate_searcher using ss_iter = static_vector::const_iterator; public: - // struct iterator; + struct iterator; /// Parameters for a given PDSCH candidate. struct candidate { diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 7bf7f05937..62dd888bc2 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -37,7 +37,7 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) { - slot_indication(); + update_ongoing_ue_retxs(); if (ues.empty()) { return; @@ -48,25 +48,21 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) return; } - auto next_ue_harq_retx = ongoing_ues_ack_retx.begin(); - while (next_ue_harq_retx != ongoing_ues_ack_retx.end()) { + auto next_ue_harq_retx = ongoing_ues_ack_retxs.begin(); + while (next_ue_harq_retx != ongoing_ues_ack_retxs.end()) { // TODO: Add a stopping condition in this loop, so next_ue won't iterate over all the UEs and HARQ-processes if // there are no resources. - // Check if UE exists. - if (not ues.contains(next_ue_harq_retx->ue_index)) { - next_ue_harq_retx = ongoing_ues_ack_retx.erase(next_ue_harq_retx); - continue; - } auto& u = *ues.find(next_ue_harq_retx->ue_index); auto* h_dl = next_ue_harq_retx->get_harq_process(); - if (h_dl->last_alloc_params().is_fallback and h_dl->has_pending_retx()) { + if (h_dl->has_pending_retx()) { + optional most_recent_tx = get_most_recent_slot_tx(u.ue_index); if (next_ue_harq_retx->is_srb0) { - schedule_srb(res_alloc, u, true, h_dl); + schedule_srb(res_alloc, u, true, h_dl, most_recent_tx); } else { // TODO: Change this into SRB1_retx. - schedule_srb(res_alloc, u, true, h_dl); + schedule_srb(res_alloc, u, true, h_dl, most_recent_tx); } } ++next_ue_harq_retx; @@ -75,19 +71,20 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) // Schedule SRB0 messages. auto next_ue = pending_ues.begin(); while (next_ue != pending_ues.end()) { - // Check if UE exists. - if (not ues.contains(next_ue->ue_index)) { - next_ue = pending_ues.erase(next_ue); + if (not next_ue->is_srb0) { continue; + ++next_ue; } - if (not next_ue->is_srb0) { + // 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; - ++next_ue; } - auto& u = ues[next_ue->ue_index]; - if (u.has_pending_dl_newtx_bytes(LCID_SRB0) and schedule_srb(res_alloc, u, true)) { + auto& u = ues[next_ue->ue_index]; + optional most_recent_tx = 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)) { next_ue = pending_ues.erase(next_ue); } else { ++next_ue; @@ -97,19 +94,20 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) // Keep SRB1 with lower priority than SRB0. next_ue = pending_ues.begin(); while (next_ue != pending_ues.end()) { - // Check if UE exists. - if (not ues.contains(next_ue->ue_index)) { - next_ue = pending_ues.erase(next_ue); + if (next_ue->is_srb0) { continue; + ++next_ue; } - if (next_ue->is_srb0) { + // 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; - ++next_ue; } - auto& u = ues[next_ue->ue_index]; - if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false)) { + auto& u = ues[next_ue->ue_index]; + optional most_recent_tx = get_most_recent_slot_tx(u.ue_index); + if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx)) { next_ue = pending_ues.erase(next_ue); } else { ++next_ue; @@ -119,53 +117,86 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) { - is_srb0 ? pending_ues.push_back({ue_index, true}) : pending_ues.push_back({ue_index, false}); + is_srb0 ? pending_ues.push_back({ue_index, is_srb0}) : pending_ues.push_back({ue_index, is_srb0}); } -static unsigned get_next_srb_slot(const cell_configuration& cell_cfg, slot_point sl_tx) +static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_point sl_tx) { if (not cell_cfg.is_tdd()) { // In FDD, we advance by 1 slot. - return 1U; + return sl_tx + 1U; } - const auto& tdd_cfg = cell_cfg.tdd_cfg_common.value(); - const unsigned tdd_period_nof_slots = nof_slots_per_tdd_period(tdd_cfg); - optional next_dl_slot_offset = - find_next_tdd_full_dl_slot(cell_cfg.tdd_cfg_common.value(), sl_tx.slot_index() % tdd_period_nof_slots); - if (not next_dl_slot_offset.has_value()) { - // This returns the offset from the current slot to the next DL slot within the next TDD period. - next_dl_slot_offset = tdd_period_nof_slots - sl_tx.slot_index() % tdd_period_nof_slots; + const auto& tdd_cfg = cell_cfg.tdd_cfg_common.value(); + const unsigned tdd_period_nof_slots = nof_slots_per_tdd_period(tdd_cfg); + + // Advance the slot by 1 and then search the next slot (including the just incremented next_candidate_slot) what is + // the next available DL slot. + slot_point next_candidate_slot = sl_tx + 1U; + optional offset_to_next_dl_slot = find_next_tdd_full_dl_slot( + cell_cfg.tdd_cfg_common.value(), next_candidate_slot.slot_index() % tdd_period_nof_slots); + if (offset_to_next_dl_slot.has_value()) { + return next_candidate_slot + offset_to_next_dl_slot.value(); } - return next_dl_slot_offset.value(); + + // If offset_to_next_dl_slot has no value, it means that there no more DL slots within the period; advance to the next + // TDD period. + const unsigned offset_to_first_slot_next_tdd_period = + tdd_period_nof_slots - next_candidate_slot.slot_index() % tdd_period_nof_slots; + + return next_candidate_slot + offset_to_first_slot_next_tdd_period; } bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, ue& u, bool is_srb0, - dl_harq_process* h_dl_retx) + dl_harq_process* h_dl_retx, + optional starting_sl) { const auto& bwp_cfg_common = cell_cfg.dl_cfg_common.init_dl_bwp; // Search valid PDSCH time domain resource. - unsigned offset = 0; - for (unsigned offset_cnt = 0; offset_cnt != max_dl_slots_ahead_sched; - ++offset_cnt, offset = get_next_srb_slot(cell_cfg, res_alloc[0 + offset].slot)) { + const bool is_retx = h_dl_retx != nullptr; + + // \rer sched_ref_slot is the slot that we take as reference for the scheduler, which is processed when calling the + // slot_indication(). + // \ref starting_sl 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. + // TODO: Make this compatible with k0 > 0. + slot_point sched_ref_slot = res_alloc[0].slot; + + if (starting_sl.has_value()) { + srsran_sanity_check(starting_sl.value() >= sched_ref_slot, + "The starting slot can't be before the scheduler reference slot"); + if (sched_ref_slot + max_dl_slots_ahead_sched < starting_sl.value()) { + return false; + } + } else { + starting_sl = sched_ref_slot; + } + + // We keep track of the number of scheduling attempts for the given UE. + unsigned sched_attempts_cnt = 0; + slot_point next_slot = starting_sl.value(); + + while (next_slot <= sched_ref_slot + max_dl_slots_ahead_sched) { + unsigned 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) { - const pdsch_time_domain_resource_allocation& pdsch_td_cfg = get_pdsch_td_cfg(time_res_idx); - - if (h_dl_retx != nullptr and h_dl_retx->last_alloc_params().nof_symbols != pdsch_td_cfg.symbols.length()) { - continue; + if (sched_attempts_cnt >= max_sched_attempts_per_ue) { + return false; } - // Fetch PDSCH resource grid allocators. - const cell_slot_resource_allocator& pdsch_alloc = res_alloc[offset + pdsch_td_cfg.k0]; + 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 with CSI-RS. + // We do not support multiplexing of PDSCH for SRB0 and SRB1 when in fallback with CSI-RS. if (not pdsch_alloc.result.dl.csi_rs.empty()) { continue; } @@ -180,25 +211,38 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, continue; } - if (h_dl_retx != nullptr) { - dl_harq_process* ret_outcome = is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset, h_dl_retx) - : schedule_srb1(u, res_alloc, time_res_idx, offset, h_dl_retx); - return ret_outcome != nullptr; - } else { - dl_harq_process* candidate_h_dl = is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset) - : schedule_srb1(u, res_alloc, time_res_idx, offset); - if (candidate_h_dl != nullptr) { - cache_ue_srb_tx(u.ue_index, candidate_h_dl, /* is_srb0*/ true); - return true; - } + 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; + } + + dl_harq_process* candidate_h_dl = + is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx) + : schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx); + + if (not is_retx and candidate_h_dl != nullptr) { + store_harq_tx(u.ue_index, candidate_h_dl, 0); } + return candidate_h_dl != nullptr; + + ++sched_attempts_cnt; } + + next_slot = get_next_srb_slot(cell_cfg, next_slot); } // No resource found in UE's carriers and Search spaces. slot_point pdcch_slot = res_alloc[0].slot; - logger.debug("rnti={}: Not enough PDSCH space for SRB0 message found in any of the slots:[{},{}).", + logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{}).", u.crnti, + is_srb0 ? "SRB0" : "SRB1", pdcch_slot, pdcch_slot + max_dl_slots_ahead_sched); return false; @@ -214,17 +258,6 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, 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[slot_offset]; - cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + 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 nullptr; - } - 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; @@ -236,37 +269,34 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, return nullptr; } - sch_prbs_tbs prbs_tbs{}; - sch_mcs_index mcs_idx = 0; - - prb_bitmap used_crbs = pdsch_alloc.dl_res_grid.used_crbs( + 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); + sch_prbs_tbs prbs_tbs{}; + sch_mcs_index mcs_idx = 0; if (is_retx) { - // See 38.214, table 5.1.3.1-1: MCS index table 1 for PDSCH. - mcs_idx = h_dl->last_alloc_params().tb[0]->mcs; - // 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. + // 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 { - // Find available symbol x RB resources. + // 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); 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. - // 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. + // Try to find least MCS to fit SRB0 message. 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. + // 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()), @@ -287,7 +317,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, } if (mcs_idx > expert_cfg.max_msg4_mcs) { - logger.debug("rnti={}: MCS index chosen ({}) for SRB0 exceeds maximum allowed MCS index ({}).", + 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); @@ -305,7 +336,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, } // Allocate PDCCH resources. - pdcch_dl_information* pdcch = + 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); @@ -361,18 +393,6 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, 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[slot_offset]; - slot_point pdcch_slot = pdcch_alloc.slot; - cell_slot_resource_allocator& pdsch_alloc = res_alloc[slot_offset + 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 nullptr; - } - const bool is_retx = h_dl_retx != nullptr; // Search for empty HARQ. @@ -398,7 +418,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, // 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. - prb_bitmap used_crbs = pdsch_alloc.dl_res_grid.used_crbs( + 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); @@ -432,8 +453,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, // [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(pdcch_slot + pdsch_td_cfg.k0) and mcs_prbs_estimate.n_prbs == 1; + 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; @@ -467,7 +487,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, } // Allocate PDCCH resources. - pdcch_dl_information* pdcch = + 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); @@ -527,10 +548,11 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, unsigned tbs_bytes, bool is_retx) { - static constexpr uint8_t srb0_dai = 0; // Allocate DL HARQ. + // NOTE: We do not multiplex the SRBO PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. if (not is_retx) { - const bool is_fallback = true; + const bool is_fallback = true; + static constexpr uint8_t srb0_dai = 0; h_dl.new_tx(pdsch_slot, k1, expert_cfg.max_nof_harq_retxs, @@ -539,7 +561,6 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, u.get_pcell().channel_state_manager().get_nof_dl_layers(), is_fallback); } else { - // We do not multiplex the SRBO PUCCH with existing PUCCH HARQs. const unsigned harq_bit_idx = 0U; h_dl.new_retx(pdsch_slot, k1, harq_bit_idx); } @@ -563,11 +584,11 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, 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); + msg.pdsch_cfg, pdsch_params, tbs_bytes, u.crnti, cell_cfg, pdcch.dci.tc_rnti_f1_0, ue_grant_crbs, not is_retx); if (not is_retx) { // Set MAC logical channels to schedule in this PDU. - u.build_dl_srb0_srb1_transport_block_info( + u.build_dl_fallback_transport_block_info( msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB0); } @@ -589,8 +610,9 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, unsigned tbs_bytes, bool is_retx) { - static constexpr uint8_t srb1_dai = 0; // Allocate DL HARQ. + // NOTE: We do not multiplex the SRBO PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. + static constexpr uint8_t srb1_dai = 0; if (not is_retx) { const bool is_fallback = true; h_dl.new_tx(pdsch_slot, @@ -598,10 +620,9 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, expert_cfg.max_nof_harq_retxs, srb1_dai, u.get_pcell().channel_state_manager().get_wideband_cqi(), - 1U, + pdsch_params.nof_layers, is_fallback); } else { - // We do not multiplex the SRBO PUCCH with existing PUCCH HARQs. const unsigned harq_bit_idx = 0U; h_dl.new_retx(pdsch_slot, k1, harq_bit_idx); } @@ -649,12 +670,18 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, switch (pdcch.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, true); + 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_srb0_srb1_transport_block_info( + u.build_dl_fallback_transport_block_info( msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB1); } break; @@ -681,10 +708,6 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, } } - // Set MAC logical channels to schedule in this PDU. - u.build_dl_srb0_srb1_transport_block_info( - msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB1); - // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); } @@ -694,32 +717,51 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; } -void ue_srb0_scheduler::cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) +optional ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const { - auto it_ue = std::find_if( - ongoing_ues_ack_retx.begin(), ongoing_ues_ack_retx.end(), [ue_index, h_dl](const ack_and_retx_tracker& tracker) { - return tracker.match_ue_harq(ue_index, h_dl); - }); + optional most_recent_tx; + for (const auto& ue_proc : ongoing_ues_ack_retxs) { + if (ue_proc.ue_index == ue_idx) { + slot_point h_dl_slot_tx = ue_proc.get_harq_process()->slot_tx(); + if (most_recent_tx.has_value() and h_dl_slot_tx > most_recent_tx.value()) { + most_recent_tx = ue_proc.get_harq_process()->slot_tx(); + } else { + most_recent_tx.emplace(ue_proc.get_harq_process()->slot_tx()); + } + } + } + return most_recent_tx; +} - srsran_assert(it_ue == ongoing_ues_ack_retx.end(), "This UE and HARQ process were already in the list"); - ongoing_ues_ack_retx.emplace_back(ue_index, h_dl, is_srb0, ues); +void ue_srb0_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) +{ + srsran_assert(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_srb0_scheduler::slot_indication() +void ue_srb0_scheduler::update_ongoing_ue_retxs() { - if (ongoing_ues_ack_retx.empty()) { + if (ongoing_ues_ack_retxs.empty()) { return; } - auto it_ue_harq = ongoing_ues_ack_retx.begin(); - while (it_ue_harq != ongoing_ues_ack_retx.end()) { + // Only remove the {UE, HARQ-process} elements that have been retransmitted and positively acked. The rest of the + // elements are potential candidate for retransmissions. + auto it_ue_harq = ongoing_ues_ack_retxs.begin(); + while (it_ue_harq != ongoing_ues_ack_retxs.end()) { if (not ues.contains(it_ue_harq->ue_index)) { - it_ue_harq = ongoing_ues_ack_retx.erase(it_ue_harq); + it_ue_harq = ongoing_ues_ack_retxs.erase(it_ue_harq); continue; } dl_harq_process& h_dl = *it_ue_harq->get_harq_process(); if (h_dl.empty()) { - it_ue_harq = ongoing_ues_ack_retx.erase(it_ue_harq); + it_ue_harq = ongoing_ues_ack_retxs.erase(it_ue_harq); continue; } ++it_ue_harq; diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index 336fb896fe..b489a591dc 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -40,17 +40,21 @@ class ue_srb0_scheduler private: /// Erase the UEs' HARQ processes that have been acked from the SRB scheduler cache. - void slot_indication(); + void update_ongoing_ue_retxs(); /// \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 = nullptr); + bool schedule_srb(cell_resource_allocator& res_alloc, + ue& u, + bool is_srb0, + dl_harq_process* h_dl_retx, + optional starting_sl); /// \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, - dl_harq_process* h_dl_retx = nullptr); + 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, @@ -125,11 +129,15 @@ class ue_srb0_scheduler ue_repository& ues; }; - void cache_ue_srb_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); + void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); + + 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; - const unsigned max_dl_slots_ahead_sched = 5U; + // TODO: Find proper values for these 2 parameters. + const unsigned max_dl_slots_ahead_sched = 10U; + const unsigned max_sched_attempts_per_ue = 7U; pdcch_resource_allocator& pdcch_sch; pucch_allocator& pucch_alloc; ue_repository& ues; @@ -143,7 +151,7 @@ class ue_srb0_scheduler coreset_configuration cs_cfg; /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. - std::list ongoing_ues_ack_retx; + std::list ongoing_ues_ack_retxs; srslog::basic_logger& logger; }; From 8db420188b524ce0e7844732b50ebf6bc70d2106 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 4 Mar 2024 12:06:14 +0100 Subject: [PATCH 61/77] sched: fix srb0 sched unittests Signed-off-by: Carlo Galiotto --- .../ue_scheduling/ue_srb0_scheduler.cpp | 29 ++++++++++--------- .../ue_scheduling/ue_srb0_scheduler.h | 11 +++---- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 62dd888bc2..720b754a9d 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -72,8 +72,8 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) auto next_ue = pending_ues.begin(); while (next_ue != pending_ues.end()) { if (not next_ue->is_srb0) { - continue; ++next_ue; + continue; } // The UE might have been deleted in the meantime, check if still exists. @@ -95,8 +95,8 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) next_ue = pending_ues.begin(); while (next_ue != pending_ues.end()) { if (next_ue->is_srb0) { - continue; ++next_ue; + continue; } // The UE might have been deleted in the meantime, check if still exists. @@ -165,15 +165,14 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, // TODO: Make this compatible with k0 > 0. slot_point sched_ref_slot = res_alloc[0].slot; - if (starting_sl.has_value()) { - srsran_sanity_check(starting_sl.value() >= sched_ref_slot, - "The starting slot can't be before the scheduler reference slot"); - if (sched_ref_slot + max_dl_slots_ahead_sched < starting_sl.value()) { - return false; - } - } else { - starting_sl = sched_ref_slot; + if (not cell_cfg.is_dl_enabled(sched_ref_slot)) { + return false; + } + + if (starting_sl.has_value() and sched_ref_slot + max_dl_slots_ahead_sched < starting_sl.value()) { + return false; } + starting_sl = sched_ref_slot; // We keep track of the number of scheduling attempts for the given UE. unsigned sched_attempts_cnt = 0; @@ -521,6 +520,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, pdsch_alloc.slot, *h_dl, *pdcch, + dci_type, pdsch_alloc.result.dl.ue_grants.emplace_back(), pucch_res_indicator.value(), pdsch_time_res, @@ -589,7 +589,7 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, if (not is_retx) { // Set MAC logical channels to schedule in this PDU. u.build_dl_fallback_transport_block_info( - msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, lcid_t::LCID_SRB0); + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, true); } // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. @@ -600,6 +600,7 @@ void ue_srb0_scheduler::fill_srb1_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, @@ -629,7 +630,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, // Fill DL PDCCH DCI. static const uint8_t msg4_rv = 0; - switch (pdcch.dci.type) { + 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, @@ -668,7 +669,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, msg.context.nof_retxs = h_dl.tb(0).nof_retxs; msg.context.olla_offset = 0; - switch (pdcch.dci.type) { + switch (dci_type) { case dci_dl_rnti_config_type::tc_rnti_f1_0: { build_pdsch_f1_0_tc_rnti(msg.pdsch_cfg, pdsch_params, @@ -682,7 +683,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, // 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, lcid_t::LCID_SRB1); + msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, false); } break; } diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index b489a591dc..32248d2294 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -81,6 +81,7 @@ class ue_srb0_scheduler 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, @@ -136,11 +137,11 @@ class ue_srb0_scheduler const scheduler_ue_expert_config& expert_cfg; const cell_configuration& cell_cfg; // TODO: Find proper values for these 2 parameters. - const unsigned max_dl_slots_ahead_sched = 10U; - const unsigned max_sched_attempts_per_ue = 7U; - pdcch_resource_allocator& pdcch_sch; - pucch_allocator& pucch_alloc; - ue_repository& ues; + const unsigned max_dl_slots_ahead_sched = 10U; + const unsigned max_sched_attempts_per_ue = 7U; + 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, From 06fb2ed6543ec06b73c67e0bc5b7bbf3496d5332 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 6 Mar 2024 18:23:46 +0100 Subject: [PATCH 62/77] sched: add unittest for head srb0 scheduling Signed-off-by: Carlo Galiotto --- lib/scheduler/support/rb_helper.cpp | 2 +- .../ue_scheduling/ue_srb0_scheduler.cpp | 48 +++--- .../ue_scheduling/ue_srb0_scheduler.h | 2 +- .../ue_scheduling/srb0_scheduler_test.cpp | 149 +++++++++++++++++- 4 files changed, 169 insertions(+), 32 deletions(-) diff --git a/lib/scheduler/support/rb_helper.cpp b/lib/scheduler/support/rb_helper.cpp index 085873a21f..121e912cb0 100644 --- a/lib/scheduler/support/rb_helper.cpp +++ b/lib/scheduler/support/rb_helper.cpp @@ -19,7 +19,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/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 720b754a9d..699f189780 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -122,28 +122,18 @@ void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_i 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()) { - // In FDD, we advance by 1 slot. - return sl_tx + 1U; - } - const auto& tdd_cfg = cell_cfg.tdd_cfg_common.value(); - const unsigned tdd_period_nof_slots = nof_slots_per_tdd_period(tdd_cfg); - - // Advance the slot by 1 and then search the next slot (including the just incremented next_candidate_slot) what is - // the next available DL slot. - slot_point next_candidate_slot = sl_tx + 1U; - optional offset_to_next_dl_slot = find_next_tdd_full_dl_slot( - cell_cfg.tdd_cfg_common.value(), next_candidate_slot.slot_index() % tdd_period_nof_slots); - if (offset_to_next_dl_slot.has_value()) { - return next_candidate_slot + offset_to_next_dl_slot.value(); + return next_candidate_slot; } - // If offset_to_next_dl_slot has no value, it means that there no more DL slots within the period; advance to the next - // TDD period. - const unsigned offset_to_first_slot_next_tdd_period = - tdd_period_nof_slots - next_candidate_slot.slot_index() % tdd_period_nof_slots; - - return next_candidate_slot + offset_to_first_slot_next_tdd_period; + // 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_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, @@ -226,10 +216,13 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx) : schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx); - if (not is_retx and candidate_h_dl != nullptr) { - store_harq_tx(u.ue_index, candidate_h_dl, 0); + 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; } - return candidate_h_dl != nullptr; ++sched_attempts_cnt; } @@ -269,10 +262,9 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, } 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); + 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; @@ -285,8 +277,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, // 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); - const unsigned starting_crb_idx = 0; - crb_interval unused_crbs = rb_helper::find_next_empty_interval(used_crbs, starting_crb_idx, used_crbs.size()); + 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) { diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index 32248d2294..369bae41d9 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -138,7 +138,7 @@ class ue_srb0_scheduler const cell_configuration& cell_cfg; // TODO: Find proper values for these 2 parameters. const unsigned max_dl_slots_ahead_sched = 10U; - const unsigned max_sched_attempts_per_ue = 7U; + const unsigned max_sched_attempts_per_ue = 10U; pdcch_resource_allocator& pdcch_sch; pucch_allocator& pucch_alloc; ue_repository& ues; diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index 9cb4cbe4d2..3e8e5fa285 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -178,7 +178,7 @@ class base_srb0_scheduler_tester void run_slot() { - current_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()); @@ -186,6 +186,7 @@ class base_srb0_scheduler_tester bench->res_grid.slot_indication(current_slot); bench->pdcch_sch.slot_indication(current_slot); + bench->pucch_alloc.slot_indication(current_slot); bench->srb0_sched.run_slot(bench->res_grid); @@ -281,7 +282,9 @@ class base_srb0_scheduler_tester return bench->ue_db[ue_idx].pending_dl_srb0_or_srb1_newtx_bytes(true); } - const ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } + const ue& get_ue(du_ue_index_t ue_idx) const { return bench->ue_db[ue_idx]; } + + ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } }; // Parameters to be passed to test. @@ -508,6 +511,148 @@ INSTANTIATE_TEST_SUITE_P(srb0_scheduler, testing::Values(srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::FDD}, srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::TDD})); +class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, + public ::testing::TestWithParam +{ +protected: + const unsigned MAX_NOF_SLOTS_GRID_IS_BUSY = 4; + const unsigned MAX_UES = 4; + const unsigned MAX_TEST_RUN_SLOTS = 2100; + const unsigned MAC_SRB0_SDU_SIZE = 128; + + srb0_scheduler_head_scheduling() : base_srb0_scheduler_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. + unsigned generate_srb0_traffic_slot() const { 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}; + for (auto k1 : dci_1_0_k1_values) { + if (cfg.is_ul_enabled(pdsch_slot + k1)) { + return true; + } + } + return false; + }; + + // Make sure the final slot for the SRB0 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))) { + sched_slot++; + } + + return sched_slot; + } +}; + +TEST_P(srb0_scheduler_head_scheduling, test_allocation_in_appropriate_slots_in_tdd) +{ + // In this test, we check if the SRB0 allocation can schedule ahead with respect to the reference slot, which is given + // by the slot_indication in the scheduler. + // Every time there is we generate SRB0 buffer bytes, we set the resource grid as occupied for a given number of + // slots. This forces the scheduler to try the allocation in next slot(s). + + 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_UES * 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); + + 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(srb0_scheduler, + srb0_scheduler_head_scheduling, + 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); From ab8fcd8b00d7416655592e90b67cf60d97151832 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 7 Mar 2024 16:25:26 +0100 Subject: [PATCH 63/77] sched: handle ahead srb0 scheduling and csi-rs Signed-off-by: Carlo Galiotto --- lib/scheduler/CMakeLists.txt | 4 +- lib/scheduler/policy/scheduler_time_rr.cpp | 5 +++ lib/scheduler/support/csi_rs_helper.cpp | 40 +++++++++++++++++++ lib/scheduler/support/csi_rs_helpers.h | 22 ++++++++++ .../support/pdsch/pdsch_resource_allocation.h | 4 +- .../dl_logical_channel_manager.cpp | 24 ++++++----- .../dl_logical_channel_manager.h | 14 ++++++- lib/scheduler/ue_scheduling/ue.cpp | 9 +---- lib/scheduler/ue_scheduling/ue.h | 9 ++--- .../ue_scheduling/ue_srb0_scheduler.cpp | 9 +++-- .../ue_scheduling/srb0_scheduler_test.cpp | 32 +++++++++------ 11 files changed, 127 insertions(+), 45 deletions(-) create mode 100644 lib/scheduler/support/csi_rs_helper.cpp create mode 100644 lib/scheduler/support/csi_rs_helpers.h diff --git a/lib/scheduler/CMakeLists.txt b/lib/scheduler/CMakeLists.txt index 959531b4df..ad567fc258 100644 --- a/lib/scheduler/CMakeLists.txt +++ b/lib/scheduler/CMakeLists.txt @@ -39,7 +39,9 @@ set(SOURCES support/csi_report_helpers.cpp cell_scheduler.cpp scheduler_factory.cpp - scheduler_impl.cpp) + scheduler_impl.cpp + support/csi_rs_helpers.h + support/csi_rs_helper.cpp) add_library(srsran_sched STATIC ${SOURCES} $ diff --git a/lib/scheduler/policy/scheduler_time_rr.cpp b/lib/scheduler/policy/scheduler_time_rr.cpp index e3bfdeab6f..28246fafe6 100644 --- a/lib/scheduler/policy/scheduler_time_rr.cpp +++ b/lib/scheduler/policy/scheduler_time_rr.cpp @@ -228,6 +228,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 SRB0 scheduler. + continue; + } + // 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/support/csi_rs_helper.cpp b/lib/scheduler/support/csi_rs_helper.cpp new file mode 100644 index 0000000000..53b5caf884 --- /dev/null +++ b/lib/scheduler/support/csi_rs_helper.cpp @@ -0,0 +1,40 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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) { + const zp_csi_rs_resource& zp_csi = cell_cfg.zp_csi_rs_list[i]; + 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 (unsigned i = 0; i != cell_cfg.nzp_csi_rs_list.size(); ++i) { + const nzp_csi_rs_resource& nzp_csi = cell_cfg.nzp_csi_rs_list[i]; + 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..94555dc611 --- /dev/null +++ b/lib/scheduler/support/csi_rs_helpers.h @@ -0,0 +1,22 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "../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/pdsch/pdsch_resource_allocation.h b/lib/scheduler/support/pdsch/pdsch_resource_allocation.h index 4cada44d03..121646174d 100644 --- a/lib/scheduler/support/pdsch/pdsch_resource_allocation.h +++ b/lib/scheduler/support/pdsch/pdsch_resource_allocation.h @@ -52,8 +52,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 init_dl_bwp Initial DL BWP configuration. -/// \param ss_id SearchSpace ID. +/// \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/ue_scheduling/dl_logical_channel_manager.cpp b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp index 6ef931bb00..33f975066c 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.cpp @@ -42,13 +42,13 @@ unsigned dl_logical_channel_manager::allocate_mac_sdu(dl_msg_lc_info& subpdu, un subpdu.lcid = lcid_dl_sch_t::MIN_RESERVED; subpdu.sched_bytes = 0; - lcid = lcid == lcid_t::INVALID_LCID ? get_max_prio_lcid() : 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 @@ -64,6 +64,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; @@ -78,7 +80,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); @@ -135,7 +137,7 @@ srsran::allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_manager& l { 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; @@ -144,10 +146,10 @@ srsran::allocate_mac_sdus(dl_msg_tb_info& tb_info, dl_logical_channel_manager& l 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; } @@ -165,10 +167,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; @@ -210,10 +212,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 20c05470a5..d15267a2e8 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h @@ -32,13 +32,21 @@ 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; + } /// \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 + { + srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); + return channels[lcid].active; + } /// \brief Checks whether the UE has pending data. /// \remark Excludes data for SRB0. @@ -95,12 +103,14 @@ class dl_logical_channel_manager /// \brief Last DL buffer status for given LCID (MAC subheader included). unsigned pending_bytes(lcid_t lcid) const { + srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); return is_active(lcid) ? get_mac_sdu_required_bytes(channels[lcid].buf_st) : 0; } /// \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; } diff --git a/lib/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index 9042599705..debb673e1f 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -108,9 +108,9 @@ 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_or_srb1_newtx_bytes(bool is_srb0) const @@ -124,11 +124,6 @@ unsigned ue::pending_dl_srb0_or_srb1_newtx_bytes(bool is_srb0) const return pending_bytes; } -unsigned ue::pending_dl_srb1_newtx_bytes() const -{ - return dl_lc_ch_mgr.pending_bytes(LCID_SRB1); -} - unsigned ue::pending_ul_newtx_bytes() const { constexpr static unsigned SR_GRANT_BYTES = 512; diff --git a/lib/scheduler/ue_scheduling/ue.h b/lib/scheduler/ue_scheduling/ue.h index f4735065c5..621bd95b5a 100644 --- a/lib/scheduler/ue_scheduling/ue.h +++ b/lib/scheduler/ue_scheduling/ue.h @@ -129,17 +129,14 @@ 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. + 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_or_srb1_newtx_bytes(bool is_srb0) 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_srb1_newtx_bytes() 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. unsigned pending_ul_newtx_bytes() const; diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 699f189780..6864cc3803 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -9,6 +9,7 @@ */ #include "ue_srb0_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" @@ -147,7 +148,7 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, const bool is_retx = h_dl_retx != nullptr; - // \rer sched_ref_slot is the slot that we take as reference for the scheduler, which is processed when calling the + // \ref sched_ref_slot is the slot that we take as reference for the scheduler, which is processed when calling the // slot_indication(). // \ref starting_sl 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 @@ -186,7 +187,9 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, } // We do not support multiplexing of PDSCH for SRB0 and SRB1 when in fallback with CSI-RS. - if (not pdsch_alloc.result.dl.csi_rs.empty()) { + 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; } @@ -433,7 +436,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, // 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_srb1_newtx_bytes(); + : 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) { diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index 3e8e5fa285..1ba30b3e9f 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -8,10 +8,12 @@ * */ +#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_srb0_scheduler.h" @@ -89,6 +91,7 @@ struct test_bench { ue_repository ue_db; ue_cell_grid_allocator ue_alloc; ue_srb0_scheduler srb0_sched; + csi_rs_scheduler csi_rs_sched; explicit test_bench(const scheduler_expert_config& sched_cfg_, const cell_config_builder_params& builder_params_, @@ -97,7 +100,8 @@ struct test_bench { 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) + srb0_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); } @@ -176,7 +180,7 @@ class base_srb0_scheduler_tester bench->pucch_alloc.slot_indication(current_slot); } - void run_slot() + void run_slot(bool disabled_csi_rs = false) { ++current_slot; @@ -188,6 +192,10 @@ class base_srb0_scheduler_tester bench->pdcch_sch.slot_indication(current_slot); bench->pucch_alloc.slot_indication(current_slot); + if (not disabled_csi_rs) { + bench->csi_rs_sched.run_slot(bench->res_grid[0]); + } + bench->srb0_sched.run_slot(bench->res_grid); result_logger.on_scheduler_result(bench->res_grid[0].result); @@ -196,7 +204,7 @@ class base_srb0_scheduler_tester test_scheduler_result_consistency(bench->cell_cfg, bench->res_grid); } - scheduler_expert_config create_expert_config(sch_mcs_index max_msg4_mcs_index) const + 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; @@ -489,7 +497,7 @@ TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) 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(); + run_slot(true); // 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 @@ -529,7 +537,7 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, } // Helper that generates the slot for the SRB0 buffer update. - unsigned generate_srb0_traffic_slot() const { return test_rgen::uniform_int(20U, 30U); } + 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 @@ -565,16 +573,14 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, 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}; - for (auto k1 : dci_1_0_k1_values) { - if (cfg.is_ul_enabled(pdsch_slot + k1)) { - return true; - } - } - return false; + 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 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))) { + 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++; } @@ -582,7 +588,7 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, } }; -TEST_P(srb0_scheduler_head_scheduling, test_allocation_in_appropriate_slots_in_tdd) +TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation_1_ue) { // In this test, we check if the SRB0 allocation can schedule ahead with respect to the reference slot, which is given // by the slot_indication in the scheduler. From 8c8df84c8758bbdea4b7bcbd8070441c1348c002 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 7 Mar 2024 16:29:04 +0100 Subject: [PATCH 64/77] sched: add forgotten comment Signed-off-by: Carlo Galiotto --- lib/scheduler/ue_scheduling/dl_logical_channel_manager.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h index d15267a2e8..d8387cdd48 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h @@ -165,6 +165,8 @@ 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, From d57c6984d94547d68e52e856f5a27f339118ee07 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 8 Mar 2024 14:33:54 +0100 Subject: [PATCH 65/77] sched: add unittest for srb0 retransmissions Signed-off-by: Carlo Galiotto --- include/srsran/support/test_utils.h | 2 + lib/scheduler/ue_scheduling/ue.cpp | 2 +- .../ue_scheduling/srb0_scheduler_test.cpp | 211 ++++++++++++++++-- 3 files changed, 201 insertions(+), 14 deletions(-) diff --git a/include/srsran/support/test_utils.h b/include/srsran/support/test_utils.h index 6c8ed9add8..a85d06c14c 100644 --- a/include/srsran/support/test_utils.h +++ b/include/srsran/support/test_utils.h @@ -271,6 +271,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/scheduler/ue_scheduling/ue.cpp b/lib/scheduler/ue_scheduling/ue.cpp index debb673e1f..2f042e4b1e 100644 --- a/lib/scheduler/ue_scheduling/ue.cpp +++ b/lib/scheduler/ue_scheduling/ue.cpp @@ -110,7 +110,7 @@ void ue::handle_reconfiguration_request(const ue_reconf_command& cmd) unsigned ue::pending_dl_newtx_bytes(lcid_t lcid) const { - return lcid == INVALID_LCID ? dl_lc_ch_mgr.pending_bytes(lcid) : 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_or_srb1_newtx_bytes(bool is_srb0) const diff --git a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index 1ba30b3e9f..b66794694c 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -275,14 +275,15 @@ class base_srb0_scheduler_tester return bench->add_ue(ue_create_req); } - void push_buffer_state_to_dl_ue(du_ue_index_t ue_idx, unsigned buffer_size) + 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, LCID_SRB0, buffer_size}; + 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->srb0_sched.handle_dl_buffer_state_indication_srb(ue_idx, true); + bench->srb0_sched.handle_dl_buffer_state_indication_srb(ue_idx, is_srb0); } unsigned get_pending_bytes(du_ue_index_t ue_idx) @@ -301,6 +302,12 @@ struct srb0_test_params { duplex_mode duplx_mode; }; +// Parameters to be passed to test. +struct fallback_sched_test_params { + bool is_srb0; + duplex_mode duplx_mode; +}; + class srb0_scheduler_tester : public base_srb0_scheduler_tester, public ::testing::TestWithParam { protected: @@ -520,11 +527,10 @@ INSTANTIATE_TEST_SUITE_P(srb0_scheduler, srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::TDD})); class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, - public ::testing::TestWithParam + public ::testing::TestWithParam { protected: const unsigned MAX_NOF_SLOTS_GRID_IS_BUSY = 4; - const unsigned MAX_UES = 4; const unsigned MAX_TEST_RUN_SLOTS = 2100; const unsigned MAC_SRB0_SDU_SIZE = 128; @@ -590,10 +596,10 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation_1_ue) { - // In this test, we check if the SRB0 allocation can schedule ahead with respect to the reference slot, which is given - // by the slot_indication in the scheduler. - // Every time there is we generate SRB0 buffer bytes, we set the resource grid as occupied for a given number of - // slots. This forces the scheduler to try the allocation in next slot(s). + // 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 there is we generate SRB0 buffer bytes, we set the + // resource grid as occupied for a given number of slots. This forces the scheduler to try the allocation in next + // slot(s). unsigned du_idx = 0; add_ue(to_rnti(0x4601 + du_idx), to_du_ue_index(du_idx)); @@ -606,7 +612,7 @@ TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation 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_UES * MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { + for (unsigned idx = 1; idx < MAX_TEST_RUN_SLOTS * (1U << current_slot.numerology()); idx++) { run_slot(); if (current_slot != check_alloc_slot) { @@ -621,7 +627,7 @@ TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation // 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); + 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}, @@ -656,8 +662,187 @@ TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation INSTANTIATE_TEST_SUITE_P(srb0_scheduler, srb0_scheduler_head_scheduling, - testing::Values(srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::FDD}, - srb0_test_params{.k0 = 0, .duplx_mode = duplex_mode::TDD})); + 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 srb0_scheduler_retx : public base_srb0_scheduler_tester, + public ::testing::TestWithParam +{ +protected: + srb0_scheduler_retx() : base_srb0_scheduler_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_, srb0_scheduler_retx* parent_) : + cell_cfg(cell_cfg_), test_ue(test_ue_), parent(parent_) + { + slot_update_srb_traffic = slot_point{to_numerology_value(cell_cfg_.dl_cfg_common.init_dl_bwp.generic_params.scs), + test_rgen::uniform_int(20U, 20U)}; + 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) { + ack_outcome = test_rgen::bernoulli(0.5); + 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() + slot_point{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), + test_rgen::uniform_int(1U, 20U)}; + 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, {}); + } + } + + 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; + srb0_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 = 32; + const unsigned MAX_TEST_RUN_SLOTS = 2100; + const unsigned MAC_SRB0_SDU_SIZE = 128; + + std::vector ues_testers; +}; + +TEST_P(srb0_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 transmission and 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(srb0_scheduler, + srb0_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})); int main(int argc, char** argv) { From 52a53223ffa0c5676799973008c919c93e38f817 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 8 Mar 2024 17:25:59 +0100 Subject: [PATCH 66/77] sched: add unittest for SRB1 segmentation Signed-off-by: Carlo Galiotto --- lib/scheduler/policy/scheduler_time_rr.cpp | 2 +- .../pucch_scheduling/pucch_allocator_impl.cpp | 8 + .../ue_scheduling/ue_srb0_scheduler.cpp | 120 ++++++++---- .../ue_scheduling/ue_srb0_scheduler.h | 19 +- .../scheduler/multiple_ue_sched_test.cpp | 8 +- .../scheduler/scheduler_retx_test.cpp | 4 +- .../test_utils/scheduler_test_suite.cpp | 6 + .../ue_scheduling/srb0_scheduler_test.cpp | 181 ++++++++++++++++-- 8 files changed, 277 insertions(+), 71 deletions(-) diff --git a/lib/scheduler/policy/scheduler_time_rr.cpp b/lib/scheduler/policy/scheduler_time_rr.cpp index 28246fafe6..8761bd9050 100644 --- a/lib/scheduler/policy/scheduler_time_rr.cpp +++ b/lib/scheduler/policy/scheduler_time_rr.cpp @@ -230,7 +230,7 @@ static alloc_outcome alloc_dl_ue(const ue& u, if (ue_cc.is_in_fallback_mode()) { // Skip allocation for UEs in fallback mode, as it is handled by the SRB0 scheduler. - continue; + 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 diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index b5e186e5fd..cba9cb9740 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -111,6 +111,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: existing grant for this UE at 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/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 6864cc3803..0d68a52595 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -34,6 +34,9 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf cs_cfg(cell_cfg.get_common_coreset(ss_cfg.get_coreset_id())), logger(srslog::fetch_basic_logger("SCHED")) { + // 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_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) @@ -58,12 +61,12 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) auto* h_dl = next_ue_harq_retx->get_harq_process(); if (h_dl->has_pending_retx()) { - optional most_recent_tx = get_most_recent_slot_tx(u.ue_index); + optional> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); if (next_ue_harq_retx->is_srb0) { - schedule_srb(res_alloc, u, true, h_dl, most_recent_tx); + schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack); } else { // TODO: Change this into SRB1_retx. - schedule_srb(res_alloc, u, true, h_dl, most_recent_tx); + schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack); } } ++next_ue_harq_retx; @@ -83,9 +86,9 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) continue; } - auto& u = ues[next_ue->ue_index]; - optional most_recent_tx = 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)) { + 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; @@ -106,10 +109,18 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) continue; } - auto& u = ues[next_ue->ue_index]; - optional most_recent_tx = get_most_recent_slot_tx(u.ue_index); - if (u.has_pending_dl_newtx_bytes(LCID_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx)) { - next_ue = pending_ues.erase(next_ue); + 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_SRB1) and schedule_srb(res_alloc, u, false, nullptr, most_recent_tx_ack)) { + if (not u.has_pending_dl_newtx_bytes(LCID_SRB1)) { + logger.debug("rnti={}: Removing UE from list, as SRB1 buffer is empty.", u.crnti); + next_ue = pending_ues.erase(next_ue); + } + // Don't increase the iterator here, as we give priority to the same UE if there left are bytes in the SRB1 + // buffer. + // NOTE: The policy we adopt in this scheduler is to schedule first the all possible grants to a given UE, + // to speed up the re-establishment and re-configuration for that UE. Only after the SRB1 buffer of the UE is + // emptied, we move on to the next UE. } else { ++next_ue; } @@ -137,11 +148,11 @@ static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_poi return next_candidate_slot; } -bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, - ue& u, - bool is_srb0, - dl_harq_process* h_dl_retx, - optional starting_sl) +bool ue_srb0_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. @@ -160,14 +171,17 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, return false; } - if (starting_sl.has_value() and sched_ref_slot + max_dl_slots_ahead_sched < starting_sl.value()) { + if (most_recent_tx_ack_slots.has_value() and + sched_ref_slot + max_dl_slots_ahead_sched < most_recent_tx_ack_slots.value().first) { return false; } - starting_sl = sched_ref_slot; // We keep track of the number of scheduling attempts for the given UE. unsigned sched_attempts_cnt = 0; - slot_point next_slot = starting_sl.value(); + slot_point next_slot = + most_recent_tx_ack_slots.has_value() and most_recent_tx_ack_slots.value().first > sched_ref_slot + ? most_recent_tx_ack_slots.value().first + : sched_ref_slot; while (next_slot <= sched_ref_slot + max_dl_slots_ahead_sched) { unsigned offset_to_sched_ref_slot = static_cast(next_slot - sched_ref_slot); @@ -215,15 +229,26 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, return false; } + 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().second) { + continue; + } + most_recent_ack_slot = most_recent_tx_ack_slots.value().second; + } + dl_harq_process* candidate_h_dl = - is_srb0 ? schedule_srb0(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx) - : schedule_srb1(u, res_alloc, time_res_idx, offset_to_sched_ref_slot, h_dl_retx); + 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); } + logger.debug( + "rnti={}: PDSCH space for SRB{} scheduled for slot:{}", u.crnti, is_srb0 ? "0" : "1", pdsch_alloc.slot); return true; } @@ -235,7 +260,7 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, // No resource found in UE's carriers and Search spaces. slot_point pdcch_slot = res_alloc[0].slot; - logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{}).", + logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{})", u.crnti, is_srb0 ? "SRB0" : "SRB1", pdcch_slot, @@ -247,6 +272,7 @@ dl_harq_process* ue_srb0_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(); @@ -306,7 +332,7 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, if (prbs_tbs.tbs_bytes < pending_bytes) { logger.debug( - "rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({}).", pending_bytes, prbs_tbs.tbs_bytes, u.crnti); + "rnti={}: SRB0 PDU size ({}) exceeds TBS calculated ({})", pending_bytes, prbs_tbs.tbs_bytes, u.crnti); return nullptr; } @@ -334,16 +360,20 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, 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); + 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 = 4; + unsigned k1 = dci_1_0_k1_values.front(); // Minimum k1 value supported is 4. - static const std::array dci_1_0_k1_values = {4, 5, 6, 7, 8}; - optional pucch_res_indicator; + 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()) { @@ -352,7 +382,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, } } if (not pucch_res_indicator.has_value()) { - logger.debug("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH."); + 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; } @@ -381,6 +412,7 @@ dl_harq_process* ue_srb0_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(); @@ -490,11 +522,14 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, } // Allocate PUCCH resources. - unsigned k1 = 4; + unsigned k1 = dci_1_0_k1_values.front(); // Minimum k1 value supported is 4. - static const std::array dci_1_0_k1_values = {4, 5, 6, 7, 8}; - optional pucch_res_indicator; + 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()) { @@ -503,7 +538,8 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, } } if (not pucch_res_indicator.has_value()) { - logger.debug("Failed to allocate PDSCH for SRB0. Cause: No space in PUCCH."); + 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; } @@ -713,20 +749,26 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; } -optional ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const +optional> ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const { - optional most_recent_tx; + 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.get_harq_process()->slot_tx(); - if (most_recent_tx.has_value() and h_dl_slot_tx > most_recent_tx.value()) { - most_recent_tx = ue_proc.get_harq_process()->slot_tx(); - } else { - most_recent_tx.emplace(ue_proc.get_harq_process()->slot_tx()); + slot_point h_dl_slot_tx = ue_proc.get_harq_process()->slot_tx(); + slot_point h_dl_slot_ack = ue_proc.get_harq_process()->slot_ack(); + if (not most_recent_tx_ack_slot.has_value()) { + most_recent_tx_ack_slot.emplace(h_dl_slot_tx, h_dl_slot_ack); + continue; + } + if (h_dl_slot_tx > most_recent_tx_ack_slot.value().first) { + most_recent_tx_ack_slot.value().first = h_dl_slot_tx; + } + if (h_dl_slot_ack > most_recent_tx_ack_slot.value().second) { + most_recent_tx_ack_slot.value().second = h_dl_slot_ack; } } } - return most_recent_tx; + return most_recent_tx_ack_slot; } void ue_srb0_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index 369bae41d9..b7feb1ba62 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -43,17 +43,18 @@ class ue_srb0_scheduler void update_ongoing_ue_retxs(); /// \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 starting_sl); + 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. @@ -61,6 +62,7 @@ class ue_srb0_scheduler 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_srb0_grant(ue& u, @@ -132,7 +134,10 @@ class ue_srb0_scheduler void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); - optional get_most_recent_slot_tx(du_ue_index_t ue_idx) const; + // If there is any pending SRB0 or SRB1 transmissions for the UE, the function returns the most recent slot with PDSCH + // for SRB0/SRB1 (first element of the pair) and the most recent slot with the corresponding PUCCH (first element of + // the pair). + 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; @@ -154,6 +159,8 @@ class ue_srb0_scheduler /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. std::list ongoing_ues_ack_retxs; + std::vector dci_1_0_k1_values; + srslog::basic_logger& logger; }; diff --git a/tests/unittests/scheduler/multiple_ue_sched_test.cpp b/tests/unittests/scheduler/multiple_ue_sched_test.cpp index 263998abb9..441786fedc 100644 --- a/tests/unittests/scheduler/multiple_ue_sched_test.cpp +++ b/tests/unittests/scheduler/multiple_ue_sched_test.cpp @@ -467,11 +467,11 @@ class scheduler_impl_tester uci_indication::uci_pdu::uci_pucch_f0_or_f1_pdu pucch_pdu{}; if (pucch.format == pucch_format::FORMAT_0) { pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_0.sr_bits) > 0; - // Auto ACK harqs. + // Auto ACK latest_harq_states. pucch_pdu.harqs.resize(pucch.format_0.harq_ack_nof_bits, mac_harq_ack_report_status::ack); } else { pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_1.sr_bits) > 0; - // Auto ACK harqs. + // Auto ACK latest_harq_states. pucch_pdu.harqs.resize(pucch.format_1.harq_ack_nof_bits, mac_harq_ack_report_status::ack); } pucch_pdu.ul_sinr = 55; @@ -482,7 +482,7 @@ class scheduler_impl_tester uci_indication::uci_pdu::uci_pucch_f2_or_f3_or_f4_pdu pucch_pdu{}; pucch_pdu.sr_info.resize(sr_nof_bits_to_uint(pucch.format_2.sr_bits)); pucch_pdu.sr_info.fill(0, sr_nof_bits_to_uint(pucch.format_2.sr_bits), true); - // Auto ACK harqs. + // Auto ACK latest_harq_states. pucch_pdu.harqs.resize(pucch.format_2.harq_ack_nof_bits, mac_harq_ack_report_status::ack); if (pucch.csi_rep_cfg.has_value()) { pucch_pdu.csi.emplace(); @@ -507,7 +507,7 @@ class scheduler_impl_tester pdu.ue_index = bench->rnti_to_du_ue_index(pdu.crnti); uci_indication::uci_pdu::uci_pusch_pdu pusch_pdu{}; - // Auto ACK harqs. + // Auto ACK latest_harq_states. if (pusch.uci->harq.has_value()) { pusch_pdu.harqs.resize(pusch.uci->harq->harq_ack_nof_bits, mac_harq_ack_report_status::ack); } diff --git a/tests/unittests/scheduler/scheduler_retx_test.cpp b/tests/unittests/scheduler/scheduler_retx_test.cpp index fa35242e16..00ae517eb6 100644 --- a/tests/unittests/scheduler/scheduler_retx_test.cpp +++ b/tests/unittests/scheduler/scheduler_retx_test.cpp @@ -166,7 +166,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)); @@ -210,7 +210,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/test_utils/scheduler_test_suite.cpp b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp index bf9cc61e1f..cbee0d5f71 100644 --- a/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp +++ b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp @@ -114,6 +114,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; @@ -156,6 +161,7 @@ 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: 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/ue_scheduling/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp index b66794694c..4fc098a9e4 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp @@ -106,7 +106,7 @@ struct test_bench { 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) + bool add_ue(const sched_ue_creation_request_message& create_req) { auto ev = cfg_mng.add_ue(create_req); if (not ev.valid()) { @@ -291,8 +291,6 @@ class base_srb0_scheduler_tester return bench->ue_db[ue_idx].pending_dl_srb0_or_srb1_newtx_bytes(true); } - const ue& get_ue(du_ue_index_t ue_idx) const { return bench->ue_db[ue_idx]; } - ue& get_ue(du_ue_index_t ue_idx) { return bench->ue_db[ue_idx]; } }; @@ -584,7 +582,7 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, }); }; - // Make sure the final slot for the SRB0 PDSCH is such that the corresponding PUCCH is in falls on a UL slot. + // 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++; @@ -594,12 +592,12 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, } }; -TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb0_allocation_1_ue) +TEST_P(srb0_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 there is we generate SRB0 buffer bytes, we set the - // resource grid as occupied for a given number of slots. This forces the scheduler to try the allocation in next - // slot(s). + // 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)); @@ -689,8 +687,7 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, ue_retx_tester(const cell_configuration& cell_cfg_, ue& test_ue_, srb0_scheduler_retx* parent_) : cell_cfg(cell_cfg_), test_ue(test_ue_), parent(parent_) { - slot_update_srb_traffic = slot_point{to_numerology_value(cell_cfg_.dl_cfg_common.init_dl_bwp.generic_params.scs), - test_rgen::uniform_int(20U, 20U)}; + slot_update_srb_traffic = generate_srb1_next_update_delay(); nof_packet_to_tx = parent->SRB_PACKETS_TOT_TX; } @@ -727,7 +724,8 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, const dl_harq_process& h_dl = test_ue.get_pcell().harqs.dl_harq(ongoing_h_id); if (h_dl.slot_ack() == sl) { - ack_outcome = test_rgen::bernoulli(0.5); + 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; @@ -759,11 +757,9 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, // ack_harq_process() function. case ue_state::reset_harq: { // Notify about SRB0 message in DL. - slot_update_srb_traffic = - sl.to_uint() + slot_point{to_numerology_value(cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.scs), - test_rgen::uniform_int(1U, 20U)}; - ongoing_h_id = INVALID_HARQ_ID; - state = ue_state::idle; + slot_update_srb_traffic = sl.to_uint() + generate_srb1_next_update_delay(); + ongoing_h_id = INVALID_HARQ_ID; + state = ue_state::idle; break; } @@ -782,6 +778,13 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, } } + 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; @@ -799,7 +802,7 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, }; const unsigned SRB_PACKETS_TOT_TX = 20; - const unsigned MAX_UES = 32; + const unsigned MAX_UES = 1; const unsigned MAX_TEST_RUN_SLOTS = 2100; const unsigned MAC_SRB0_SDU_SIZE = 128; @@ -813,9 +816,9 @@ TEST_P(srb0_scheduler_retx, test_scheduling_for_srb_retransmissions_multi_ue) // 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 transmission and unsuccessful transmissions is less + // 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) + // 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)); @@ -844,6 +847,146 @@ INSTANTIATE_TEST_SUITE_P(srb0_scheduler, 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 srb0_scheduler_srb1_segmentation : public base_srb0_scheduler_tester, + public ::testing::TestWithParam +{ +protected: + srb0_scheduler_srb1_segmentation() : base_srb0_scheduler_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_, srb0_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; + srb0_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(srb0_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(srb0_scheduler, + srb0_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); From ca25bc8b668a25d5841b52fa20aad01ba110c9fd Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 12 Mar 2024 19:42:52 +0100 Subject: [PATCH 67/77] sched: fix pucch_common unittest Signed-off-by: Carlo Galiotto --- .../uci_and_pucch/pucch_alloc_common_harq_test.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 6f307a3b22..6f546d22d2 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 @@ -253,20 +253,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()); } From fe354f377b12607fbb4c9942b868366caca971b8 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 13 Mar 2024 17:05:39 +0100 Subject: [PATCH 68/77] sched: add comments and clean code in srb0 sched Signed-off-by: Carlo Galiotto --- lib/scheduler/CMakeLists.txt | 1 - lib/scheduler/policy/scheduler_time_rr.cpp | 2 +- .../pucch_scheduling/pucch_allocator_impl.cpp | 8 +- lib/scheduler/support/csi_rs_helper.cpp | 7 +- lib/scheduler/ue_scheduling/ue.h | 7 +- .../ue_scheduling/ue_event_manager.cpp | 2 +- .../ue_scheduling/ue_srb0_scheduler.cpp | 73 ++++++++++--------- .../ue_scheduling/ue_srb0_scheduler.h | 30 +++++--- .../scheduler/multiple_ue_sched_test.cpp | 2 +- 9 files changed, 74 insertions(+), 58 deletions(-) diff --git a/lib/scheduler/CMakeLists.txt b/lib/scheduler/CMakeLists.txt index ad567fc258..608fe25cb1 100644 --- a/lib/scheduler/CMakeLists.txt +++ b/lib/scheduler/CMakeLists.txt @@ -40,7 +40,6 @@ set(SOURCES cell_scheduler.cpp scheduler_factory.cpp scheduler_impl.cpp - support/csi_rs_helpers.h support/csi_rs_helper.cpp) add_library(srsran_sched STATIC ${SOURCES} diff --git a/lib/scheduler/policy/scheduler_time_rr.cpp b/lib/scheduler/policy/scheduler_time_rr.cpp index 8761bd9050..0071073f5e 100644 --- a/lib/scheduler/policy/scheduler_time_rr.cpp +++ b/lib/scheduler/policy/scheduler_time_rr.cpp @@ -229,7 +229,7 @@ static alloc_outcome alloc_dl_ue(const ue& u, 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 SRB0 scheduler. + // Skip allocation for UEs in fallback mode, as it is handled by the SRB fallback scheduler. return alloc_outcome::skip_ue; } diff --git a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp index cba9cb9740..28417d34aa 100644 --- a/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp +++ b/lib/scheduler/pucch_scheduling/pucch_allocator_impl.cpp @@ -112,10 +112,10 @@ optional pucch_allocator_impl::alloc_common_pucch_harq_ack_ue(cell_res } if (has_common_pucch_f1_grant(tcrnti, pucch_slot_alloc.slot)) { - logger.debug( - "tc-rnti={}: PUCCH common not allocated for slot={}. Cause: existing grant for this UE at the same slot", - 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; } diff --git a/lib/scheduler/support/csi_rs_helper.cpp b/lib/scheduler/support/csi_rs_helper.cpp index 53b5caf884..74d0e52f03 100644 --- a/lib/scheduler/support/csi_rs_helper.cpp +++ b/lib/scheduler/support/csi_rs_helper.cpp @@ -20,16 +20,15 @@ bool srsran::csi_helper::is_csi_rs_slot(const cell_configuration& cell_cfg, slot return false; } - for (unsigned i = 0; i != cell_cfg.zp_csi_rs_list.size(); ++i) { - const zp_csi_rs_resource& zp_csi = cell_cfg.zp_csi_rs_list[i]; + // 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 (unsigned i = 0; i != cell_cfg.nzp_csi_rs_list.size(); ++i) { - const nzp_csi_rs_resource& nzp_csi = cell_cfg.nzp_csi_rs_list[i]; + 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; diff --git a/lib/scheduler/ue_scheduling/ue.h b/lib/scheduler/ue_scheduling/ue.h index 621bd95b5a..e4fd9b7ddc 100644 --- a/lib/scheduler/ue_scheduling/ue.h +++ b/lib/scheduler/ue_scheduling/ue.h @@ -131,10 +131,13 @@ class ue /// to derive the required transport block size for an DL grant. /// 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. + /// \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 diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index fe9698c48e..4837225f43 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -79,7 +79,7 @@ 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 or (u.get_pcell().is_in_fallback_mode() and dl_bo.lcid == LCID_SRB1)) { - // Signal SRB0 scheduler with the new SRB0 buffer state. + // Signal SRB fallback scheduler with the new SRB0/SRB1 buffer state. parent.du_cells[u.get_pcell().cell_index].srb0_sched->handle_dl_buffer_state_indication_srb( dl_bo.ue_index, dl_bo.lcid == LCID_SRB0); } diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp index 0d68a52595..a5c2b161e3 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp @@ -41,6 +41,8 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf void ue_srb0_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(); if (ues.empty()) { @@ -61,7 +63,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) auto* h_dl = next_ue_harq_retx->get_harq_process(); if (h_dl->has_pending_retx()) { - optional> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + optional most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); if (next_ue_harq_retx->is_srb0) { schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack); } else { @@ -72,7 +74,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) ++next_ue_harq_retx; } - // Schedule SRB0 messages. + // Schedule SRB0 messages before SRB1, as we prioritize SRB0 over SRB1. auto next_ue = pending_ues.begin(); while (next_ue != pending_ues.end()) { if (not next_ue->is_srb0) { @@ -86,8 +88,8 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) continue; } - auto& u = ues[next_ue->ue_index]; - optional> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + 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 { @@ -109,18 +111,20 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) continue; } - auto& u = ues[next_ue->ue_index]; - optional> most_recent_tx_ack = get_most_recent_slot_tx(u.ue_index); + 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)) { logger.debug("rnti={}: Removing UE from list, as SRB1 buffer is empty.", u.crnti); next_ue = pending_ues.erase(next_ue); } - // Don't increase the iterator here, as we give priority to the same UE if there left are bytes in the SRB1 - // buffer. - // NOTE: The policy we adopt in this scheduler is to schedule first the all possible grants to a given UE, - // to speed up the re-establishment and re-configuration for that UE. Only after the SRB1 buffer of the UE is - // emptied, we move on to the 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; } @@ -129,7 +133,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) { - is_srb0 ? pending_ues.push_back({ue_index, is_srb0}) : pending_ues.push_back({ue_index, 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) @@ -148,11 +152,11 @@ static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_poi return next_candidate_slot; } -bool ue_srb0_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) +bool ue_srb0_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. @@ -172,19 +176,19 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& } if (most_recent_tx_ack_slots.has_value() and - sched_ref_slot + max_dl_slots_ahead_sched < most_recent_tx_ack_slots.value().first) { + sched_ref_slot + max_dl_slots_ahead_sched < most_recent_tx_ack_slots.value().most_recent_ack_slot) { return false; } // We keep track of the number of scheduling attempts for the given UE. unsigned sched_attempts_cnt = 0; slot_point next_slot = - most_recent_tx_ack_slots.has_value() and most_recent_tx_ack_slots.value().first > sched_ref_slot - ? most_recent_tx_ack_slots.value().first + 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; while (next_slot <= sched_ref_slot + max_dl_slots_ahead_sched) { - unsigned offset_to_sched_ref_slot = static_cast(next_slot - sched_ref_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(); @@ -229,12 +233,15 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& 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().second) { + 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().second; + most_recent_ack_slot = most_recent_tx_ack_slots.value().most_recent_ack_slot; } dl_harq_process* candidate_h_dl = @@ -460,7 +467,6 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, 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 alloc_outcome::skip_ue; return nullptr; } @@ -472,7 +478,6 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, 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 alloc_outcome::skip_ue; return nullptr; } @@ -487,7 +492,6 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, 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 alloc_outcome::skip_ue; return nullptr; } @@ -643,7 +647,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, bool is_retx) { // Allocate DL HARQ. - // NOTE: We do not multiplex the SRBO PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. + // 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 srb1_dai = 0; if (not is_retx) { const bool is_fallback = true; @@ -749,22 +753,23 @@ const pdsch_time_domain_resource_allocation& ue_srb0_scheduler::get_pdsch_td_cfg return cell_cfg.dl_cfg_common.init_dl_bwp.pdsch_common.pdsch_td_alloc_list[pdsch_time_res_idx]; } -optional> ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const +optional ue_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const { - optional> most_recent_tx_ack_slot; + 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.get_harq_process()->slot_tx(); slot_point h_dl_slot_ack = ue_proc.get_harq_process()->slot_ack(); if (not most_recent_tx_ack_slot.has_value()) { - most_recent_tx_ack_slot.emplace(h_dl_slot_tx, h_dl_slot_ack); + 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().first) { - most_recent_tx_ack_slot.value().first = h_dl_slot_tx; + 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().second) { - most_recent_tx_ack_slot.value().second = h_dl_slot_ack; + 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; } } } diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h index b7feb1ba62..ac615cc235 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h @@ -42,12 +42,18 @@ class ue_srb0_scheduler /// 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); + 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, @@ -134,15 +140,19 @@ class ue_srb0_scheduler void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); - // If there is any pending SRB0 or SRB1 transmissions for the UE, the function returns the most recent slot with PDSCH - // for SRB0/SRB1 (first element of the pair) and the most recent slot with the corresponding PUCCH (first element of - // the pair). - optional> get_most_recent_slot_tx(du_ue_index_t ue_idx) const; + // 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. - const unsigned max_dl_slots_ahead_sched = 10U; + // 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 attempt the scheduler can do while running through the nested loops over the PDSCH time + // allocation indices and the ahead slots. This is to avoid excessive long iterations in case of a large number of + // PDSCH time allocation indices. const unsigned max_sched_attempts_per_ue = 10U; pdcch_resource_allocator& pdcch_sch; pucch_allocator& pucch_alloc; diff --git a/tests/unittests/scheduler/multiple_ue_sched_test.cpp b/tests/unittests/scheduler/multiple_ue_sched_test.cpp index 441786fedc..16f21ead61 100644 --- a/tests/unittests/scheduler/multiple_ue_sched_test.cpp +++ b/tests/unittests/scheduler/multiple_ue_sched_test.cpp @@ -507,7 +507,7 @@ class scheduler_impl_tester pdu.ue_index = bench->rnti_to_du_ue_index(pdu.crnti); uci_indication::uci_pdu::uci_pusch_pdu pusch_pdu{}; - // Auto ACK latest_harq_states. + // Auto ACK harqs. if (pusch.uci->harq.has_value()) { pusch_pdu.harqs.resize(pusch.uci->harq->harq_ack_nof_bits, mac_harq_ack_report_status::ack); } From 4e061b1a0cb4bc0a5dfcf86ab9e1aeff454a75b4 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 13 Mar 2024 17:27:24 +0100 Subject: [PATCH 69/77] sched: fix failing unittest Signed-off-by: Carlo Galiotto --- lib/scheduler/ue_scheduling/dl_logical_channel_manager.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h index d8387cdd48..c59df39858 100644 --- a/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h +++ b/lib/scheduler/ue_scheduling/dl_logical_channel_manager.h @@ -35,7 +35,7 @@ class dl_logical_channel_manager void set_status(lcid_t lcid, bool active) { srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); - channels[lcid].active; + channels[lcid].active = active; } /// \brief Update the configurations of the provided lists of bearers. @@ -44,7 +44,9 @@ class dl_logical_channel_manager /// \brief Verifies if logical channel is activated for DL. bool is_active(lcid_t lcid) const { - srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); + if (lcid > LCID_MAX_DRB) { + return false; + } return channels[lcid].active; } @@ -103,7 +105,6 @@ class dl_logical_channel_manager /// \brief Last DL buffer status for given LCID (MAC subheader included). unsigned pending_bytes(lcid_t lcid) const { - srsran_sanity_check(lcid < MAX_NOF_RB_LCIDS, "Max LCID value 32 exceeded"); return is_active(lcid) ? get_mac_sdu_required_bytes(channels[lcid].buf_st) : 0; } From 7770d808684832941c9f97ba73ab585e96ae51a8 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 14 Mar 2024 11:57:47 +0100 Subject: [PATCH 70/77] sched: change filename and replace list with vector Signed-off-by: Carlo Galiotto --- lib/scheduler/ue_scheduling/CMakeLists.txt | 2 +- .../ue_scheduling/ue_event_manager.cpp | 2 +- .../ue_scheduling/ue_event_manager.h | 7 +- ...cheduler.cpp => ue_fallback_scheduler.cpp} | 268 +++++++++--------- ...b0_scheduler.h => ue_fallback_scheduler.h} | 59 ++-- .../ue_scheduling/ue_scheduler_impl.h | 4 +- .../paging_scheduler_test.cpp | 2 +- .../scheduler/multiple_ue_sched_test.cpp | 8 +- .../test_utils/scheduler_test_suite.cpp | 11 +- .../scheduler/ue_scheduling/CMakeLists.txt | 2 +- ...r_test.cpp => fallback_scheduler_test.cpp} | 85 +++--- 11 files changed, 228 insertions(+), 222 deletions(-) rename lib/scheduler/ue_scheduling/{ue_srb0_scheduler.cpp => ue_fallback_scheduler.cpp} (75%) rename lib/scheduler/ue_scheduling/{ue_srb0_scheduler.h => ue_fallback_scheduler.h} (76%) rename tests/unittests/scheduler/ue_scheduling/{srb0_scheduler_test.cpp => fallback_scheduler_test.cpp} (93%) diff --git a/lib/scheduler/ue_scheduling/CMakeLists.txt b/lib/scheduler/ue_scheduling/CMakeLists.txt index 4cd5bfc0bc..e4363997a6 100644 --- a/lib/scheduler/ue_scheduling/CMakeLists.txt +++ b/lib/scheduler/ue_scheduling/CMakeLists.txt @@ -17,7 +17,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/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index 4837225f43..ad479a00e1 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -632,7 +632,7 @@ 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& srb0_sched, uci_scheduler_impl& uci_sched) { const du_cell_index_t cell_index = cell_res_grid.cell_index(); diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.h b/lib/scheduler/ue_scheduling/ue_event_manager.h index 15ce777064..36dc0f6799 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.h +++ b/lib/scheduler/ue_scheduling/ue_event_manager.h @@ -14,7 +14,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" @@ -36,7 +36,8 @@ 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& srb0_sched, uci_scheduler_impl& uci_sched); /// UE Add/Mod/Remove interface. void handle_ue_creation(ue_config_update_event ev) override; @@ -113,7 +114,7 @@ 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; + ue_fallback_scheduler* srb0_sched = nullptr; // Reference to the CSI and SR UCI scheduler. uci_scheduler_impl* uci_sched = nullptr; diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp similarity index 75% rename from lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp rename to lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp index a5c2b161e3..315b7a3709 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp @@ -8,7 +8,7 @@ * */ -#include "ue_srb0_scheduler.h" +#include "ue_fallback_scheduler.h" #include "../support/csi_rs_helpers.h" #include "../support/dci_builder.h" #include "../support/dmrs_helpers.h" @@ -18,11 +18,11 @@ 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_) : +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_), @@ -34,12 +34,13 @@ ue_srb0_scheduler::ue_srb0_scheduler(const scheduler_ue_expert_config& expert_cf 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_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) +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. @@ -49,34 +50,23 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) return; } - const cell_slot_resource_allocator& pdcch_alloc = res_alloc[0]; - if (not cell_cfg.is_dl_enabled(pdcch_alloc.slot)) { + // 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; } - auto next_ue_harq_retx = ongoing_ues_ack_retxs.begin(); - while (next_ue_harq_retx != ongoing_ues_ack_retxs.end()) { - // TODO: Add a stopping condition in this loop, so next_ue won't iterate over all the UEs and HARQ-processes if - // there are no resources. - - auto& u = *ues.find(next_ue_harq_retx->ue_index); - auto* h_dl = next_ue_harq_retx->get_harq_process(); + 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); - if (next_ue_harq_retx->is_srb0) { - schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack); - } else { - // TODO: Change this into SRB1_retx. - schedule_srb(res_alloc, u, next_ue_harq_retx->is_srb0, h_dl, most_recent_tx_ack); - } + schedule_srb(res_alloc, u, next_ue_harq_retx.is_srb0, h_dl, most_recent_tx_ack); } - ++next_ue_harq_retx; } // Schedule SRB0 messages before SRB1, as we prioritize SRB0 over SRB1. - auto next_ue = pending_ues.begin(); - while (next_ue != pending_ues.end()) { + for (auto next_ue = pending_ues.begin(); next_ue != pending_ues.end();) { if (not next_ue->is_srb0) { ++next_ue; continue; @@ -98,8 +88,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) } // Keep SRB1 with lower priority than SRB0. - next_ue = pending_ues.begin(); - while (next_ue != pending_ues.end()) { + for (auto next_ue = pending_ues.begin(); next_ue != pending_ues.end();) { if (next_ue->is_srb0) { ++next_ue; continue; @@ -131,7 +120,7 @@ void ue_srb0_scheduler::run_slot(cell_resource_allocator& res_alloc) } } -void ue_srb0_scheduler::handle_dl_buffer_state_indication_srb(du_ue_index_t ue_index, bool is_srb0) +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}); } @@ -152,11 +141,11 @@ static slot_point get_next_srb_slot(const cell_configuration& cell_cfg, slot_poi return next_candidate_slot; } -bool ue_srb0_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) +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. @@ -165,29 +154,34 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, // \ref sched_ref_slot is the slot that we take as reference for the scheduler, which is processed when calling the // slot_indication(). - // \ref starting_sl 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: 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; - if (not cell_cfg.is_dl_enabled(sched_ref_slot)) { - return false; - } - + // 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_ack_slot) { + sched_ref_slot + max_dl_slots_ahead_sched <= most_recent_tx_ack_slots.value().most_recent_tx_slot) { return false; } // We keep track of the number of scheduling attempts for the given UE. - unsigned sched_attempts_cnt = 0; - slot_point next_slot = + unsigned sched_attempts_cnt = 0; + + // \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; - while (next_slot <= sched_ref_slot + max_dl_slots_ahead_sched) { + 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]; @@ -261,8 +255,6 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, ++sched_attempts_cnt; } - - next_slot = get_next_srb_slot(cell_cfg, next_slot); } // No resource found in UE's carriers and Search spaces. @@ -275,12 +267,12 @@ bool ue_srb0_scheduler::schedule_srb(cell_resource_allocator& res_alloc, return false; } -dl_harq_process* ue_srb0_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) +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; @@ -398,29 +390,33 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb0(ue& u, // 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, - is_retx); + 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_srb0_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) +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; @@ -551,37 +547,39 @@ dl_harq_process* ue_srb0_scheduler::schedule_srb1(ue& u, // Mark resources as occupied in the ResourceGrid. pdsch_alloc.dl_res_grid.fill(grant_info{scs, pdsch_td_cfg.symbols, ue_grant_crbs}); - fill_srb1_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); + 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_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, - bool is_retx) +void ue_fallback_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, + bool is_retx) { // Allocate DL HARQ. // NOTE: We do not multiplex the SRBO PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. @@ -631,30 +629,31 @@ void ue_srb0_scheduler::fill_srb0_grant(ue& u, h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); } -void ue_srb0_scheduler::fill_srb1_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) +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 srb1_dai = 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, - srb1_dai, + srb_dai, u.get_pcell().channel_state_manager().get_wideband_cqi(), pdsch_params.nof_layers, is_fallback); @@ -665,6 +664,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, // 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, @@ -686,7 +686,7 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, pdsch_time_res, k1, pucch_res_indicator, - srb1_dai, + srb_dai, mcs_idx, msg4_rv, h_dl); @@ -718,10 +718,11 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, // 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, false); + 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, @@ -748,18 +749,19 @@ void ue_srb0_scheduler::fill_srb1_grant(ue& u, 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 +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_srb0_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const +optional +ue_fallback_scheduler::get_most_recent_slot_tx(du_ue_index_t ue_idx) const { - optional most_recent_tx_ack_slot; + 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.get_harq_process()->slot_tx(); - slot_point h_dl_slot_ack = ue_proc.get_harq_process()->slot_ack(); + 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}); @@ -776,19 +778,20 @@ optional ue_srb0_scheduler::get_most_re return most_recent_tx_ack_slot; } -void ue_srb0_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) +void ue_fallback_scheduler::store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0) { - srsran_assert(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"); + 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_srb0_scheduler::update_ongoing_ue_retxs() +void ue_fallback_scheduler::update_ongoing_ue_retxs() { if (ongoing_ues_ack_retxs.empty()) { return; @@ -796,13 +799,14 @@ void ue_srb0_scheduler::update_ongoing_ue_retxs() // Only remove the {UE, HARQ-process} elements that have been retransmitted and positively acked. The rest of the // elements are potential candidate for retransmissions. - auto it_ue_harq = ongoing_ues_ack_retxs.begin(); - while (it_ue_harq != ongoing_ues_ack_retxs.end()) { + 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->get_harq_process(); + + 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; diff --git a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h similarity index 76% rename from lib/scheduler/ue_scheduling/ue_srb0_scheduler.h rename to lib/scheduler/ue_scheduling/ue_fallback_scheduler.h index ac615cc235..8579b924bc 100644 --- a/lib/scheduler/ue_scheduling/ue_srb0_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h @@ -21,14 +21,14 @@ 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 +class ue_fallback_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_); + 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. @@ -85,20 +85,21 @@ class ue_srb0_scheduler unsigned tbs_bytes, bool is_retx); - void fill_srb1_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); + 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; @@ -115,27 +116,19 @@ class ue_srb0_scheduler { 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_), ues(ues_) + ue_index(ue_idx), is_srb0(is_srb0_), h_dl(h_dl_) { - srsran_assert(ues.contains(ue_index), "UE not found in the UE repository"); - srsran_assert(h_dl_ == &(ues[ue_idx].get_pcell().harqs.dl_harq(h_dl_->id)), - "HARQ process not found among the UE HARQs"); } + 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_; } - // We make the access to the HARQ process is subject to the UE existence in the UE repository. - dl_harq_process* get_harq_process() const { return ues.contains(ue_index) ? h_dl : nullptr; } - - du_ue_index_t ue_index; - bool is_srb0; - - private: + du_ue_index_t ue_index; + bool is_srb0; dl_harq_process* h_dl; - ue_repository& ues; }; void store_harq_tx(du_ue_index_t ue_index, dl_harq_process* h_dl, bool is_srb0); @@ -167,7 +160,7 @@ class ue_srb0_scheduler coreset_configuration cs_cfg; /// Cache the UEs that are waiting for SRB HARQ processes to be ACKed or retransmitted. - std::list ongoing_ues_ack_retxs; + std::vector ongoing_ues_ack_retxs; std::vector dci_1_0_k1_values; diff --git a/lib/scheduler/ue_scheduling/ue_scheduler_impl.h b/lib/scheduler/ue_scheduling/ue_scheduler_impl.h index 954f8f9b00..63c720de9e 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.h +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.h @@ -18,9 +18,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" @@ -69,7 +69,7 @@ class ue_scheduler_impl final : public ue_scheduler uci_scheduler_impl uci_sched; /// SRB0 scheduler. - ue_srb0_scheduler srb0_sched; + ue_fallback_scheduler srb0_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), diff --git a/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp b/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp index 06bdc9e7f8..54f82b8016 100644 --- a/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp +++ b/tests/unittests/scheduler/common_scheduling/paging_scheduler_test.cpp @@ -12,7 +12,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 16f21ead61..8de775e9d4 100644 --- a/tests/unittests/scheduler/multiple_ue_sched_test.cpp +++ b/tests/unittests/scheduler/multiple_ue_sched_test.cpp @@ -10,7 +10,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" @@ -467,11 +467,11 @@ class scheduler_impl_tester uci_indication::uci_pdu::uci_pucch_f0_or_f1_pdu pucch_pdu{}; if (pucch.format == pucch_format::FORMAT_0) { pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_0.sr_bits) > 0; - // Auto ACK latest_harq_states. + // Auto ACK harqs. pucch_pdu.harqs.resize(pucch.format_0.harq_ack_nof_bits, mac_harq_ack_report_status::ack); } else { pucch_pdu.sr_detected = sr_nof_bits_to_uint(pucch.format_1.sr_bits) > 0; - // Auto ACK latest_harq_states. + // Auto ACK harqs. pucch_pdu.harqs.resize(pucch.format_1.harq_ack_nof_bits, mac_harq_ack_report_status::ack); } pucch_pdu.ul_sinr = 55; @@ -482,7 +482,7 @@ class scheduler_impl_tester uci_indication::uci_pdu::uci_pucch_f2_or_f3_or_f4_pdu pucch_pdu{}; pucch_pdu.sr_info.resize(sr_nof_bits_to_uint(pucch.format_2.sr_bits)); pucch_pdu.sr_info.fill(0, sr_nof_bits_to_uint(pucch.format_2.sr_bits), true); - // Auto ACK latest_harq_states. + // Auto ACK harqs. pucch_pdu.harqs.resize(pucch.format_2.harq_ack_nof_bits, mac_harq_ack_report_status::ack); if (pucch.csi_rep_cfg.has_value()) { pucch_pdu.csi.emplace(); diff --git a/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp index cbee0d5f71..f1edd3dbe5 100644 --- a/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp +++ b/tests/unittests/scheduler/test_utils/scheduler_test_suite.cpp @@ -161,7 +161,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: + 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/ue_scheduling/CMakeLists.txt b/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt index 8bae967317..f90ecf127b 100644 --- a/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt +++ b/tests/unittests/scheduler/ue_scheduling/CMakeLists.txt @@ -10,7 +10,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/srb0_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp similarity index 93% rename from tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp rename to tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp index 4fc098a9e4..0c5e18b9f5 100644 --- a/tests/unittests/scheduler/ue_scheduling/srb0_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp @@ -16,7 +16,7 @@ #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_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/dummy_test_components.h" #include "tests/unittests/scheduler/test_utils/scheduler_test_suite.h" @@ -90,7 +90,7 @@ struct test_bench { uci_allocator_impl uci_alloc{pucch_alloc}; ue_repository ue_db; ue_cell_grid_allocator ue_alloc; - ue_srb0_scheduler srb0_sched; + ue_fallback_scheduler fallback_sched; csi_rs_scheduler csi_rs_sched; explicit test_bench(const scheduler_expert_config& sched_cfg_, @@ -100,7 +100,7 @@ struct test_bench { 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), + 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); @@ -126,7 +126,7 @@ struct test_bench { } }; -class base_srb0_scheduler_tester +class base_fallback_tester { protected: slot_point current_slot{0, 0}; @@ -139,12 +139,12 @@ class base_srb0_scheduler_tester // 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_) : + base_fallback_tester(duplex_mode duplx_mode_) : duplx_mode(duplx_mode_), builder_params(test_builder_params(duplx_mode)) { } - ~base_srb0_scheduler_tester() + ~base_fallback_tester() { // Log pending allocations before finishing test. for (unsigned i = 0; i != max_k_value; ++i) { @@ -196,7 +196,7 @@ class base_srb0_scheduler_tester bench->csi_rs_sched.run_slot(bench->res_grid[0]); } - bench->srb0_sched.run_slot(bench->res_grid); + bench->fallback_sched.run_slot(bench->res_grid); result_logger.on_scheduler_result(bench->res_grid[0].result); @@ -283,7 +283,7 @@ class base_srb0_scheduler_tester 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->srb0_sched.handle_dl_buffer_state_indication_srb(ue_idx, is_srb0); + bench->fallback_sched.handle_dl_buffer_state_indication_srb(ue_idx, is_srb0); } unsigned get_pending_bytes(du_ue_index_t ue_idx) @@ -306,15 +306,15 @@ struct fallback_sched_test_params { duplex_mode duplx_mode; }; -class srb0_scheduler_tester : public base_srb0_scheduler_tester, public ::testing::TestWithParam +class fallback_scheduler_tester : public base_fallback_tester, public ::testing::TestWithParam { protected: - srb0_scheduler_tester() : base_srb0_scheduler_tester(GetParam().duplx_mode), params{GetParam()} {} + fallback_scheduler_tester() : base_fallback_tester(GetParam().duplx_mode), params{GetParam()} {} srb0_test_params params; }; -TEST_P(srb0_scheduler_tester, successfully_allocated_resources) +TEST_P(fallback_scheduler_tester, successfully_allocated_resources) { setup_sched(create_expert_config(2), create_custom_cell_config_request(params.k0)); // Add UE. @@ -346,7 +346,7 @@ TEST_P(srb0_scheduler_tester, successfully_allocated_resources) ASSERT_TRUE(is_ue_allocated_pdsch); } -TEST_P(srb0_scheduler_tester, failed_allocating_resources) +TEST_P(fallback_scheduler_tester, failed_allocating_resources) { setup_sched(create_expert_config(0), create_custom_cell_config_request(params.k0)); @@ -373,7 +373,7 @@ TEST_P(srb0_scheduler_tester, failed_allocating_resources) } } -TEST_P(srb0_scheduler_tester, test_large_srb0_buffer_size) +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. @@ -401,7 +401,7 @@ TEST_P(srb0_scheduler_tester, test_large_srb0_buffer_size) ASSERT_TRUE(is_ue_allocated_pdsch); } -TEST_P(srb0_scheduler_tester, test_srb0_buffer_size_exceeding_max_msg4_mcs_index) +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. @@ -419,7 +419,7 @@ TEST_P(srb0_scheduler_tester, test_srb0_buffer_size_exceeding_max_msg4_mcs_index } } -TEST_P(srb0_scheduler_tester, sanity_check_with_random_max_mcs_and_payload_size) +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)); @@ -435,13 +435,13 @@ TEST_P(srb0_scheduler_tester, sanity_check_with_random_max_mcs_and_payload_size) run_slot(); } -class srb0_scheduler_tdd_tester : public base_srb0_scheduler_tester, public ::testing::Test +class fallback_scheduler_tdd_tester : public base_fallback_tester, public ::testing::Test { protected: - srb0_scheduler_tdd_tester() : base_srb0_scheduler_tester(srsran::duplex_mode::TDD) {} + fallback_scheduler_tdd_tester() : base_fallback_tester(srsran::duplex_mode::TDD) {} }; -TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_appropriate_slots_in_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 = 1; @@ -479,7 +479,7 @@ TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_appropriate_slots_in_tdd) } } -TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) +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; @@ -519,20 +519,20 @@ TEST_F(srb0_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) } } -INSTANTIATE_TEST_SUITE_P(srb0_scheduler, - srb0_scheduler_tester, +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 srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, - public ::testing::TestWithParam +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; - srb0_scheduler_head_scheduling() : base_srb0_scheduler_tester(GetParam().duplx_mode) + fallback_scheduler_head_scheduling() : base_fallback_tester(GetParam().duplx_mode) { const unsigned k0 = 0; const sch_mcs_index max_msg4_mcs_index = 8; @@ -592,7 +592,7 @@ class srb0_scheduler_head_scheduling : public base_srb0_scheduler_tester, } }; -TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb_allocation_1_ue) +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 @@ -658,18 +658,17 @@ TEST_P(srb0_scheduler_head_scheduling, test_ahead_scheduling_for_srb_allocation_ } } -INSTANTIATE_TEST_SUITE_P(srb0_scheduler, - srb0_scheduler_head_scheduling, +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 srb0_scheduler_retx : public base_srb0_scheduler_tester, - public ::testing::TestWithParam +class fallback_scheduler_retx : public base_fallback_tester, public ::testing::TestWithParam { protected: - srb0_scheduler_retx() : base_srb0_scheduler_tester(GetParam().duplx_mode) + fallback_scheduler_retx() : base_fallback_tester(GetParam().duplx_mode) { const unsigned k0 = 0; const sch_mcs_index max_msg4_mcs_index = 8; @@ -684,7 +683,7 @@ class srb0_scheduler_retx : public base_srb0_scheduler_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_, srb0_scheduler_retx* parent_) : + 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(); @@ -791,7 +790,7 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, slot_point slot_update_srb_traffic; unsigned nof_packet_to_tx; harq_id_t ongoing_h_id = INVALID_HARQ_ID; - srb0_scheduler_retx* parent; + 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; @@ -809,7 +808,7 @@ class srb0_scheduler_retx : public base_srb0_scheduler_tester, std::vector ues_testers; }; -TEST_P(srb0_scheduler_retx, test_scheduling_for_srb_retransmissions_multi_ue) +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 @@ -840,18 +839,18 @@ TEST_P(srb0_scheduler_retx, test_scheduling_for_srb_retransmissions_multi_ue) } } -INSTANTIATE_TEST_SUITE_P(srb0_scheduler, - srb0_scheduler_retx, +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 srb0_scheduler_srb1_segmentation : public base_srb0_scheduler_tester, - public ::testing::TestWithParam +class fallback_scheduler_srb1_segmentation : public base_fallback_tester, + public ::testing::TestWithParam { protected: - srb0_scheduler_srb1_segmentation() : base_srb0_scheduler_tester(GetParam().duplx_mode) + fallback_scheduler_srb1_segmentation() : base_fallback_tester(GetParam().duplx_mode) { const unsigned k0 = 0; const sch_mcs_index max_msg4_mcs_index = 8; @@ -864,7 +863,7 @@ class srb0_scheduler_srb1_segmentation : public base_srb0_scheduler_tester, class ue_retx_tester { public: - ue_retx_tester(const cell_configuration& cell_cfg_, ue& test_ue_, srb0_scheduler_srb1_segmentation* parent_) : + 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(); @@ -940,7 +939,7 @@ class srb0_scheduler_srb1_segmentation : public base_srb0_scheduler_tester, ue& test_ue; slot_point slot_update_srb_traffic; unsigned nof_packet_to_tx; - srb0_scheduler_srb1_segmentation* parent; + fallback_scheduler_srb1_segmentation* parent; srslog::basic_logger& test_logger = srslog::fetch_basic_logger("TEST"); unsigned missing_retx = 0; @@ -956,7 +955,7 @@ class srb0_scheduler_srb1_segmentation : public base_srb0_scheduler_tester, std::vector ues_testers; }; -TEST_P(srb0_scheduler_srb1_segmentation, test_scheduling_srb1_segmentation) +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. @@ -982,8 +981,8 @@ TEST_P(srb0_scheduler_srb1_segmentation, test_scheduling_srb1_segmentation) } } -INSTANTIATE_TEST_SUITE_P(srb0_scheduler, - srb0_scheduler_srb1_segmentation, +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})); From 7b03b20476f593ea69adf8a8bd604e1cb21fec56 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 14 Mar 2024 16:03:17 +0100 Subject: [PATCH 71/77] sched: fix uninited var + remove unused function Signed-off-by: Carlo Galiotto --- lib/scheduler/ue_scheduling/harq_process.h | 2 +- .../ue_scheduling/ue_event_manager.cpp | 12 ++-- .../ue_scheduling/ue_event_manager.h | 9 +-- .../ue_scheduling/ue_fallback_scheduler.cpp | 64 +------------------ .../ue_scheduling/ue_fallback_scheduler.h | 14 ---- .../ue_pdsch_param_candidate_searcher.h | 2 +- .../ue_scheduling/ue_scheduler_impl.cpp | 5 +- .../ue_scheduling/ue_scheduler_impl.h | 6 +- .../ue_scheduling/fallback_scheduler_test.cpp | 12 ++-- 9 files changed, 26 insertions(+), 100 deletions(-) diff --git a/lib/scheduler/ue_scheduling/harq_process.h b/lib/scheduler/ue_scheduling/harq_process.h index 2936de31c5..4db5bbde51 100644 --- a/lib/scheduler/ue_scheduling/harq_process.h +++ b/lib/scheduler/ue_scheduling/harq_process.h @@ -270,7 +270,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; + bool is_fallback{false}; }; struct dl_ack_info_result { diff --git a/lib/scheduler/ue_scheduling/ue_event_manager.cpp b/lib/scheduler/ue_scheduling/ue_event_manager.cpp index ad479a00e1..cef9298a9f 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.cpp +++ b/lib/scheduler/ue_scheduling/ue_event_manager.cpp @@ -80,7 +80,7 @@ class ue_event_manager::ue_dl_buffer_occupancy_manager final : public scheduler_ u.handle_dl_buffer_state_indication(dl_bo); 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].srb0_sched->handle_dl_buffer_state_indication_srb( + 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); } @@ -632,16 +632,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_fallback_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 36dc0f6799..46a46d0b58 100644 --- a/lib/scheduler/ue_scheduling/ue_event_manager.h +++ b/lib/scheduler/ue_scheduling/ue_event_manager.h @@ -36,8 +36,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_fallback_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; @@ -113,8 +114,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_fallback_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 index 315b7a3709..43c9fc39eb 100644 --- a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp @@ -337,7 +337,7 @@ dl_harq_process* ue_fallback_scheduler::schedule_srb0(ue& u 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 ({})", + " allowed MCS index ({})", u.crnti, mcs_idx, expert_cfg.max_msg4_mcs); @@ -567,68 +567,6 @@ dl_harq_process* ue_fallback_scheduler::schedule_srb1(ue& u return h_dl; } -void ue_fallback_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, - bool is_retx) -{ - // Allocate DL HARQ. - // NOTE: We do not multiplex the SRBO PUCCH with existing PUCCH HARQs, thus both DAI and HARQ-ACK bit index are 0. - if (not is_retx) { - const bool is_fallback = true; - static constexpr uint8_t srb0_dai = 0; - 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(), - 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; - 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, not is_retx); - - if (not is_retx) { - // Set MAC logical channels to schedule in this PDU. - u.build_dl_fallback_transport_block_info( - msg.tb_list.emplace_back(), msg.pdsch_cfg.codewords[0].tb_size_bytes, true); - } - - // Save in HARQ the parameters set for this PDCCH and PDSCH PDUs. - h_dl.save_alloc_params(pdcch.dci.type, msg.pdsch_cfg); -} - void ue_fallback_scheduler::fill_srb_grant(ue& u, slot_point pdsch_slot, dl_harq_process& h_dl, diff --git a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h index 8579b924bc..880f8dd460 100644 --- a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h @@ -71,20 +71,6 @@ class ue_fallback_scheduler slot_point most_recent_ack_slot, dl_harq_process* h_dl_retx = nullptr); - 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, - bool is_retx); - void fill_srb_grant(ue& u, slot_point pdsch_slot, dl_harq_process& h_dl, 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 b6c45734e7..9264795e0a 100644 --- a/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h +++ b/lib/scheduler/ue_scheduling/ue_pdsch_param_candidate_searcher.h @@ -137,7 +137,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 ((not h.last_alloc_params().is_fallback) and 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_scheduler_impl.cpp b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp index 72928a04a0..606056accb 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.cpp @@ -30,7 +30,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); } @@ -155,7 +156,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 63c720de9e..580d2c35e8 100644 --- a/lib/scheduler/ue_scheduling/ue_scheduler_impl.h +++ b/lib/scheduler/ue_scheduling/ue_scheduler_impl.h @@ -68,13 +68,13 @@ class ue_scheduler_impl final : public ue_scheduler /// PUCCH scheduler. uci_scheduler_impl uci_sched; - /// SRB0 scheduler. - ue_fallback_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/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp index 0c5e18b9f5..57dc5bed29 100644 --- a/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp @@ -935,13 +935,13 @@ class fallback_scheduler_srb1_segmentation : public base_fallback_tester, 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; + 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; + 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; From f8faa95ce29e63f95f7d0da4c7d04eb709f97106 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 15 Mar 2024 11:30:44 +0100 Subject: [PATCH 72/77] sched: fix failing unittests and remove verbose logs Signed-off-by: Carlo Galiotto --- .../ue_scheduling/ue_fallback_scheduler.cpp | 17 ++++---- .../ue_scheduling/ue_fallback_scheduler.h | 11 +++-- .../ue_scheduling/fallback_scheduler_test.cpp | 42 ++++++++++++------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp index 43c9fc39eb..c9ea2c3a4d 100644 --- a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.cpp @@ -46,6 +46,9 @@ void ue_fallback_scheduler::run_slot(cell_resource_allocator& res_alloc) // 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; } @@ -109,7 +112,6 @@ void ue_fallback_scheduler::run_slot(cell_resource_allocator& res_alloc) 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)) { - logger.debug("rnti={}: Removing UE from list, as SRB1 buffer is empty.", u.crnti); 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 @@ -167,9 +169,6 @@ bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_allo return false; } - // We keep track of the number of scheduling attempts for the given UE. - unsigned sched_attempts_cnt = 0; - // \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. @@ -187,7 +186,7 @@ bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_allo 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_per_ue) { + if (sched_attempts_cnt >= max_sched_attempts) { return false; } @@ -221,7 +220,7 @@ bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_allo // 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.", + logger.debug("rnti={}: Failed to allocate PDSCH for {}. Cause: No space available in scheduler output list", u.crnti, is_srb0 ? "SRB0" : "SRB1"); return false; @@ -248,8 +247,6 @@ bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_allo if (not is_retx) { store_harq_tx(u.ue_index, candidate_h_dl, is_srb0); } - logger.debug( - "rnti={}: PDSCH space for SRB{} scheduled for slot:{}", u.crnti, is_srb0 ? "0" : "1", pdsch_alloc.slot); return true; } @@ -259,11 +256,11 @@ bool ue_fallback_scheduler::schedule_srb(cell_resource_allocator& res_allo // No resource found in UE's carriers and Search spaces. slot_point pdcch_slot = res_alloc[0].slot; - logger.debug("rnti={}: Not enough PDSCH space for {} message found in any of the slots:[{},{})", + 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); + pdcch_slot + max_dl_slots_ahead_sched + 1); return false; } diff --git a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h index 880f8dd460..9078908125 100644 --- a/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h +++ b/lib/scheduler/ue_scheduling/ue_fallback_scheduler.h @@ -129,10 +129,13 @@ class ue_fallback_scheduler // 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 attempt the scheduler can do while running through the nested loops over the PDSCH time - // allocation indices and the ahead slots. This is to avoid excessive long iterations in case of a large number of - // PDSCH time allocation indices. - const unsigned max_sched_attempts_per_ue = 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; diff --git a/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp index 57dc5bed29..9e88e2829e 100644 --- a/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp +++ b/tests/unittests/scheduler/ue_scheduling/fallback_scheduler_test.cpp @@ -180,7 +180,7 @@ class base_fallback_tester bench->pucch_alloc.slot_indication(current_slot); } - void run_slot(bool disabled_csi_rs = false) + void run_slot() { ++current_slot; @@ -192,9 +192,7 @@ class base_fallback_tester bench->pdcch_sch.slot_indication(current_slot); bench->pucch_alloc.slot_indication(current_slot); - if (not disabled_csi_rs) { - bench->csi_rs_sched.run_slot(bench->res_grid[0]); - } + bench->csi_rs_sched.run_slot(bench->res_grid[0]); bench->fallback_sched.run_slot(bench->res_grid); @@ -318,18 +316,19 @@ TEST_P(fallback_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)); + 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(to_du_ue_index(0), mac_srb0_sdu_size); + push_buffer_state_to_dl_ue(ue_idx, mac_srb0_sdu_size); - const unsigned exp_size = get_pending_bytes(to_du_ue_index(0)); + 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(to_du_ue_index(0)); + 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++) { @@ -344,6 +343,7 @@ TEST_P(fallback_scheduler_tester, successfully_allocated_resources) } 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) @@ -377,14 +377,15 @@ 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. - add_ue(to_rnti(0x4601), to_du_ue_index(0)); + 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(to_du_ue_index(0), mac_srb0_sdu_size); + push_buffer_state_to_dl_ue(ue_idx, mac_srb0_sdu_size); - const unsigned exp_size = get_pending_bytes(to_du_ue_index(0)); + const unsigned exp_size = get_pending_bytes(ue_idx); - const auto& test_ue = get_ue(to_du_ue_index(0)); + 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++) { @@ -399,6 +400,8 @@ TEST_P(fallback_scheduler_tester, test_large_srb0_buffer_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) @@ -424,7 +427,8 @@ TEST_P(fallback_scheduler_tester, sanity_check_with_random_max_mcs_and_payload_s 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)); + 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); @@ -444,7 +448,7 @@ class fallback_scheduler_tdd_tester : public base_fallback_tester, public ::test 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 = 1; + 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); @@ -477,6 +481,11 @@ TEST_F(fallback_scheduler_tdd_tester, test_allocation_in_appropriate_slots_in_td } } } + + 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) @@ -493,6 +502,9 @@ TEST_F(fallback_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) // 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; @@ -502,7 +514,7 @@ TEST_F(fallback_scheduler_tdd_tester, test_allocation_in_partial_slots_tdd) 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(true); + 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 From 9ff7ee24fe937e425894fdd6de3ed97c44b98d21 Mon Sep 17 00:00:00 2001 From: asaezper Date: Fri, 15 Mar 2024 15:48:44 +0100 Subject: [PATCH 73/77] memory_pool: TSAN explicitly synchronization --- CMakeLists.txt | 1 + .../fixed_size_memory_block_pool.h | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d691428c85..ee023b48a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,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/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h b/include/srsran/support/memory_pool/fixed_size_memory_block_pool.h index 599b71d22f..ee06bab575 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 @@ -10,6 +10,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" @@ -155,6 +159,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); } @@ -177,6 +184,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. @@ -198,7 +208,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() { @@ -266,7 +279,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) { From 6cc2635652492b3be863473ed90a0c81cb3d7868 Mon Sep 17 00:00:00 2001 From: qarlosalberto Date: Thu, 14 Mar 2024 15:45:23 +0100 Subject: [PATCH 74/77] ci: reorder conf viavi --- .gitlab/ci/e2e/.env | 2 +- .gitlab/ci/e2e/retina_request_test_mode.yml | 3 ++- .gitlab/ci/e2e/retina_request_zmq.yml | 1 - .gitlab/ci/e2e/retina_request_zmq_4x4_mimo.yml | 7 ++++--- tests/e2e/tests/iperf.py | 6 +++--- tests/e2e/tests/viavi.py | 18 ++++++++++++++++-- tests/e2e/tests/viavi/config.yml | 13 ------------- 7 files changed, 26 insertions(+), 24 deletions(-) diff --git a/.gitlab/ci/e2e/.env b/.gitlab/ci/e2e/.env index d47c6fb363..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.9 +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_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_zmq.yml b/.gitlab/ci/e2e/retina_request_zmq.yml index ec19cacd76..a8c3c2bdab 100644 --- a/.gitlab/ci/e2e/retina_request_zmq.yml +++ b/.gitlab/ci/e2e/retina_request_zmq.yml @@ -41,7 +41,6 @@ requests: 1 memory: requests: "8G" - limits: "8G" ephemeral-storage: requests: "15G" limits: "15G" 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/tests/e2e/tests/iperf.py b/tests/e2e/tests/iperf.py index 0bdc68b320..1941e4fa4d 100644 --- a/tests/e2e/tests/iperf.py +++ b/tests/e2e/tests/iperf.py @@ -477,9 +477,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 0d9676c978..9ac7053288 100644 --- a/tests/e2e/tests/viavi.py +++ b/tests/e2e/tests/viavi.py @@ -192,8 +192,22 @@ def _test_viavi( """ retina_data.test_config = { "gnb": { - "parameters": {"gnb_id": 1, "log_level": "warning", "pcap": False, "max_rb_size": max_rb_size}, - "templates": {"cell": str(Path(__file__).joinpath("../viavi/config.yml").resolve())}, + "parameters": { + "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": {"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 81df8206a1..be57eb19ab 100644 --- a/tests/e2e/tests/viavi/config.yml +++ b/tests/e2e/tests/viavi/config.yml @@ -7,18 +7,10 @@ # 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 @@ -32,9 +24,6 @@ cell_cfg: mcs_table: qam256 max_alloc_attempts: 8 max_pdschs_per_slot: 8 -{% if max_rb_size != -1 %} - max_rb_size: {{ max_rb_size }} -{% endif %} ul_common: max_ul_grants_per_slot: 16 max_pucchs_per_slot: 14 @@ -42,8 +31,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 From 3acaede5b474e461b12cb50b4b301a165e3f6be9 Mon Sep 17 00:00:00 2001 From: Pavel Harbanau Date: Fri, 15 Mar 2024 18:00:18 +0000 Subject: [PATCH 75/77] ofh: add RU emulator application --- tests/integrationtests/ofh/CMakeLists.txt | 11 + tests/integrationtests/ofh/helpers.h | 87 +++ .../ofh/ofh_integration_test.cpp | 87 +-- tests/integrationtests/ofh/ru_emulator.cpp | 679 ++++++++++++++++++ .../ofh/ru_emulator_appconfig.h | 63 ++ .../ofh/ru_emulator_cli11_schema.cpp | 104 +++ .../ofh/ru_emulator_cli11_schema.h | 22 + 7 files changed, 970 insertions(+), 83 deletions(-) create mode 100644 tests/integrationtests/ofh/helpers.h create mode 100644 tests/integrationtests/ofh/ru_emulator.cpp create mode 100644 tests/integrationtests/ofh/ru_emulator_appconfig.h create mode 100644 tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp create mode 100644 tests/integrationtests/ofh/ru_emulator_cli11_schema.h diff --git a/tests/integrationtests/ofh/CMakeLists.txt b/tests/integrationtests/ofh/CMakeLists.txt index 1494725933..be3fe1dcaa 100644 --- a/tests/integrationtests/ofh/CMakeLists.txt +++ b/tests/integrationtests/ofh/CMakeLists.txt @@ -12,3 +12,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..c03d8f6b2a --- /dev/null +++ b/tests/integrationtests/ofh/helpers.h @@ -0,0 +1,87 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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 f63a56e9ed..3b335b250f 100644 --- a/tests/integrationtests/ofh/ofh_integration_test.cpp +++ b/tests/integrationtests/ofh/ofh_integration_test.cpp @@ -9,6 +9,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" @@ -102,39 +103,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) { @@ -169,55 +137,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) { @@ -255,9 +174,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..1d77b1ba55 --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator.cpp @@ -0,0 +1,679 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "../../../lib/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..f45fb65763 --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_appconfig.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "srsran/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..f5d30396cf --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_cli11_schema.cpp @@ -0,0 +1,104 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "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..ec763464c5 --- /dev/null +++ b/tests/integrationtests/ofh/ru_emulator_cli11_schema.h @@ -0,0 +1,22 @@ +/* + * + * Copyright 2021-2024 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#pragma once + +#include "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 From f066a33f434e90316bed1d7c8f3574e20dde6416 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Fri, 15 Mar 2024 10:28:16 +0100 Subject: [PATCH 76/77] f1u: sync concurrent access to handlers in local bearer adapters This synchronizes access to `handler` pointer, used by DU UL executors to forward UL NRUP PDUs and reset by CU-UP executors upon removal of bearers. --- .../f1u_local_bearer_adapter.h | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) 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 5882513c66..a331e2fcf5 100644 --- a/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h +++ b/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h @@ -19,6 +19,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 @@ -31,12 +32,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(); @@ -49,6 +52,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; @@ -58,8 +62,11 @@ 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; + srs_cu_up::f1u_bearer_logger logger; + + srs_du::f1u_rx_pdu_handler* handler = nullptr; + std::mutex handler_mutex; + optional dl_tnl_info; }; @@ -81,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; @@ -94,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 From 1bfa904f58b6bc07a0234aae18a8e292a89e9247 Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Fri, 15 Mar 2024 10:28:49 +0100 Subject: [PATCH 77/77] f1u: remove unused adapter --- .../f1u/local_connector/f1u_local_bearer_adapter.h | 11 ----------- 1 file changed, 11 deletions(-) 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 a331e2fcf5..a880b3f22c 100644 --- a/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h +++ b/include/srsran/f1u/local_connector/f1u_local_bearer_adapter.h @@ -70,17 +70,6 @@ class f1u_dl_local_adapter : public srs_cu_up::f1u_tx_pdu_notifier 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 {} - -private: - srs_du::f1u_rx_pdu_handler* handler = nullptr; -}; - class f1u_ul_local_adapter : public srs_du::f1u_tx_pdu_notifier { public: